You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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)
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 like tag.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
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 42nbt.resolveOrCreateCompound("foo.bar.baz").setInteger("test", 42);
// gets the value we just set or 0nbt.resolveOrDefault("foo.bar.baz.test", 0);
// gets the value we just set or nullnbt.resolveOrNull("foo.bar.baz.test", int.class);
// example of a key with a . in it. Sets the key foo/some.key/baz/othernbt.resolveOrCreateCompound("foo.some\\.key.baz").setInteger("other", 123)
// get a tag or null when it's not therenbt.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
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:
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 exceptionTestInterfaceyourInterface = NBT.readNbt(item, TestInterface.class);
yourInterface .getKills();
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
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:
Major Changes
.
separated strings to keys liketag.othertag.key
(see below for examples)Noteworthy Changes
{}
tagset(String key, T value, NBTHandler<T> handler)
method to set your custom data with the provided handlerget(String key, NBTHandler<T> handler)
method to get your custom data with the provided handlerOther Changes/Documentation
Performance
This release has a lot of performance optimizations under the hood, mainly for the
NBT.get
andNBT.modify
methods for ItemStacks/Entities/BlockEntities. I highly encourage everyone to start updating theirNBTItem
/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 theNBT
class. Both tests get/set the same data, just changing between the old and new syntax!NMS-Backed Itemstacks:
Bukkit-only Itemstacks:
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:
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();
runsreturn nbt.hasTag("kills");
public void setKills(int amount);
runsnbt.setInteger("kills", amount);
public int getKills();
runsreturn nbt.getInteger("kills");
Default methods like
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:To now use your interface, just call
NBT.modify
orNBT.readNbt
like this: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
Full Changelog: 2.11.3...2.12.0-RC1
This discussion was created from the release 2.12.0 .
Beta Was this translation helpful? Give feedback.
All reactions