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

搬运团队
搬运资源声明
对于可进行 JAR 文件搬运的许可证,我们提供站内下载服务;其他资源会跳转到原帖下载。资源更新可能不及时,建议前往资源内提供的原帖链接下载最新版本。
详情信息
更新日志
2.12.0
大家好,这是迄今为止 NBTAPI 最重大的一次更新。本次发布共包含 580 次总提交中的 100 次(占过去 7 年全部提交数的 17%?!),请做好准备迎接这些变更。
(顺便温馨提醒:支持本项目的开发者将非常棒,尤其是当你使用此 API 开发付费插件时 😅)
2.12.0-RC1 与 2.12.0 之间的延迟变更:
- 新增对 1.20.2 版本的支持
- 修复空 ItemStack 上的 getKeys 方法
- 修复空 ItemStack 上的 modifyMeta 方法
- 新增对代理列表(ProxiedLists)的支持
- 新增在 resolve 方法中使用类似
[123]或[-1]索引的支持 - 强制禁止使用 JitPack。若你因任何原因仍在使用 JitPack,请查阅 Wiki 以使用正确的仓库!
主要变更
- 新增对 Mojang 映射服务器(Paper-Mojmap / Paper 开发模式)的支持
- 新增对 Folia 的支持
- 对 NBT.get 和 NBT.modify 方法进行了大幅性能优化(详见下文)
- 预览功能:接口代理(Interface Proxies),无需编写代码即可访问 NBT(详见下文)
- 实体(Entity)/ 区块实体(BlockEntity)的修改操作现为原子性且速度更快,可避免常见陷阱
- 实体(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 将 license-maven-plugin 从 2.0.1 升级至 2.1.0:https://github.com/tr7zw/Item-NBT-API/pull/229
- 由 @dependabot 将 maven-shade-plugin 从 3.4.1 升级至 3.5.0:https://github.com/tr7zw/Item-NBT-API/pull/232
- 由 @dependabot 将 license-maven-plugin 从 2.1.0 升级至 2.2.0:https://github.com/tr7zw/Item-NBT-API/pull/235
- 只读性能优化,由 @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 修复 Folia 检测及区块实体(tile entities)的 NBT#modify 方法:https://github.com/tr7zw/Item-NBT-API/pull/243
性能优化
本次发布在底层进行了大量性能优化,主要针对 ItemStack / 实体(Entity)/ 区块实体(BlockEntity)的 NBT.get 和 NBT.modify 方法。我们强烈建议各位尽快将 NBTItem / NBTEntity / NBTTileEntity 的现有代码迁移至这些新方法。
所有基准测试均在本地 PC 上基于 Paper-171 运行,对比版本为 2.11.3 与 2.12.0-RC1。数值表示每秒可执行测试用例的次数(JVM 在测试前已进行预热)。但由于仅为单次运行,实际误差范围约为 ±5%,仅供参考。
ItemStack
运行代码链接。旧版测试使用 new NBTItem,其余测试则使用 NBT 类。两种测试均对相同数据进行读写,仅语法不同!
基于 NMS 的 ItemStack:
- 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 的 ItemStack:
- 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)API 的性能差异,我也对此进行了测试与对比。同样基于 Paper-171 与 2.12.0-RC1。在基于 NMS 的 ItemStack 上,常规 PDC 与 NBT.get 性能基本相当;仅当将 NamespacedKey 缓存于 final 类字段中时,PDC 才略占优势。而写入数据(尤其在纯 Bukkit 物品上)则慢得多,但即便如此仍可达每秒 50 万次以上,因此实际影响极小(尤其考虑到 NBTAPI 提供了更灵活的 API 以及对 1.14 之前版本的支持)。
resolve 方法
为简化对深层嵌套 NBT 的操作,resolve 方法现支持直接获取或操作这些标签。
复合标签(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


