Farmer's Delight

Farmer's Delight

77M Downloads

1.18.2: Nourishment effect fails when the player would use more than 0.5 food points per second for any reason

James103 opened this issue ยท 6 comments

commented

Description
When FTB Ultimine is being used, the Nourishment effect fails to remove enough exhaustion from the player and the player still loses hunger even if their current food level is below 90%.

More generally, when the player would use more than one food point every 2 seconds, the Nourishment effect stops working completely and the player still starts losing hunger anyway.
For example, if the player is sprinting so fast so as to lose one food point per second, the Nourishment effect only reduces this to half a food point per second instead of stopping completely.

Caused by the float reduction = Math.min(exhaustion, 0.1F); limiter here:

float exhaustion = foodData.getExhaustionLevel();
float reduction = Math.min(exhaustion, 0.1F);
if (exhaustion > 0.0F) {
player.causeFoodExhaustion(-reduction);
}

Steps to reproduce:

  1. Install Farmer's Delight version 1.1.2 on a new Minecraft 1.18.2 + Forge 40.1.31 instance.
  2. Create a new world with cheats enabled.
  3. Run: /gamemode survival
  4. Run: /effect give @s farmersdelight:nourishment 999
  5. Run /effect give @s hunger 30 255 to simulate the exhaustion from mining with FTB Ultimine active.

Expected behavior:
The Nourishment effect should, at its peak, completely remove all exhaustion from the player regardless of how much exhaustion, therefore not letting the hunger level go down from exhaustion alone.
There could be a config setting to determine how much exhaustion per tick is removed from players that have the Nourishment effect.

Mod list:

  • Minecraft 1.18.2
  • Forge 40.1.31
  • Farmer's Delight 1.1.2
commented

I have two possible workarounds to this.

  1. Change the 0.1F to 4.0F in line 32 of NourishmentEffect.java as shown in the original post.
  2. Find a way to restore the original food level if it somehow decreased while the player was at full health and under the effects of Nourishment.

The full solution, which requires MinecraftForge/MinecraftForge#8405, would be to:

  1. Use the food API provided by the linked PR, once merged, to hook into the exhaustion events.
  2. In the event that fires when the player's exhaustion is about to increase, set exhaustion to 0 and cancel the event if the player is at full health / unable to heal and has the Nourishment effect.
  3. In the event that fires when the player is about to lose hunger due to exhaustion, cancel the event if the player is at full health / unable to heal and has the Nourishment effect.
commented

The main problem with the way exhaustion works at the moment is that I cannot directly set it a value, only add/subtract from it. Ideally, I would be setting it to zero every tick, but that isn't possible. So in order to not make the value become negative, I resort to this limiter.

I can take a look at it later. Though this kind of use case is too extreme for standard play, mods can sometimes exaggerate things a lot more. ๐Ÿ˜…

commented

It took me an embarassing amount of time to remember what my own logic did; your suggestion to change the decrease to 4.0F worked perfectly, and didn't run any risk of infinite negative values. ๐Ÿ˜…

It even worked against your explained reproduction steps! Exhaustion stays stuck to this value for the duration.
image

Thank you very much for the help. I'll add this fix to the upcoming version. ๐Ÿ‘

commented

Fixed on commit c3507c7.

commented

This bug, as exactly described by OP, still applies to...

Mod Version: 0.6.0 (Current Latest for 1.16.5)
MC Version: 1.16.5
Forge Version: Any

If someone could fix this for 1.16.5 that would be fantastic as I use Ore Excavator a lot when mining out large amounts of resources quickly. @vectorwing

commented

The fix, as posted above, increases the maximum covered exhaustion from the equivalent of half a food point per second to 20 food points per second (1 per tick), a 40x increase.

This, still, may not be enough in very extreme cases (FTB Ultimine + Unbreakable Netherite Pickaxe with Efficiency 50 + very high forge:reach_distance for example), as that can create exhaustion levels higher than 4 in a single tick, which is not fully covered by Nourishment and may still lead to loss of food points.

For a more effective fix, try removing the following code:

float exhaustion = foodData.getExhaustionLevel();
float reduction = Math.min(exhaustion, 4.0F);
if (exhaustion > 0.0F) {
player.causeFoodExhaustion(-reduction);
}

and replacing it with the following (untested).

float exhaustion = foodData.getExhaustionLevel();
if (exhaustion > 0.0F) {
	player.causeFoodExhaustion(-exhaustion);
}

This should work because setting x = x + (-x) (as is being done) is the same as x = 0 because x + (-x) = 0.
In other words, subtracting the player's current exhaustion from itself should always return 0.