营养衰减机制

基本信息

属性 值
触发位置 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 内多次衰减合并为一个网络包。

相关条目