
在minecraft 1.19源码中,`damagesource.in_fire`与`damagesource.on_fire`虽同为火系伤害源且均绕过护甲、标记为火焰类型,但语义与触发场景截然不同:前者表示实体**处于火焰方块中**(如站在火堆里),后者表示实体**自身正在燃烧**(如被火把点燃后持续掉血)。
这两个常量定义于 net.minecraft.world.damagesource.DamageSource 类中:
public static final DamageSource IN_FIRE = (new DamageSource("inFire")).bypassArmor().setIsFire();
public static final DamageSource ON_FIRE = (new DamageSource("onFire")).bypassArmor().setIsFire();表面上看,二者行为高度相似——都调用 .bypassArmor()(无视护甲减免)和 .setIsFire()(启用火焰相关逻辑,如对凋灵造成伤害、触发防火药水效果等)。但其设计核心在于语义分离与上下文精确性,这是Minecraft死亡消息系统、成就判定及模组兼容性的关键基础。
✅ 实际使用场景差异
IN_FIRE:用于实体直接接触火焰方块(Fire Block)或熔岩时的即时伤害。
例如:玩家跳入火堆、僵尸卡在燃烧的草方块中、掉落进岩浆池边缘的火焰层。该伤害每秒触发一次,且仅当实体的碰撞箱完全或部分位于火焰方块内时生效。ON_FIRE:用于实体已被点燃(setOnFireFor(int ticks))后,每刻(20 ticks/秒)持续承受的燃烧伤害。
例如:被烈焰人火球击中、手持打火石点燃自己、受“着火”状态效果影响。此伤害独立于环境方块,即使玩家瞬移出火堆,只要燃烧倒计时未结束,ON_FIRE 仍会持续造成伤害。
? 验证依据:死亡消息与日志表现
Minecraft通过 DamageSource.getLocalizedDeathMessage(LivingEntity) 方法生成死亡提示,而 IN_FIRE 与 ON_FIRE 对应不同本地化键:
- inFire → "death.attack.inFire" → "Player was burnt to a crisp"`
- onFire → "death.attack.onFire" → "Player went up in flames"`
你可以在 en_us.json 资源文件中查到这两条独立翻译,证实它们面向不同事件语义。若合并为同一 DamageSource,则无法实现精准死亡反馈——比如“在火里烤焦”和“自燃成灰”在游戏叙事中具有明确区分。
⚠️ 注意事项与开发建议
- 模组开发中切勿混用:若你的模组添加自定义火焰伤害逻辑,请根据实际触发条件选择对应 DamageSource。误用 ON_FIRE 替代 IN_FIRE 可能导致死亡消息错误,或与防火药水、抗火附魔等机制产生意外交互。
- 服务端同步安全:二者均为 public static final 常量,在多线程环境下安全共享,无需额外同步。
- 扩展性考量:MCP(Mod Coder Pack)或Yarn映射中,此类命名规范(inXxx vs onXxx)是Mojang惯用模式,类似还有 IN_WALL / WALL(挤压伤害)、FALLING_BLOCK / FALLING_ANVIL(下落物细分)等,体现其精细化伤害建模哲学。
简言之,IN_FIRE 是环境致害,ON_FIRE 是状态致害;名称差异不是冗余,而是Minecraft底层伤害系统语义严谨性的直接体现。理解这一点,是读懂原版逻辑、编写健壮模组的基础。










