Fast NBT

Fast NBT

加速各类NBT操作并提升游戏性能

性能

Fast NBT 让 Minecraft 不断执行的 NBT 操作变得更加廉价:读取标签、将其转换为游戏对象,以及从区块、数据包、方块状态和 ItemStack 中加载它们。

CompoundTag

  • 各种 get 方法。 在原版游戏中,它首先调用 contains 检查键是否存在,然后调用 get——两次 map 查找。Fast NBT 将这两个操作合并为一个,并应用内联,从而大幅提升查找速度。
  • 迭代。 使用 keySet 配合 get 进行迭代的方式被替换为同时遍历键和值的方法,因此写入和合并 compound 不再需要为每个条目执行一次查找。
  • 相关类。 其他相关类中使用这些 get 方法的操作也得到了优化。

ItemStack、方块状态和 NBT I/O

  • ItemStack 加载。 从 NBT 读取 ItemStack 时,直接从底层 map 中获取 tag 和 ForgeCaps,而不是用两次 contains 调用进行探测,并且 getOrCreateTagElement、getTagElement 和 removeTagKey 只需一次查找即可解析。
  • 方块状态。 NbtUtils.readBlockState 和 getDataVersion 直接读取 Name 和 Properties,而不是走原版的 contains / getString 链。
  • 区块区段调色板。 每个调色板条目通常都要经过完整的 DFU 编解码链——分发编解码器、注册表查找、每个属性一个 MapCodec,以及 DataResult / Either / Pair / Optional 分配——在每次区块加载和每次保存时都会发生。Fast NBT 直接从 map 中解析规范的 {Name, Properties} 标签。这是该模组中最大的收益。
  • NBT I/O。 无限制读取器——每次区块加载,以及 level.dat 和 playerdata——跳过一个其结果会被丢弃的字节核算遍历。

因此,收益出现在批量解码 NBT 的地方:世界和区块加载、服务器自动保存(会重新编码每个区块),以及携带带标签 ItemStack 的物品栏、方块实体和实体负载。调色板路径上更少的临时对象也意味着更少的 GC 压力。

这不是一个通用性能模组:它不触及 NBT 之外的任何内容,也无法帮助受磁盘或网络限制的工作负载。节省量随整合包解码 NBT 的量而扩展,在纯原版世界中最小。

配置

config/fastnbt.toml 在首次启动时生成,并为每个优化提供独立的开关:

enabled = true              # 以下所有内容的总开关

[features.itemStack]
    enabled = true

[features.blockState]
    enabled = true

[features.blockStateCodec]
    enabled = true

[features.nbtIo]
    enabled = true

CompoundTag 的重写没有单独的开关;全局 enabled 标志控制它们。

如何保持安全

  • 只有规范数据才走快速路径。 任何非规范数据都会被报告为解码错误,而不是进行猜测,并且 Properties 中方块没有的键会被忽略,与原版完全一致。对于区块调色板,调用方会将失败的条目变为空气,因此引用未安装模组方块的世界仍然可以加载——每个条目记录一行日志。
  • 编码永远不会被替换。 调色板优化只加速解码,因此保存的区块和网络数据包保持字节完全一致。
  • 注入冲突。 这些优化会替换或重定向原版方法,并且不提供非破坏性变体,因此如果另一个模组针对同一方法,最后应用的会生效。在发布大型整合包之前请先进行测试。

依据 GNU LGPL v3.0 或更高版本授权。