基本信息
我的世界Java版本
平台
运行环境
分类

搬运团队
搬运资源声明
对于可进行 JAR 文件搬运的许可证,我们提供站内下载服务;其他资源会跳转到原帖下载。资源更新可能不及时,建议前往资源内提供的原帖链接下载最新版本。
详情信息
更新日志
2.12.0 - 发布候选版 1
大家好!这是迄今为止 NBTAPI 最重大的一次更新,因此我决定在正式发布 2.12.0 版本前,先推出一个 Minecraft 风格的发布候选版(理想情况下无需任何改动即可正式发布)。本次版本共包含 84 次提交,占过去 6–7 年全部 563 次提交的近 15%(竟达 15%?!),请系好安全带,迎接这些变更。
(顺便温馨提醒:支持本项目的开发者将不胜感激,尤其当你使用此 API 开发付费插件时 😅)
主要变更
- 新增对 Mojang 映射服务器(Paper-Mojmap / Paper 开发模式)的支持
- 新增对 Folia 的支持
- 对
NBT.get和NBT.modify方法进行了大幅性能优化(详见下文) - 预览功能:接口代理(Interface Proxies),无需编写代码即可访问 NBT(详见下文)
- 实体(Entity)与方块实体(BlockEntity)的修改操作现已改为原子性操作,速度更快,避免常见陷阱
- 实体与方块实体的只读访问大幅提速,仅需获取一次标签(tag)即可
- 新增
resolveOrNull/resolveOrDefault/resolveCompound/resolveOrCreateCompound方法。这些方法接受以英文句点.分隔的路径字符串(如tag.othertag.key)(示例见下文)
值得关注的变更
- 将 bStats 从 1.x 版本升级至 3.0.2
- 减少 Gson 相关日志输出
- 新增
long[]类型支持(含setLongArray/getLongArray方法,适用于 1.16+) - 在错误信息中包含 NBTAPI 版本号
- 移除了
functional-annotations依赖项(此前部分用户可能注意到该依赖被遮蔽) - 修复
NBTFile.saveTo总是保存根标签而非传入标签的问题 - 在若干关键位置添加了
@Nullable注解 - 当
NBT.modify执行完毕后标签为空时,该标签将从物品中彻底移除,而非保存空标签{} - 防止对
NBT.get/NBT.modify方法的误用 - 新增
set(String key, T value, NBTHandler<T> handler)方法,可通过指定处理器写入自定义数据 - 新增
get(String key, NBTHandler<T> handler)方法,可通过指定处理器读取自定义数据
其他变更 / 文档更新
- @dependabot 在 https://github.com/tr7zw/Item-NBT-API/pull/229 中将 license-maven-plugin 从 2.0.1 升级至 2.1.0
- @dependabot 在 https://github.com/tr7zw/Item-NBT-API/pull/232 中将 maven-shade-plugin 从 3.4.1 升级至 3.5.0
- @dependabot 在 https://github.com/tr7zw/Item-NBT-API/pull/235 中将 license-maven-plugin 从 2.1.0 升级至 2.2.0
- @tr7zw 在 https://github.com/tr7zw/Item-NBT-API/pull/236 中实现只读访问优化
- @BlackBaroness 在 https://github.com/tr7zw/Item-NBT-API/pull/237 中更新“设置玩家头颅皮肤”文档
- @BlackBaroness 在 https://github.com/tr7zw/Item-NBT-API/pull/238 中修正文档中的少量英文表述错误
- @U5B 在 https://github.com/tr7zw/Item-NBT-API/pull/242 中新增荣誉插件列表提及
- @SoSeDiK 在 https://github.com/tr7zw/Item-NBT-API/pull/243 中修复 Folia 检测及方块实体的
NBT#modify方法
性能表现
本次发布在底层进行了大量性能优化,主要针对 NBT.get 和 NBT.modify 方法在物品栈(ItemStack)、实体(Entity)及方块实体(BlockEntity)上的表现。强烈建议各位尽快将现有 NBTItem / NBTEntity / NBTTileEntity 代码迁移至这些新方法。
所有基准测试均在本地 PC 的 Paper-171 上运行,对比版本为 2.11.3 与 2.12.0-RC1。数值表示每秒可完成的测试用例执行次数(JVM 在测试前已进行充分预热)。由于仅执行单次测试,实际误差范围约为 ±5%,数值仅供粗略参考。
物品栈(ItemStack)
运行代码链接。旧版测试使用 new NBTItem,新版测试则使用 NBT 类。两组测试均读写相同数据,仅语法不同!
基于 NMS 的物品栈:
- LegacyGet:880.620 → 909.369(提升约 3%)
- NBT.get:884.326 → 4,214,210(提升约 376%)
- LegacySet:762.453 → 804.732(提升约 5%)
- NBT.modify:298.238 → 1,781,667(提升约 497%)
纯 Bukkit 物品栈:
- LegacyGet:215.992 → 202.413(下降约 6%)
- NBT.get:223.998 → 649.626(提升约 190%)
- LegacySet:229.485 → 239.910(提升约 4%)
- NBT.modify:166.048 → 567.107(提升 241%)
简而言之:切换至新的 NBT.get / NBT.modify 方法后,性能至少提升 200%。
持久化数据容器(Persistent Data Container)
为更清晰地对比 NBTAPI 与 Spigot 原生持久化数据容器(PDC)在物品数据存储方面的性能,我也一并进行了测试与对比。测试环境仍为 Paper-171 下的 2.12.0-RC1。在基于 NMS 的物品栈上,常规 PDC 的读取速度与 NBT.get 基本持平;仅当将 NamespacedKey 缓存于 final 类字段时,PDC 才略微领先。而数据写入(尤其在纯 Bukkit 物品上)则慢得多——但即便如此,仍可轻松达到每秒 50 万次以上,因此实际影响微乎其微(更何况 NBTAPI 提供了更灵活的 API 及对 1.14 之前版本的支持)。
解析方法(Resolve Methods)
为简化对深层嵌套 NBT 的操作,新增解析方法,可直接获取或操作对应标签。
复合标签(Compound)路径以英文句点 . 分隔。若键名本身需包含句点 .,可用反斜杠 \ 进行转义。
示例:
// 将 foo/bar/baz/test 设为 42
nbt.resolveOrCreateCompound("foo.bar.baz").setInteger("test", 42);
// 获取刚刚设置的值,若不存在则返回 0
nbt.resolveOrDefault("foo.bar.baz.test", 0);
// 获取刚刚设置的值,若不存在则返回 null
nbt.resolveOrNull("foo.bar.baz.test", int.class);
// 键名含句点的示例:设置键 foo/some.key/baz/other
nbt.resolveOrCreateCompound("foo.some\\.key.baz").setInteger("other", 123);
// 获取标签,若不存在则返回 null
nbt.resolveCompound("some.nested.key");
接口代理(Interface Proxies)
本功能为预览性质,API 可能随反馈与开发进展而调整。它允许你定义一个普通接口(含常规方法与默认方法),NBTAPI 将自动为该接口生成实现类,并将 NBT 标签封装其中。
以 has / get / set 开头的方法将被自动映射为对应操作:
public boolean hasKills(); → return nbt.hasTag("kills");
public void setKills(int amount); → nbt.setInteger("kills", amount);
public int getKills(); → return nbt.getInteger("kills");
接口内定义的默认方法(如以下示例)同样受支持:
public default void addKill() {
setKills(getKills() + 1);
}
此外,getter 方法也可返回另一个同样继承 NBTProxy 的接口。
如需支持 ItemStack 等其他数据类型,可通过覆盖 init 方法(设为默认方法),调用 registerHandler 注册处理器。例如:
@Override
default void init() {
registerHandler(ItemStack.class, NBTHandlers.ITEM_STACK);
}
要使用你的接口,只需如下调用 NBT.modify 或 NBT.readNbt:
NBT.modify(item, TestInterface.class, ti -> {
ti.addKill();
// 或调用你接口中的任意其他方法
});
// 此实例仅支持只读方法。调用任何 setter 方法将抛出异常
TestInterface yourInterface = NBT.readNbt(item, TestInterface.class);
yourInterface.getKills();
完整示例请参阅 内置启动测试 或 正在开发中的 NBT-ItemMeta 代理。欢迎随时在 Discord 中提问交流。
新贡献者
- @BlackBaroness 首次贡献见 https://github.com/tr7zw/Item-NBT-API/pull/237
- @U5B 首次贡献见 https://github.com/tr7zw/Item-NBT-API/pull/242
完整更新日志:https://github.com/tr7zw/Item-NBT-API/compare/2.11.3...2.12.0-RC1


