玩家数据持久化

基本信息

属性 值
NBT 标签名 Nutrients
数据格式 NBTTagCompound 内嵌一个 NBTTagCompound,key 是 Nutrient name,value 是 float
触发点 Forge 默认的 Player persistent NBT 序列化(PlayerEvent.SaveToFile / PlayerEvent.LoadFromFile 等的 entityData)

功能

通过 Forge 默认的玩家持久化机制(Entity.playerData)保存与恢复每个 Nutrient 的值。

写入

public static void saveForPlayer(EntityPlayer player, NBTTagCompound tagCompound) {
    NBTTagCompound playerData = new NBTTagCompound();
    for (Nutrient nutrient : NutrientList.get()) {
        float value = NutritionManager.instance().get(player, nutrient);
        playerData.setFloat(nutrient.name, value);
    }
    tagCompound.setTag(NBT_NUTRIENT_DATA, playerData);
}

只序列化 NutrientList.get() 中存在的 Nutrient。删除 Nutrient 配置后,旧玩家 NBT 中的遗留字段会被忽略。

读取

public static void initializeForPlayer(EntityPlayer player, NBTTagCompound tagCompound) {
    if (tagCompound.hasKey(NBT_NUTRIENT_DATA)) {
        NBTTagCompound nutrientTag = tagCompound.getCompoundTag(NBT_NUTRIENT_DATA);
        Map<Nutrient, Float> values = new HashMap<>();

        for (Nutrient nutrient : NutrientList.get()) {
            float value;
            if (nutrientTag.hasKey(nutrient.name)) {
                value = nutrientTag.getFloat(nutrient.name);
            } else {
                value = (float) NutritionConfig.nutrition.startingNutrition;
            }
            values.put(nutrient, value);
        }

        // Do not sync here since the client is not yet ready to receive it.
        // It will be synced later in EventPlayerJoinWorld.
        NutritionManager.instance().setAll(player, values, false);
    }
}

行为

  • 玩家 NBT 中没有 Nutrients 字段 → 跳过(玩家首次进服)
  • 某个 Nutrient 在 NBT 里没有记录(mod 更新后新增 Nutrient) → 用 startingNutrition(默认 50)初始化
  • setAll(player, values, false):第三个参数 sync=false 显式禁止此刻发包,因为"客户端尚未准备好接收";后续 EventPlayerJoinWorld 会触发 SPacketNutrients.send(player)

相关条目