营养衰减机制
基本信息
| 属性 | 值 |
|---|---|
| 触发位置 | EventWorldTick.serverTickEvent(TickEvent.WorldTickEvent,只在 Phase.END + Side.SERVER) |
| 触发频率 | 每个服务端 tick |
| 核心类 | ca.wescook.nutrition.events.EventWorldTick |
| 默认开启 | NutritionConfig.decay.enable = true |
功能
跟踪玩家饥饿条(player.getFoodStats().getFoodLevel())下降,按 Nutrient 自己的 decay 倍率线性扣减每个 Nutrient 的值。playerFoodLevels Map 缓存上一 tick 的饥饿值用于 diff 计算。
触发条件
if (foodLevelOld != null && foodLevelNew < foodLevelOld) {
int difference = foodLevelOld - foodLevelNew;
calculateDecay(player, difference);
}
只有饥饿下降才衰减(吃饭时饥饿上涨不走这条路径,由 EventEatFood 反向累加营养)。
衰减公式
float decay = (float) (difference * 0.075 * nutrient.decay);
float newValue = MathHelper.clamp_float(manager.get(player, nutrient) - decay, 0, 100);
difference:本 tick 饥饿下降值(饥饿图标格数)0.075:硬编码基础衰减率nutrient.decay:单个 Nutrient 的衰减倍率(默认NutritionConfig.decay.decayMultiplier = 1.0,范围 -100…100,可被 per-nutrient JSON 覆盖)- 结果钳制到
[0, 100]
非食物饥饿变化处理
针对 IC2 food can、talisman of nourishment、healing axe 等直接修改饥饿的物品,EventEatFood.onFoodStatsChanged 通过 pushNonFoodHungerChange 把饥饿变化压入栈,EventWorldTick.handleNonFoodHungerChanges 每 tick 检查:
if (hungerChange > 0) {
float amountToChange = NutrientUtils.getNutrientValue(
hungerChange, NutrientList.get().size());
NutritionManager.instance().normalize(player, 50.0f, amountToChange);
}
normalize(player, 50.0f, amountToChange) 把所有 Nutrient 朝 50 线性收敛,幅度 amountToChange,模拟"吃杂食不增不减"。
批量更新优化
calculateDecay 只把有变化的 Nutrient 装入 newValues Map 后调 manager.setAll(player, newValues),目的是把同 tick 内多次衰减合并为一个网络包。
相关条目
- 配置文件 -
decay.enable/decayMultiplier - Nutrient JSON 配置格式 - 每个 Nutrient 的
decay字段 - 食物营养计算公式 - 吃饭时正向累加
getNutrientValue