Skip to content

fix: 防止子弹生成数据中的空资源 ID 导致服务端崩溃 - #736

Open
0xMashiro wants to merge 1 commit into
MCModderAnchor:1.20.1from
0xMashiro:fix/bullet-spawn-null-resource-ids
Open

0xMashiro wants to merge 1 commit into
MCModderAnchor:1.20.1from
0xMashiro:fix/bullet-spawn-null-resource-ids

Conversation

@0xMashiro

@0xMashiro 0xMashiro commented Aug 20, 2026 •

Copy link
Copy Markdown

变更原因

生产环境中出现了一次由 TaCZ 子弹实体生成数据编码触发的服务端主线程崩溃。

现场环境:

  • Minecraft 1.20.1
  • Forge 47.4.0
  • TaCZ 1.1.7-hotfix2
  • Java 17

事故发生在玩家移动后重新建立实体追踪关系时。服务端尝试向客户端发送一枚 EntityKineticBullet 的生成数据包,其中 gunId 为 null,最终在资源 ID 序列化阶段抛出 NullPointerException:

FriendlyByteBuf.writeResourceLocation
EntityKineticBullet.writeSpawnData(EntityKineticBullet.java:609)
PlayMessages$SpawnEntity.encode
ChunkMap$TrackedEntity.updatePlayer

该异常由服务端主线程向上抛出并导致实例停止。现场没有 OOM 证据;玩家移动只触发了实体追踪更新,并不是空字段的创建来源。

进一步检查发现,EntityKineticBullet(EntityType, Level) 会由实体类型工厂调用。该构造路径为 ammoId 设置了字段默认值,但 gunId 和 gunDisplayId 保持 Java 默认值 null。如果附属 Mod 或其他运行时代码通过实体工厂创建子弹并绕过正常开枪构造器,该实体在进入追踪范围后即可触发上述崩溃。

同一代码路径在 1.1.8-hotfix 中仍然存在。

修改内容

  • 为 gunId 和 gunDisplayId 增加与项目现有 ammoId 相同风格的字段默认值。
  • 在完整构造器中使用 TaCZ 已有的哨兵资源 ID 归一化空参数。
  • 在 writeSpawnData 中增加最终空值保护,覆盖字段被第三方 Mixin、反射或异常路径重新写为 null 的情况。
  • 同时保护 ammoId、gunId 和 gunDisplayId 三个生成数据包中的 ResourceLocation 字段。

使用的回退值均来自现有 DefaultAssets:

ammoId       -> EMPTY_AMMO_ID
gunId        -> EMPTY_GUN_ID
gunDisplayId -> DEFAULT_GUN_DISPLAY_ID

兼容性

  • 不改变生成数据包的字段数量、顺序或数据类型。
  • 正常开枪构造路径中的非空资源 ID 保持不变。
  • 不新增事件、配置、依赖或网络消息。
  • 客户端和服务端协议保持兼容。

复现建议

由于 tacz:bullet 注册为 noSummon(),不能通过普通 /summon 命令可靠复现。可在开发测试代码中调用:

EntityKineticBullet bullet = EntityKineticBullet.TYPE.create(serverLevel);
serverLevel.addFreshEntity(bullet);

随后让玩家进入该实体的追踪范围。修改前会在 writeSpawnData 中对空 gunId 编码并导致 NPE;修改后会使用安全哨兵 ID 完成编码。

验证状态

  • git diff --check:通过。
  • 已核对修改方式与项目现有 DefaultAssets、Objects.requireNonNullElse 用法一致。
  • 已经将编译后的 hotfix 版本在自己的服务器上线,运行24小时无问题。

风险评估

本修改只影响异常空值路径。对于正常子弹实体,序列化结果与修改前完全一致;对于数据不完整的实体,行为从“服务端主线程崩溃”降级为“使用 TaCZ 已定义的空/默认资源 ID 完成同步”。

@0xMashiro
0xMashiro marked this pull request as ready for review August 21, 2026 02:42
@0xMashiro

Copy link
Copy Markdown
Author

已经将编译后的 hotfix 版本在自己的服务器上线,运行24小时无问题。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant