package net.minecraft.world.food; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.Mth; import net.minecraft.world.Difficulty; import net.minecraft.world.level.GameRules; public class FoodData { private static final int DEFAULT_TICK_TIMER = 0; private static final float DEFAULT_EXHAUSTION_LEVEL = 0.0F; private int foodLevel = 20; private float saturationLevel = 5.0F; private float exhaustionLevel; private int tickTimer; private void add(int foodLevel, float saturationLevel) { this.foodLevel = Mth.clamp(foodLevel + this.foodLevel, 0, 20); this.saturationLevel = Mth.clamp(saturationLevel + this.saturationLevel, 0.0F, (float)this.foodLevel); } /** * Add food stats. */ public void eat(int foodLevelModifier, float saturationLevelModifier) { this.add(foodLevelModifier, FoodConstants.saturationByModifier(foodLevelModifier, saturationLevelModifier)); } public void eat(FoodProperties foodProperties) { this.add(foodProperties.nutrition(), foodProperties.saturation()); } public void tick(ServerPlayer player) { ServerLevel serverLevel = player.serverLevel(); Difficulty difficulty = serverLevel.getDifficulty(); if (this.exhaustionLevel > 4.0F) { this.exhaustionLevel -= 4.0F; if (this.saturationLevel > 0.0F) { this.saturationLevel = Math.max(this.saturationLevel - 1.0F, 0.0F); } else if (difficulty != Difficulty.PEACEFUL) { this.foodLevel = Math.max(this.foodLevel - 1, 0); } } boolean bl = serverLevel.getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION); if (bl && this.saturationLevel > 0.0F && player.isHurt() && this.foodLevel >= 20) { this.tickTimer++; if (this.tickTimer >= 10) { float f = Math.min(this.saturationLevel, 6.0F); player.heal(f / 6.0F); this.addExhaustion(f); this.tickTimer = 0; } } else if (bl && this.foodLevel >= 18 && player.isHurt()) { this.tickTimer++; if (this.tickTimer >= 80) { player.heal(1.0F); this.addExhaustion(6.0F); this.tickTimer = 0; } } else if (this.foodLevel <= 0) { this.tickTimer++; if (this.tickTimer >= 80) { if (player.getHealth() > 10.0F || difficulty == Difficulty.HARD || player.getHealth() > 1.0F && difficulty == Difficulty.NORMAL) { player.hurtServer(serverLevel, player.damageSources().starve(), 1.0F); } this.tickTimer = 0; } } else { this.tickTimer = 0; } } /** * Reads the food data for the player. */ public void readAdditionalSaveData(CompoundTag compoundTag) { this.foodLevel = compoundTag.getIntOr("foodLevel", 20); this.tickTimer = compoundTag.getIntOr("foodTickTimer", 0); this.saturationLevel = compoundTag.getFloatOr("foodSaturationLevel", 5.0F); this.exhaustionLevel = compoundTag.getFloatOr("foodExhaustionLevel", 0.0F); } /** * Writes the food data for the player. */ public void addAdditionalSaveData(CompoundTag compoundTag) { compoundTag.putInt("foodLevel", this.foodLevel); compoundTag.putInt("foodTickTimer", this.tickTimer); compoundTag.putFloat("foodSaturationLevel", this.saturationLevel); compoundTag.putFloat("foodExhaustionLevel", this.exhaustionLevel); } /** * Get the player's food level. */ public int getFoodLevel() { return this.foodLevel; } /** * Get whether the player must eat food. */ public boolean needsFood() { return this.foodLevel < 20; } /** * Adds input to {@code foodExhaustionLevel} to a max of 40. */ public void addExhaustion(float exhaustion) { this.exhaustionLevel = Math.min(this.exhaustionLevel + exhaustion, 40.0F); } /** * Get the player's food saturation level. */ public float getSaturationLevel() { return this.saturationLevel; } public void setFoodLevel(int foodLevel) { this.foodLevel = foodLevel; } public void setSaturation(float saturationLevel) { this.saturationLevel = saturationLevel; } }