ToroHealth Damage Indicators

[!INFO] Git Commit: 845aa04 | Updated: 2026-10-01

modid:torohealthmod(来自 ToroHealthMod.java:19 public static final String MODID = "torohealthmod";,并由 @Mod(modid = ToroHealthMod.MODID) 在 ToroHealthMod.java:12-16 引用) 显示名: gradle.properties 的 modName = ToroHealth Damage Indicators; @Mod(name = Tags.MODNAME)(ToroHealthMod.java:14,值由 gradle token 注入) mcmod.info 描述: “Displays damage indicators and health bars for all entities.” 网址: http://torocraft.net/

现状:纯客户端的伤害数字飘字,零方块 / 物品 / 实体

9 个 Java 文件里:

项目 数量
方块 / 物品 / 实体 / TileEntity 0 / 0 / 0 / 0
指令 0
配置项 5(全在 CATEGORY_GENERAL)
实体渲染的粒子类型 1(DamageParticles,一个 EntityFX 子类,不是注册的 EntityFX 实体 ID)
服务端逻辑 0

⚠️ 描述与实现不符:没有血条

mcmod.info 写的是 “Displays damage indicators and health bars for all entities”, 但源码里不存在任何血条(health bar)渲染代码。DamageParticles.renderParticle 用的是 mc.fontRenderer.drawStringWithShadow 画纯数字(DamageParticles.java:117), 没有任何横向条形绘制、没有 RenderGameOverlayEvent 订阅、没有 GuiIngameMenu 之类挂钩。 唯一的事件订阅是 LivingEvent.LivingUpdateEvent(ToroHealthEventHandler.java:14-15)。

引用该描述会让人以为它能在实体头顶显示血量条——它做不到。

纯客户端 mod

  • preInit 时若 Side.SERVER,只打一条日志说明"装在服务端没有意义,可以安全移除" (ToroHealthMod.java:26-30)
  • 唯一的 mixin(注入 EntityLivingBase 血量快照)只在客户端加载 (MixinLoadingPlugin.getMixins 里 FMLLaunchHandler.side().isClient() 判断, MixinLoadingPlugin.java:45-51)
  • dependencies.gradle 只有一个 runtimeOnlyNonPublishable 的 Waila(运行时非发布依赖, 仅用于开发期),没有真正的必需前置——ToroHealth 可以单独装

实现机制

不靠 Forge 事件拿伤害量,而是客户端自己逐 tick 快照血量再算差值:

  1. early mixin 给 EntityLivingBase 注入两个 @Unique 字段 torohealth$prevHealth / torohealth$prevMaxHealth,初值 -1,并实现 EntityLivingBaseExt 接口暴露读写 (mixins/early/MixinEntityLivingBase.java:12-36、mixins/interfaces/EntityLivingBaseExt.java)
  2. LivingUpdateEvent(LOW 优先级,仅 isRemote)比较 floor 后的当前血量与快照, 不同则更新快照并用 prevHealth - health 作为伤害量生成粒子 (ToroHealthEventHandler.java:26-38)

这个设计有个刻意的排除逻辑(ToroHealthEventHandler.java:32-35):当最大血量也变了时 不生成粒子。源码注释点名这是为了跳过"外部 mod 在实体生成瞬间改血量"的情况, 举例是 EnderZoo 的 health modifier。

游戏内内容 / 机制列表

  • 伤害数字粒子 - 12 tick 生命期、先放大后缩小的 3D 飘字,伤害红 / 回血绿,64 格外与遮挡时不生成
  • 配置项 - 5 个 general 分类项;Show Damage Particles 通过注册/注销事件处理器实现热开关

本 mod 没有的内容(源码核实)

src/main/java 下 registerBlock、registerItem、registerEntity、registerTileEntity、 addCommand、keyBinding、Enchantment、Potion 各 0 命中; src/main/resources 只有 3 个文件(mcmod.info + 两个 mixin json),无贴图 / 模型 / 语言文件。

mixins.torohealthmod.json 与 mixins.torohealthmod.early.json 的 mixins / client / server 三个数组全为空(无 package 字段的常规版里 package 也未声明)。实际加载的 mixin 列表由 MixinLoadingPlugin 以编程方式给出, 走 GTNH 的 IEarlyMixinLoader 通道,不依赖 json 里的数组。

已知源码问题

  • 描述宣称 health bars 但无实现(见上)。
  • ConfigurationHandler 构造函数不保存 path:ConfigurationHandler.java:25-30 只在 config == null 时才 new Configuration(path);若 preInit 被触发两次(不会发生)第二次是空操作。 更实际的问题是 eventHandler 字段非 final 且只在 showDamageParticles == true 分支赋值 (ConfigurationHandler.java:41-45),首次进入 false 分支时 unregister(null) 不会被调用—— 这点是对的,但依赖了 != null 判断,属隐式契约。
  • 颜色映射漏 WHITE(ConfigurationHandler.java:70-81),靠 default 兜底,见 配置项。
  • damage < 0 判定与 Math.abs 显示组合有歧义:若某 tick 净效果恰好为 0 伤害, prevHealth - health == 0,会被判成 damageColor(红)并显示数字 0 (DamageParticles.java:36-37)。源码未过滤 damage == 0。
  • 距离阈值魔法数:64D * 64D 与 25D 无命名、无注释(DamageParticles.java:62、71), 且一个是"写成平方形式"、一个是"直接写平方",风格不一致,容易被后人误读成 64 格与 25 格。
  • mixins.torohealthmod.json 缺 package 字段且数组全空,属 GTNH 项目模板残留, 实际不被使用。