Releases: tr7zw/Item-NBT-API
2.14.0
What's Changed
- Add 1.21.3 support (and 1.21.2, but you shouldn't be using this version)
- Hide NBTFile/NBTContainer fully behind NBT (methods are now deprecated, pointing to the equivalent NBT replacement)
- Add missing addCompound(ReadableNBT comp) to ReadWriteNBTCompoundList
- Fix edge-case in writing out Bukkit items without data
- Try to auto-detect pre 1.20.3 item nbt also via the "Count" tag for updating
- Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.8.0 to 3.10.0 by @dependabot in #297
- Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.10.0 to 3.10.1 by @dependabot in #300
Full Changelog: 2.13.2...2.14.0
2.13.2
What's Changed
- Add 1.21.1 support
- Small wiki changes by @SoSeDiK in #287
- Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.7.0 to 3.8.0 by @dependabot in #290
- Prevent chunk loading during tile entity tests by @SoSeDiK in #288
Full Changelog: 2.13.1...2.13.2
2.13.1
What's Changed
- Fix Paper 1.21
- Fix resolveCompound in ReadWriteNBT not returning ReadWriteNBT
- Add a missing
@Nullable
flag to resolveCompound - Removed old incorrect mappings on newer versions
- General code cleanup
- Fix datafixer now knowing the 1.21 version id
- Update wiki by @SoSeDiK in #282
If you have questions about how to migrate your code away from NBTItem or how to support 1.20.5+ with the new ItemStack logic, check out the updated wiki! SoSeDiK did an amazing job updating the wiki, including many updated examples. Also, feel free to PR your plugin to the Plugin list on the wiki.
Full Changelog: 2.13.0...2.13.1
2.13.0
What's Changed
- Update to 1.21
- Deprecated lots of old methods/constructors. Please migrate to the NBT class for faster and abstracted alternatives
- Added new NBT.modifyComponents API for 1.20.5+ to modify vanilla components
- Removed nbt-injector(you really shouldn't be using this) and nbt-data-api(never finished). This removed a lot of bloat from the jar
- Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.3 to 3.7.0 by @dependabot in #279
- Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.3 to 3.6.0 by @dependabot in #278
Full Changelog: 2.12.4...2.13.0
2.12.4
What's Changed
- Add 1.20.5 & 1.20.6 support
- Add Datafixer support to upgrade item NBT to newer versions
- Auto upgrade old ItemStacks when using
NBT.itemStackFromNBT
and the related methods (it will assume the NBT is 1.20.4 data, otherwise upgrade the NBT before yourself with the Datafixer) - Fix BlockEntity bug on Mojang mapped servers
- Bump org.apache.maven.plugins:maven-source-plugin from 3.3.0 to 3.3.1 by @dependabot in #273
- Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.2 to 3.5.3 by @dependabot in #277
Note
Due to Mojang changes to how ItemStacks work at runtime, vanilla NBT won't be visible on loaded ItemStacks in 1.20.5+ anymore. So modifying vanilla data will not work anymore in the same way as for 1.8-1.20.4, and all plugins need to be updated to be aware of that. If in doubt, feel free to ask on Discord.
Full Changelog: 2.12.3...2.12.4
2.12.3
What's Changed
- Add support for un-remapped Paper 1.20+
Other changes
- Bump org.apache.maven.plugins:maven-compiler-plugin from 3.11.0 to 3.12.0 by @dependabot in #261
- Bump org.apache.maven.plugins:maven-compiler-plugin from 3.12.0 to 3.12.1 by @dependabot in #263
- Update LICENSE copyright to 2024 by @SmartGecko44 in #264
- Bump org.codehaus.mojo:license-maven-plugin from 2.3.0 to 2.4.0 by @dependabot in #265
- Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.1 to 3.5.2 by @dependabot in #267
- Bump org.apache.maven.plugins:maven-compiler-plugin from 3.12.1 to 3.13.0 by @dependabot in #270
New Contributors
- @SmartGecko44 made their first contribution in #264
Full Changelog: 2.12.2...2.12.3
2.12.2
What's Changed
- Add 1.20.4 support
- Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.0 to 3.6.2 by @dependabot in #256
- Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.2 to 3.6.3 by @dependabot in #258
Full Changelog: 2.12.1...2.12.2
2.12.1
What's Changed
- Fix 1.19R3 using the wrong mapping, causing a test to fail
- Fix internal version ID of 1.20R2
- Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.0 to 3.5.1 by @dependabot in #250
- Bump org.codehaus.mojo:license-maven-plugin from 2.2.0 to 2.3.0 by @dependabot in #253
Full Changelog: 2.12.0...2.12.1
2.12.0
2.12.0
Hello everyone, this is the by far biggest NBTAPI update so far. This release contains 100 commits of the total 580 total commits(17% of all commits of the past 7 years?!?), so strap in for the changes.
(Also small reminder that supporting the dev behind this project would be really nice, especially when you use this API to make paid Plugins 😅)
Late changes between 2.12.0-RC1 and 2.12.0:
- Add 1.20.2 support
- Fix getKeys on empty ItemStacks
- Fix modifyMeta on empty ItemStacks
- Add support for ProxiedLists
- Add support for using indices like [123] or [-1] in resolve methods
- Hard prevent Jitpack. If you are using Jitpack for whatever reason, check the wiki to use the correct repo!
Major Changes
- Add support for Mojang-Mapped servers(Paper-Mojmap/Paper dev mode)
- Add support for Folia
- HEAVY performance improvements for NBT.get and NBT.modify (see below)
- Preview: Interface proxies to access NBT without writing code(see below)
- Entity/BlockEntity modifications are now atomic and faster to prevent pitfalls
- Entity/BlockEntity read-only is now a lot faster by only getting the tag once
- Added resolveOrNull/resolveOrDefault/resolveCompound/resolveOrCreateCompound. They take
.
separated strings to keys liketag.othertag.key
(see below for examples)
Noteworthy Changes
- Updated bStats from version 1? to 3.0.2
- Reduced logging for Gson
- Added long[] support with setLongArray/getLongArray (1.16+)
- Include NBTAPI version in errors
- Removed the "functional-annotations" dependency shading users might have noticed
- Fixed NBTFile.saveTo always saving the root instead of the passed tag
- Added @nullable in some key places
- When the tag is empty at the end of NBT.modify, the tag gets removed from the item instead of saving an empty
{}
tag - Prevented some misuse of the NBT.get/NBT.modify methods
- New
set(String key, T value, NBTHandler<T> handler)
method to set your custom data with the provided handler - New
get(String key, NBTHandler<T> handler)
method to get your custom data with the provided handler
Other Changes/Documentation
- Bump license-maven-plugin from 2.0.1 to 2.1.0 by @dependabot in #229
- Bump maven-shade-plugin from 3.4.1 to 3.5.0 by @dependabot in #232
- Bump license-maven-plugin from 2.1.0 to 2.2.0 by @dependabot in #235
- Read-only optimization by @tr7zw in #236
- Update "set skull skin" documentation by @BlackBaroness in #237
- Fix minor English mistakes in documentation by @BlackBaroness in #238
- add honorable plugin list mentions by @U5B in #242
- Fix Folia detection and NBT#modify for tile entities by @SoSeDiK in #243
Performance
This release has a lot of performance optimizations under the hood, mainly for the NBT.get
and NBT.modify
methods for ItemStacks/Entities/BlockEntities. I highly encourage everyone to start updating their NBTItem
/NBTEntity
/NBTTileEntity
code to use these new methods.
All benchmarks are done on Paper-171
on my local PC with 2.11.3 vs 2.12.0-RC1. The numbers are how often the test case was able to run in one second(the JVM did have some warmup time before on these methods). But since it's just one run there is probably a +-5% margin of error on these values, they are just there to get a rough idea.
Itemstacks
Link to the code that runs. The legacy tests use new NBTItem
, while the others use the NBT
class. Both tests get/set the same data, just changing between the old and new syntax!
NMS-Backed Itemstacks:
- LegacyGet: 880.620 -> 909.369 = ~3% faster
- NBT.get: 884.326 -> 4.214.210 = ~376% faster
- LegacySet: 762.453 -> 804.732 = ~5% faster
- NBT.modify: 298.238 -> 1.781.667 = ~497% faster
Bukkit-only Itemstacks:
- LegacyGet: 215.992 -> 202.413 = ~6% slower
- NBT.get: 223.998 -> 649.626 = ~190% faster
- LegacySet: 229.485 -> 239.910 = ~4% faster
- NBT.modify: 166.048 -> 567.107 = 241% faster
Basically, switch to the new NBT.get
/NBT.modify
method and get at least 200% more performance compared to before.
Persistent Data Container
To get a better idea on the performance of using the NBTAPI to store data on items vs Spigots Persistent Data Container API I checked and compared these too. Again, Paper-171
on 2.12.0-RC1. On NMS-Backed Itemstacks normal PDC is about the same speed as NBT.get. Only when caching the NamespacedKey in a final class field PDC pulls ahead. Writing data, especially on Bukkit-only items is a lot slower, but still easily 500.000+ times per second, so doubt that it's much of an issue(especially for gaining a way more flexible API and pre-1.14 support).
Resolve methods
To simplify working with deeply nested NBT, resolve methods now allow directly getting or working with these tags.
Compounds are separated by .
. In case you need a .
inside a key, it can be escaped with a \
.
Examples:
// sets foo/bar/baz/test to 42
nbt.resolveOrCreateCompound("foo.bar.baz").setInteger("test", 42);
// gets the value we just set or 0
nbt.resolveOrDefault("foo.bar.baz.test", 0);
// gets the value we just set or null
nbt.resolveOrNull("foo.bar.baz.test", int.class);
// example of a key with a . in it. Sets the key foo/some.key/baz/other
nbt.resolveOrCreateCompound("foo.some\\.key.baz").setInteger("other", 123)
// get a tag or null when it's not there
nbt.resolveCompound("some.nested.key");
Interface Proxies
This is a preview feature contained in this release, and the API might change depending on feedback/development. It allows defining an Interface with normal methods/default methods, and the NBTAPI wraps the NBT with an automatically generated implementation of this Interface.
Methods starting with has
/get
/set
will be interpreted as their respective calls:
public boolean hasKills();
runs return nbt.hasTag("kills");
public void setKills(int amount);
runs nbt.setInteger("kills", amount);
public int getKills();
runs return nbt.getInteger("kills");
Default methods like
public default void addKill() {
setKills(getKills() + 1);
}
inside the interface are supported. Also having a getter return another Interface that also extends NBTProxy
is supported.
To support other datatypes like ItemStacks, the init method can be overwritten with a default method, using the registerHandler
method to add handlers. For example:
@Override
default void init() {
registerHandler(ItemStack.class, NBTHandlers.ITEM_STACK);
}
To now use your interface, just call NBT.modify
or NBT.readNbt
like this:
NBT.modify(item, TestInterface.class, ti -> {
ti.addKill();
//or any other method from your interface
});
// This instance can only run read-only methods. Calling any setter will cause an exception
TestInterface yourInterface = NBT.readNbt(item, TestInterface.class);
yourInterface .getKills();
For the complete example check the built-in startup test or the WIP NBT-ItemMeta proxy. Also feel free to ask on Discord.
New Contributors
- @BlackBaroness made their first contribution in #237
- @U5B made their first contribution in #242
Full Changelog: 2.11.3...2.12.0-RC1
2.12.0 - Release Candidate 1
2.12.0 - Release Candidate 1
Hello everyone, this is the by far biggest NBTAPI update so far, that's why I decided to have a Minecraft-style Release Candidate before the full 2.12.0 release(best-case without any changes). This release contains 84 commits of the total 563 total commits(nearly 15% of all commits of the past 6-7 years?!?), so strap in for the changes.
(Also small reminder that supporting the dev behind this project would be really nice, especially when you use this API to make paid Plugins 😅)
Major Changes
- Add support for Mojang-Mapped servers(Paper-Mojmap/Paper dev mode)
- Add support for Folia
- HEAVY performance improvements for NBT.get and NBT.modify (see below)
- Preview: Interface proxies to access NBT without writing code(see below)
- Entity/BlockEntity modifications are now atomic and faster to prevent pitfalls
- Entity/BlockEntity read-only is now a lot faster by only getting the tag once
- Added resolveOrNull/resolveOrDefault/resolveCompound/resolveOrCreateCompound. They take
.
separated strings to keys liketag.othertag.key
(see below for examples)
Noteworthy Changes
- Updated bStats from version 1? to 3.0.2
- Reduced logging for Gson
- Added long[] support with setLongArray/getLongArray (1.16+)
- Include NBTAPI version in errors
- Removed the "functional-annotations" dependency shading users might have noticed
- Fixed NBTFile.saveTo always saving the root instead of the passed tag
- Added @nullable in some key places
- When the tag is empty at the end of NBT.modify, the tag gets removed from the item instead of saving an empty
{}
tag - Prevented some misuse of the NBT.get/NBT.modify methods
- New
set(String key, T value, NBTHandler<T> handler)
method to set your custom data with the provided handler - New
get(String key, NBTHandler<T> handler)
method to get your custom data with the provided handler
Other Changes/Documentation
- Bump license-maven-plugin from 2.0.1 to 2.1.0 by @dependabot in #229
- Bump maven-shade-plugin from 3.4.1 to 3.5.0 by @dependabot in #232
- Bump license-maven-plugin from 2.1.0 to 2.2.0 by @dependabot in #235
- Read-only optimization by @tr7zw in #236
- Update "set skull skin" documentation by @BlackBaroness in #237
- Fix minor English mistakes in documentation by @BlackBaroness in #238
- add honorable plugin list mentions by @U5B in #242
- Fix Folia detection and NBT#modify for tile entities by @SoSeDiK in #243
Performance
This release has a lot of performance optimizations under the hood, mainly for the NBT.get
and NBT.modify
methods for ItemStacks/Entities/BlockEntities. I highly encourage everyone to start updating their NBTItem
/NBTEntity
/NBTTileEntity
code to use these new methods.
All benchmarks are done on Paper-171
on my local PC with 2.11.3 vs 2.12.0-RC1. The numbers are how often the test case was able to run in one second(the JVM did have some warmup time before on these methods). But since it's just one run there is probably a +-5% margin of error on these values, they are just there to get a rough idea.
Itemstacks
Link to the code that runs. The legacy tests use new NBTItem
, while the others use the NBT
class. Both tests get/set the same data, just changing between the old and new syntax!
NMS-Backed Itemstacks:
- LegacyGet: 880.620 -> 909.369 = ~3% faster
- NBT.get: 884.326 -> 4.214.210 = ~376% faster
- LegacySet: 762.453 -> 804.732 = ~5% faster
- NBT.modify: 298.238 -> 1.781.667 = ~497% faster
Bukkit-only Itemstacks:
- LegacyGet: 215.992 -> 202.413 = ~6% slower
- NBT.get: 223.998 -> 649.626 = ~190% faster
- LegacySet: 229.485 -> 239.910 = ~4% faster
- NBT.modify: 166.048 -> 567.107 = 241% faster
Basically, switch to the new NBT.get
/NBT.modify
method and get at least 200% more performance compared to before.
Persistent Data Container
To get a better idea on the performance of using the NBTAPI to store data on items vs Spigots Persistent Data Container API I checked and compared these too. Again, Paper-171
on 2.12.0-RC1. On NMS-Backed Itemstacks normal PDC is about the same speed as NBT.get. Only when caching the NamespacedKey in a final class field PDC pulls ahead. Writing data, especially on Bukkit-only items is a lot slower, but still easily 500.000+ times per second, so doubt that it's much of an issue(especially for gaining a way more flexible API and pre-1.14 support).
Resolve methods
To simplify working with deeply nested NBT, resolve methods now allow directly getting or working with these tags.
Compounds are separated by .
. In case you need a .
inside a key, it can be escaped with a \
.
Examples:
// sets foo/bar/baz/test to 42
nbt.resolveOrCreateCompound("foo.bar.baz").setInteger("test", 42);
// gets the value we just set or 0
nbt.resolveOrDefault("foo.bar.baz.test", 0);
// gets the value we just set or null
nbt.resolveOrNull("foo.bar.baz.test", int.class);
// example of a key with a . in it. Sets the key foo/some.key/baz/other
nbt.resolveOrCreateCompound("foo.some\\.key.baz").setInteger("other", 123)
// get a tag or null when it's not there
nbt.resolveCompound("some.nested.key");
Interface Proxies
This is a preview feature contained in this release, and the API might change depending on feedback/development. It allows defining an Interface with normal methods/default methods, and the NBTAPI wraps the NBT with an automatically generated implementation of this Interface.
Methods starting with has
/get
/set
will be interpreted as their respective calls:
public boolean hasKills();
runs return nbt.hasTag("kills");
public void setKills(int amount);
runs nbt.setInteger("kills", amount);
public int getKills();
runs return nbt.getInteger("kills");
Default methods like
public default void addKill() {
setKills(getKills() + 1);
}
inside the interface are supported. Also having a getter return another Interface that also extends NBTProxy
is supported.
To support other datatypes like ItemStacks, the init method can be overwritten with a default method, using the registerHandler
method to add handlers. For example:
@Override
default void init() {
registerHandler(ItemStack.class, NBTHandlers.ITEM_STACK);
}
To now use your interface, just call NBT.modify
or NBT.readNbt
like this:
NBT.modify(item, TestInterface.class, ti -> {
ti.addKill();
//or any other method from your interface
});
// This instance can only run read-only methods. Calling any setter will cause an exception
TestInterface yourInterface = NBT.readNbt(item, TestInterface.class);
yourInterface .getKills();
For the complete example check the built-in startup test or the WIP NBT-ItemMeta proxy. Also feel free to ask on Discord.
New Contributors
- @BlackBaroness made their first contribution in #237
- @U5B made their first contribution in #242
Full Changelog: 2.11.3...2.12.0-RC1