Compare commits

..
34 Commits
Author SHA1 Message Date
tr7zw 0f926998f6 Tag 2.13.2 2024-08-10 20:28:54 +02:00
tr7zw 3a44a5e989 Add 1.21.1 Paper support 2024-08-10 20:21:32 +02:00
tr7zw 30b931945c Merge pull request #288 from SoSeDiK/chunkload
Prevent chunk loading during tile entity tests
2024-08-10 20:20:58 +02:00
tr7zw 88d8629541 Merge pull request #290 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-javadoc-plugin-3.8.0
Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.7.0 to 3.8.0
2024-07-21 20:56:57 +02:00
dependabot[bot] 00ae0448f4 Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.7.0 to 3.8.0
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.7.0 to 3.8.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.7.0...maven-javadoc-plugin-3.8.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-21 18:53:26 +00:00
tr7zw ce26e180e6 Merge branch 'master' of https://github.com/tr7zw/Item-NBT-API 2024-07-21 20:51:52 +02:00
tr7zw c939105e45 Start 2.13.2-SNAPSHOT 2024-07-21 20:51:48 +02:00
tr7zw 2079123a42 Merge pull request #287 from SoSeDiK/wiki
Small wiki changes
2024-07-21 20:48:08 +02:00
SoSeDiK 31b17fe9c9 Update wiki
- Fix broken (block-)entities link in sidebar
- Change "(block)-entities" to "entities and block entities" in titles to better reflect title in links
- Move repository above artifact in Maven/Gradle usage
- Add info about preloadApi
- Add title for ItemMeta usage
- Small text changes
2024-07-01 15:53:10 +03:00
SoSeDiK b565902006 Prevent chunk loading during tile entity tests 2024-07-01 15:20:52 +03:00
tr7zw 5280ba82a2 Tag 2.13.1 2024-06-20 22:37:58 +02:00
tr7zw 522f732ed1 Fix wiki and update the datafixer 2024-06-20 22:34:21 +02:00
tr7zw ac84a4d69a Fix another dead link 2024-06-20 22:20:04 +02:00
tr7zw d7e18c1cb6 Fix dead link 2024-06-20 22:18:41 +02:00
tr7zw ffa612634a Merge pull request #282 from SoSeDiK/wiki
Update wiki
2024-06-20 22:13:01 +02:00
tr7zw 739682122b Remove the usage of the word "tile" entity 2024-06-20 22:07:38 +02:00
tr7zw 2e20af40e5 Add NBT.preloadApi 2024-06-20 21:39:39 +02:00
SoSeDiK e6527515be Update Maven/Gradle usage 2024-06-17 01:05:07 +03:00
SoSeDiK e6f33a35ae Small clarifications/grammar 2024-06-17 01:05:07 +03:00
SoSeDiK 39801ada18 Update saving entity nbt example 2024-06-17 01:05:07 +03:00
SoSeDiK 75fab7622a Update examples 2024-06-17 01:05:07 +03:00
tr7zw 33eef1bcf1 Update FAQ.md 2024-06-17 01:05:07 +03:00
SoSeDiK 877a42fd06 Even more TODOs 2024-06-17 01:05:07 +03:00
SoSeDiK 0a7e560e2e Fill out some TODOs 2024-06-17 01:05:07 +03:00
SoSeDiK 174728a681 mvn spottless:apply 2024-06-17 01:05:07 +03:00
SoSeDiK 79ba1dd275 [WIP] Started updating wiki 2024-06-17 01:05:07 +03:00
tr7zw 25c59b0eae Fix build 2024-06-16 22:51:48 +02:00
tr7zw 0057d3f2e8 Remove nbtinjector/dataapi from the build 2024-06-16 00:35:20 +02:00
tr7zw 59c67a3f0b Remove unused code/private some methods/classes 2024-06-16 00:31:36 +02:00
tr7zw 3ec606ae21 Disable old method mappings 2024-06-15 23:39:40 +02:00
tr7zw ff0a94f279 Add nullable flag 2024-06-15 23:27:41 +02:00
tr7zw 53216d3b7d Overwrite resolveCompound to be ReadWriteNBT 2024-06-15 23:06:38 +02:00
tr7zw 7cf23201ce Hotfix Paper 1.21 2024-06-14 21:30:01 +02:00
tr7zw fe1d586f44 Start 2.13.1 snapshots 2024-06-14 12:33:35 +02:00
35 changed files with 772 additions and 315 deletions

No files matched your search

+1 -1
View File
@@ -8,7 +8,7 @@ updates:
ignore:
- dependency-name: com.github.ekryd.sortpom:sortpom-maven-plugin
versions:
- 2.13.1
- 2.13.2
- 2.14.0
- 2.14.1
- 2.15.0
+2 -2
View File
@@ -1,6 +1,6 @@
# Item-NBT-API
Add custom NBT tags to Items/Tiles/Entities without NMS! Modify NBT and store it Files, other NBT or as String in yaml/json/SQL/Redis.
Add custom NBT tags to Items/Tiles/Entities without NMS! Modify NBT and store it in Files, other NBT, or as String in yaml/json/SQL/Redis.
[Server Owner/Developer Wiki](https://github.com/tr7zw/Item-NBT-API/wiki)
### Build/Maven/Sonar Status
@@ -15,7 +15,7 @@ Add custom NBT tags to Items/Tiles/Entities without NMS! Modify NBT and store it
## Getting started
Import the API [using Maven](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Maven), then check out the [basic usage](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API) or code examples like [working with Skulls](https://github.com/tr7zw/Item-NBT-API/wiki/Set-a-skull's-skin-using-NBT-API).
Import the API using [Maven](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Maven) or [Gradle](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Gradle), then check out the [basic usage](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API) or code examples like [working with Skulls](https://github.com/tr7zw/Item-NBT-API/wiki/Example-Usages#set-a-skulls-skin).
### bStats
+2 -2
View File
@@ -1,6 +1,6 @@
# (Item-)NBT-API
Add custom NBT tags to Items/Tiles/Entities without NMS! Modify NBT and store it Files, other NBT or as String in yaml/json/SQL/Redis.
Add custom NBT tags to Items/Tiles/Entities without NMS! Modify NBT and store it in Files, other NBT, or as String in yaml/json/SQL/Redis.
[Server Owner/Developer Wiki](https://github.com/tr7zw/Item-NBT-API/wiki)
### Build/Maven/Sonar Status
@@ -14,7 +14,7 @@ Discord:[![Discord](https://img.shields.io/discord/342814924310970398?color=%237
## Getting started
Import the API [using Maven](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Maven), then check out the [basic usage](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API) or code examples like [working with Skulls](https://github.com/tr7zw/Item-NBT-API/wiki/Set-a-skull's-skin-using-NBT-API).
Import the API using [Maven](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Maven) or [Gradle](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Gradle), then check out the [basic usage](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API) or code examples like [working with Skulls](https://github.com/tr7zw/Item-NBT-API/wiki/Example-Usages#set-a-skulls-skin).
### bStats
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.13.0</version>
<version>2.13.2</version>
</parent>
<artifactId>item-nbt-api</artifactId>
@@ -2,6 +2,7 @@ package de.tr7zw.changeme.nbtapi;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.logging.Level;
import javax.annotation.Nullable;
@@ -19,6 +20,8 @@ import de.tr7zw.changeme.nbtapi.wrapper.NBTProxy;
import de.tr7zw.changeme.nbtapi.wrapper.ProxyBuilder;
import de.tr7zw.changeme.nbtapi.iface.ReadableNBTList;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
/**
* General utility class for a clean and simple nbt access.
@@ -33,6 +36,45 @@ public class NBT {
// No instances of NBT. Utility class
}
/**
* Utility method for shaded versions to preload and check the API during
* onEnable. This method does not throw an exception and instead logs them. Will
* return false if something fundamentally is wrong and the NBTAPI is in a non
* functioning state. The shading plugin then needs to handle this. Note:
* Calling this method during onLoad will cause an failure, so please wait till
* onEnable.
*
* @return true if everything went fine
*/
public static boolean preloadApi() {
try {
// boiled down version of the plugin selfcheck without tests
if (MinecraftVersion.getVersion() == MinecraftVersion.UNKNOWN) {
NbtApiException.confirmedBroken = true;
return false;
}
for (ClassWrapper c : ClassWrapper.values()) {
if (c.isEnabled() && c.getClazz() == null) {
NbtApiException.confirmedBroken = true;
return false;
}
}
for (ReflectionMethod method : ReflectionMethod.values()) {
if (method.isCompatible() && !method.isLoaded()) {
NbtApiException.confirmedBroken = true;
return false;
}
}
// not settings NbtApiException.confirmedBroken = false, as no actual tests were done.
// This just means the version was found, and all reflections seem to work.
return true;
} catch (Exception ex) {
NbtApiException.confirmedBroken = true;
MinecraftVersion.getLogger().log(Level.WARNING, "[NBTAPI] Error during the selfcheck!", ex);
return false;
}
}
/**
* Get a read only instance of the items NBT. This method is slightly slower
* than calling NBT.get due to having to create a copy of the ItemStack, but
@@ -1460,7 +1460,7 @@ public class NBTCompound implements ReadWriteNBT {
return false;
}
protected static boolean isEqual(NBTCompound compA, NBTCompound compB, String key) {
private static boolean isEqual(NBTCompound compA, NBTCompound compB, String key) {
if (compA.getType(key) != compB.getType(key))
return false;
switch (compA.getType(key)) {
@@ -29,16 +29,6 @@ public class NbtApiException extends RuntimeException {
super();
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public NbtApiException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(generateMessage(message), cause, enableSuppression, writableStackTrace);
}
/**
* @param message
* @param cause
@@ -203,6 +203,10 @@ public interface ReadWriteNBT extends ReadableNBT {
@Override
ReadWriteNBTCompoundList getCompoundList(String name);
@Override
@Nullable
ReadWriteNBT resolveCompound(String key);
/**
* Remove all keys from this compound
@@ -16,6 +16,9 @@ import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
public class DataFixerUtil {
// these values can be found in DetectedVersion inside mc
// Finding pre 1.12.2 values is left as an exercise for the reader,
// as DetectedVersion is not a thing there
public static final int VERSION1_12_2 = 1343;
public static final int VERSION1_16_5 = 2586;
public static final int VERSION1_17_1 = 2730;
@@ -26,6 +29,7 @@ public class DataFixerUtil {
public static final int VERSION1_20_2 = 3578;
public static final int VERSION1_20_4 = 3700;
public static final int VERSION1_20_5 = 3837;
public static final int VERSION1_21 = 3953;
@SuppressWarnings("unchecked")
public static Object fixUpRawItemData(Object nbt, int fromVersion, int toVersion)
@@ -58,7 +62,9 @@ public class DataFixerUtil {
* @return
*/
public static int getCurrentVersion() {
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R1)) {
return VERSION1_21;
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
return VERSION1_20_5;
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R3)) {
return VERSION1_20_4;
@@ -39,7 +39,7 @@ public enum MinecraftVersion {
private static Logger logger = Logger.getLogger("NBTAPI");
// NBT-API Version
protected static final String VERSION = "2.13.0";
protected static final String VERSION = "2.13.2";
private final int versionId;
private final boolean mojangMapping;
@@ -55,7 +55,8 @@ public enum MinecraftVersion {
this.put("1.20.4", MC1_20_R3);
this.put("1.20.5", MC1_20_R4);
this.put("1.20.6", MC1_20_R4);
this.put("1.21.0", MC1_21_R1);
this.put("1.21", MC1_21_R1);
this.put("1.21.1", MC1_21_R1);
}
};
@@ -27,12 +27,7 @@ public final class PathUtil {
private final String path;
private final Integer index;
public PathSegment(String path, int index) {
this.path = path;
this.index = index;
}
public PathSegment(String path) {
private PathSegment(String path) {
Matcher matcher = indexPattern.matcher(path);
if (matcher.find()) {
this.path = path.substring(0, path.indexOf("["));
@@ -5,8 +5,6 @@ import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.UUID;
import java.util.stream.Collectors;
import org.bukkit.inventory.ItemStack;
import de.tr7zw.changeme.nbtapi.NbtApiException;
@@ -114,7 +112,7 @@ public enum ReflectionMethod {
new Since(MinecraftVersion.MC1_7_R4, "getCompound"),
new Since(MinecraftVersion.MC1_18_R1, "getCompound(java.lang.String)")),
NMSITEM_GETTAG(ClassWrapper.NMS_ITEMSTACK, new Class[] {}, MinecraftVersion.MC1_7_R4,
NMSITEM_GETTAG(ClassWrapper.NMS_ITEMSTACK, new Class[] {}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_20_R3,
new Since(MinecraftVersion.MC1_7_R4, "getTag"), new Since(MinecraftVersion.MC1_18_R1, "getTag()")),
NMSITEM_SAVE(ClassWrapper.NMS_ITEMSTACK, new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_20_R3, new Since(MinecraftVersion.MC1_7_R4, "save"),
@@ -175,10 +173,6 @@ public enum ReflectionMethod {
NMS_WORLD_GET_TILEENTITY(ClassWrapper.NMS_WORLDSERVER, new Class[] { ClassWrapper.NMS_BLOCKPOSITION.getClazz() },
MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "getTileEntity"),
new Since(MinecraftVersion.MC1_18_R1, "getBlockEntity(net.minecraft.core.BlockPos)")),
NMS_WORLD_SET_TILEENTITY(ClassWrapper.NMS_WORLDSERVER,
new Class[] { ClassWrapper.NMS_BLOCKPOSITION.getClazz(), ClassWrapper.NMS_TILEENTITY.getClazz() },
MinecraftVersion.MC1_8_R3, MinecraftVersion.MC1_16_R3,
new Since(MinecraftVersion.MC1_8_R3, "setTileEntity")),
NMS_WORLD_REMOVE_TILEENTITY(ClassWrapper.NMS_WORLDSERVER, new Class[] { ClassWrapper.NMS_BLOCKPOSITION.getClazz() },
MinecraftVersion.MC1_8_R3, MinecraftVersion.MC1_17_R1, new Since(MinecraftVersion.MC1_8_R3, "t"),
new Since(MinecraftVersion.MC1_9_R1, "s"), new Since(MinecraftVersion.MC1_13_R1, "n"),
@@ -187,11 +181,9 @@ public enum ReflectionMethod {
NMS_WORLD_GET_TILEENTITY_1_7_10(ClassWrapper.NMS_WORLDSERVER, new Class[] { int.class, int.class, int.class },
MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "getTileEntity")),
// FIXME: No Spigot mapping!
TILEENTITY_LOAD_LEGACY191(ClassWrapper.NMS_TILEENTITY,
new Class[] { ClassWrapper.NMS_MINECRAFTSERVER.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
MinecraftVersion.MC1_9_R1, MinecraftVersion.MC1_9_R1, new Since(MinecraftVersion.MC1_9_R1, "a")),
// FIXME: No Spigot mapping!
TILEENTITY_LOAD_LEGACY183(ClassWrapper.NMS_TILEENTITY, new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
MinecraftVersion.MC1_8_R3, MinecraftVersion.MC1_9_R2, new Since(MinecraftVersion.MC1_8_R3, "c"),
new Since(MinecraftVersion.MC1_9_R1, "a"), new Since(MinecraftVersion.MC1_9_R2, "c")),
@@ -264,10 +256,8 @@ public enum ReflectionMethod {
MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "keySet")),
REGISTRY_GET(ClassWrapper.NMS_REGISTRYSIMPLE, new Class[] { Object.class }, MinecraftVersion.MC1_11_R1,
MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "get")),
// FIXME: No Spigot mapping!
REGISTRY_SET(ClassWrapper.NMS_REGISTRYSIMPLE, new Class[] { Object.class, Object.class },
MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "a")),
// FIXME: No Spigot mapping!
REGISTRY_GET_INVERSE(ClassWrapper.NMS_REGISTRYMATERIALS, new Class[] { Object.class }, MinecraftVersion.MC1_11_R1,
MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "b")),
REGISTRYMATERIALS_KEYSET(ClassWrapper.NMS_REGISTRYMATERIALS, new Class[] {}, MinecraftVersion.MC1_13_R1,
@@ -278,7 +268,7 @@ public enum ReflectionMethod {
MinecraftVersion.MC1_13_R2, MinecraftVersion.MC1_17_R1, new Since(MinecraftVersion.MC1_13_R2, "getKey")),
GAMEPROFILE_DESERIALIZE(ClassWrapper.NMS_GAMEPROFILESERIALIZER,
new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() }, MinecraftVersion.MC1_7_R4,
new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() }, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_20_R3,
new Since(MinecraftVersion.MC1_7_R4, "deserialize"),
new Since(MinecraftVersion.MC1_18_R1, "readGameProfile(net.minecraft.nbt.CompoundTag)")),
GAMEPROFILE_SERIALIZE(ClassWrapper.NMS_GAMEPROFILESERIALIZER,
@@ -65,7 +65,7 @@ public class ProxyBuilder<T extends NBTProxy> implements InvocationHandler {
}
}
@SuppressWarnings("unchecked")
@SuppressWarnings({ "unchecked", "rawtypes" })
private static Function<Arguments, Object> createFunction(NBTProxy proxy, Method method) {
if ("toString".equals(method.getName()) && method.getParameterCount() == 0
&& method.getReturnType() == String.class) {
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.13.0</version>
<version>2.13.2</version>
</parent>
<artifactId>item-nbt-api-plugin</artifactId>
<packaging>jar</packaging>
@@ -12,7 +12,7 @@
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>2.13.0</version>
<version>2.13.2</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -22,7 +22,7 @@ public class TileTest implements Test {
try {
Block block = world.getBlockAt(world.getSpawnLocation().getBlockX(), 254,
world.getSpawnLocation().getBlockZ());
if (block.getChunk().isLoaded() && block.getType() == Material.AIR) {
if (world.isChunkLoaded(block.getX() >> 4, block.getZ() >> 4) && block.getType() == Material.AIR) {
block.setType(Material.CHEST);
NBTTileEntity tile = new NBTTileEntity(block.getState());
if (!MinecraftVersion.isNewerThan(MinecraftVersion.MC1_17_R1)) {
@@ -25,7 +25,7 @@ public class TilesCustomNBTPersistentTest implements Test {
try {
Block block = world.getBlockAt(world.getSpawnLocation().getBlockX(), 250,
world.getSpawnLocation().getBlockZ());
if (block.getType() == Material.AIR) {
if (world.isChunkLoaded(block.getX() >> 4, block.getZ() >> 4) && block.getType() == Material.AIR) {
block.setType(Material.CHEST);
NBTTileEntity comp = new NBTTileEntity(block.getState());
NBTCompound persistentData = comp.getPersistentDataContainer();
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.13.0</version>
<version>2.13.2</version>
</parent>
<artifactId>mappings-parser</artifactId>
<packaging>jar</packaging>
@@ -12,7 +12,7 @@
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>2.13.0</version>
<version>2.13.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
@@ -3,7 +3,6 @@ package dev.tr7zw.mappingsparser;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+2 -2
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.13.0</version>
<version>2.13.2</version>
</parent>
<artifactId>nbt-data-api</artifactId>
@@ -14,7 +14,7 @@
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>2.13.0</version>
<version>2.13.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.13.0</version>
<version>2.13.2</version>
</parent>
<artifactId>nbt-injector</artifactId>
<packaging>jar</packaging>
@@ -12,7 +12,7 @@
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>2.13.0</version>
<version>2.13.2</version>
<scope>compile</scope>
</dependency>
<dependency>
+2 -4
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.13.0</version>
<version>2.13.2</version>
<packaging>pom</packaging>
<inceptionYear>2015</inceptionYear>
<organization>
@@ -19,8 +19,6 @@
</licenses>
<modules>
<module>item-nbt-api</module>
<module>nbt-injector</module>
<module>nbt-data-api</module>
<module>item-nbt-plugin</module>
<module>mappings-parser</module>
</modules>
@@ -112,7 +110,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.7.0</version>
<version>3.8.0</version>
<configuration>
<source>8</source>
</configuration>
+2 -2
View File
@@ -112,7 +112,7 @@ Just use the Plugin as Maven dependency and remember to add "NBTAPI" as dependen
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api-plugin</artifactId>
<version>2.13.0</version>
<version>2.13.2</version>
</dependency>
[/CODE]
[/SPOILER]
@@ -122,7 +122,7 @@ Using this method the API gets copied into your plugin. Server owners don't have
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>2.13.0</version>
<version>2.13.2</version>
</dependency>
...
<plugins>
@@ -1,42 +0,0 @@
# Converting Minecraft Objects to NBT and Strings
The basic idea is that you can convert data into different representations:
Minecraft Objects <-> NBT <-> String(Mojang-Json)
## Converting Minecraft Objects into NBT
```java
// Items
ReadWriteNBT nbt = NBT.itemStackToNBT(itemStack);
ReadWriteNBT nbt = NBT.itemStackArrayToNBT(itemStacks);
// Entity
NBTEntity nbte = new NBTEntity(entity);
// Tiles
NBTTileEntity nbtt= new NBTTileEntity(block.getState());
// Gameprofiles
ReadWriteNBT nbt = NBT.gameProfileToNBT(profile);
// NBT Files
NBTFile file = new NBTFile(testFile);
```
## Converting NBT to a String and the String back to NBT
```java
// to String(works with any NBT object)
String str = nbt.toString();
// String back to NBT
ReadWriteNBT nbt = NBT.parseNBT(json);
```
## Recreating the Minecraft Objects from NBT
```java
// Items
ItemStack itemStack = NBT.itemStackFromNBT(nbt);
ItemStack[] itemStacks = NBT.itemStackArrayFromNBT(nbt);
// Entity/Tiles
In general "new NBTEntity(entity).mergeCompound(nbt)", but you might want to remove some data from the nbt first like the Location, uuid and entityId
// Gameprofile
GameProfile profile = NBT.gameProfileFromNBT(nbt);
```
+125
View File
@@ -0,0 +1,125 @@
## Set a skull's skin
#### We will be using [this head](https://minecraft-heads.com/custom-heads/head/28194-cup-of-soda) as example.
```java
// This is the base64 texture value from the bottom of the previously mentioned website.
final String textureValue = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTQyY2M5MjAzYzkwYjg5YmRhYzFkZjI4NDE2NzI2NmI5NTNkZmViZjNjNDY5MGE3Y2QwYjE1NzkxYTYyZTU4MiJ9fX0=";
// Creating ItemStack
// For Minecraft 1.12.2 and below
final ItemStack item = new ItemStack(Material.SKULL_ITEM);
item.setDurability((short) 3);
// For Minecraft 1.13 and newer
final ItemStack item = new ItemStack(Material.PLAYER_HEAD);
// Applying nbt
// For Minecraft 1.20.4 and below
NBT.modify(item, nbt -> {
ReadWriteNBT skullOwnerCompound = nbt.getOrCreateCompound("SkullOwner");
// The owner UUID. Note that skulls with the same UUID but different textures will misbehave and only one texture will load.
// They will share the texture. To avoid this limitation, it is recommended to use a random UUID.
skullOwnerCompound.setUUID("Id", UUID.randomUUID());
skullOwnerCompound.getOrCreateCompound("Properties")
.getCompoundList("textures")
.addCompound()
.setString("Value", textureValue);
});
// Workaround for Minecraft 1.20.5+
NBT.modifyComponents(item, nbt -> {
ReadWriteNBT profileNbt = nbt.getOrCreateCompound("minecraft:profile");
profileNbt.setUUID("id", uuid);
ReadWriteNBT propertiesNbt = profileNbt.getCompoundList("properties").addCompound();
propertiesNbt.setString("name", "textures");
propertiesNbt.setString("value", textureValue);
});
```
> [!TIP]
> If you are using Paper API on 1.12.2+, you may use the following code to create textured skulls
```java
SkullMeta meta = (SkullMeta) item.getItemMeta();
PlayerProfile playerProfile = Bukkit.createProfile(uuid);
playerProfile.setProperty(new ProfileProperty("textures", textureValue));
meta.setPlayerProfile(playerProfile);
// You can also use item.editMeta(SkullMeta.class, meta -> {}); on 1.17+
item.setItemMeta(meta);
```
## Zombie that can pick up loot and does 0.5 hearts of damage
This code should serve only as a reference, the nbt structure might change between versions.
```java
Zombie zombie = location.getWorld().spawn(location, Zombie.class);
String attributeName = "minecraft:generic.attack_damage"; // Or generic.attackDamage prior to 1.16
double damageValue = 0.5;
// Modify vanilla data
NBT.modify(zombie, nbt -> {
nbt.setBoolean("CanPickUpLoot", true);
ReadWriteNBTCompoundList list = nbt.getCompoundList("Attributes");
// Check if zombie already has attribute set. If so, modify it
for (ReadWriteNBT listEntryNbt : list) {
if (!listEntryNbt.getString("Name").equals(attributeName)) continue;
listEntryNbt.setDouble("Base", damageValue);
return;
}
// Attribute is missing, add it instead
ReadWriteNBT listEntryNbt = list.addCompound();
listEntryNbt.setString("Name", attributeName);
listEntryNbt.setDouble("Base", damageValue);
});
// Modify custom data
NBT.modifyPersistentData(zombie, nbt -> {
// Let's mark our zombie as a custom one
nbt.setBoolean("custom_zombie", true);
});
```
## Reading world data
```java
// Get main world's folder
File worldDataFolder = Bukkit.getWorlds().getFirst().getWorldFolder();
// Read level data
NBTFile levelNbtFile = new NBTFile(new File(worldDataFolder, "level.dat"));
// Obtain world name
String worldName = levelNbtFile.resolveOrNull("Data.LevelName", String.class);
// Read some player's data
UUID playerUuid;
File playerFile = new File(worldDataFolder, "playerdata/" + playerUuid + ".dat");
if (!playerFile.exists()) {
// No offline player data for provided uuid
return;
}
NBTFile playerNbtFile = new NBTFile(playerFile);
// Change player's health
float health = playerNbtFile.getFloat("Health");
playerNbtFile.setFloat("Health", health + 5);
// Once finished, save the file
playerNbtFile.save();
```
+26
View File
@@ -0,0 +1,26 @@
## Frequently Asked Questions
### I've updated NBT-API, but it keeps saying that it's outdated
Some other plugin on your server has a shaded version of NBT-API. Try looking at the logs to find out which plugin is it, or add/remove your plugins until you find a culprit.
### I've installed NBT-API, but the plugin keeps asking for ItemNBTAPI
The plugin uses a very outdated version of NBT-API. In this case, download the version 1.8.3 from the versions tab. The outdated "ItemNBTAPI" and "NBTAPI" can be used both at the same time.
### 1.7 support
- Use 1.7.10.
- NBTLists may not work.
- NBTTypes don't work as 1.7.x is missing this feature.
- TLDR: 1.7.10 is a bit broken and not everything will work! Also, it's not supported anymore!
### Where did NBTInjector go?
The experimental NBTInjector became unsupported since Minecraft 1.14 and was removed in 2.13.0 with Minecraft 1.21 release.
NBTInjector is incompatible with reloads and may break things, and thus is not recommended.
If you're using Minecraft 1.14+, you should switch to the persistent storage API instead.
In versions prior to 1.14, you may use a workaround like storing data inside an item's nbt that the entity is wearing (e.g. having a button in mob's helmet, and storing data on that button).
+8 -17
View File
@@ -1,26 +1,17 @@
# Welcome to the NBT API wiki
# Welcome to the NBT-API wiki
NBT API has been tested on Spigot
1.7.10-1.19+
NBT-API supports Spigot and Paper versions starting at 1.8. It runs on 1.7.10 too, but some features might not work (see [1.7 support](https://github.com/tr7zw/Item-NBT-API/wiki/FAQ#17-support)).
Full JavaDoc can be found [here](https://tr7zw.github.io/Item-NBT-API/v2-api/)!
Feel free to seek for support in [![Discord](https://img.shields.io/discord/342814924310970398?color=%237289DA&label=Discord&logo=discord&logoColor=white)](https://discordapp.com/invite/yk4caxM).
### What do I have to do as a server owner?
Just download the jar and drop it in the plugins folder. Done.
Note that outdated plugins may ask for "ItemNBTAPI". In this case, download version 1.8.3 from the versions tab. The outdated "ItemNBTAPI" and "NBTAPI" can be used at the same time.
Just download the jar and drop it in the plugins folder. Done!
### 1.7 Notes
* Use 1.7.10
* NBTLists may not work
* NBTTypes don't work as 1.7.x is missing this feature.
* TLDR: 1.7.10 is a bit broken and not everything will work! Also it's not supported anymore!
### Don't reload the NBT-Injector
Reloading in general is a horrible thing and it will break the NBTInjector in horrible ways! When updating plugins/changing configs always restart the server normally!
You might also want to check out some [plugins that use NBT-API](https://github.com/tr7zw/Item-NBT-API/wiki/Plugins).
### How can I use the API as a developer?
See [Using the NBT API](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API)
Import the API using [Maven](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Maven) or [Gradle](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Gradle), then see the [basic usage](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API) or code examples like [working with Skulls](https://github.com/tr7zw/Item-NBT-API/wiki/Example-Usages#set-a-skulls-skin) to familiarize yourself with the API.
Full Javadoc can be found [here](https://tr7zw.github.io/Item-NBT-API/v2-api/)!
@@ -1,24 +0,0 @@
# Merging Compounds
You can "merge" the data from any given Compound onto some other Compound. This will overwrite tags with the same name.
Example:
`Tag1: {Num1:1, Num2:2} Tag2: {Num1:7, Num3:3}`
After merging Tag2 on Tag1:
```java
tag1.mergeCompound(tag2);
```
`Tag1: {Num1:7, Num2:2, Num3:3} Tag2: {Num1:7, Num3:3}`
## Simulate the "/data merge" command
```java
NBT.modify(zombie, nbt -> {
nbt.mergeCompound(NBT.parseNBT("{Silent:1b,Invulnerable:1b,Glowing:1b,IsBaby:1b}"));
});
```
+4 -3
View File
@@ -1,6 +1,4 @@
## List of some plugins on Github that utilize NBTAPI
Want your plugin added to this list? Submit a PR editing this file located in `~/wiki/Plugins.md`!
## List of some plugins on GitHub that utilize NBT-API
- [IllegalStack](https://github.com/dniym/IllegalStack)
- [Prison](https://github.com/PrisonTeam/Prison)
@@ -8,3 +6,6 @@ Want your plugin added to this list? Submit a PR editing this file located in `~
- [SkBee](https://github.com/ShaneBeee/SkBee/)
- [Monumenta](https://github.com/TeamMonumenta/monumenta-plugins-public/)
___
Want your plugin added to this list? Submit a PR editing this file located in `~/wiki/Plugins.md`!
-29
View File
@@ -1,29 +0,0 @@
### We will be using [this head](https://minecraft-heads.com/custom-heads/food%20&%20drinks/28194-cup-of-soda) as example.
```java
// This is the base64 texture value from the bottom of the previously mentioned website.
final String textureValue = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTQyY2M5MjAzYzkwYjg5YmRhYzFkZjI4NDE2NzI2NmI5NTNkZmViZjNjNDY5MGE3Y2QwYjE1NzkxYTYyZTU4MiJ9fX0=";
// Creating ItemStack
// For Minecraft 1.12 and above
final ItemStack item = new ItemStack(Material.SKULL_ITEM);
item.setDurability((short) 3);
// For Minecraft 1.13 and newer
final ItemStack item = new ItemStack(Material.PLAYER_HEAD);
NBT.modify(item, nbt -> {
final ReadWriteNBT skullOwnerCompound = nbt.getOrCreateCompound("SkullOwner");
// The owner UUID. Note that skulls with the same UUID but different textures will misbehave and only one texture will load.
// They will share the texture. To avoid this limitation, it is recommended to use a random UUID.
skullOwnerCompound.setUUID("Id", UUID.randomUUID());
skullOwnerCompound.getOrCreateCompound("Properties")
.getCompoundList("textures")
.addCompound()
.setString("Value", textureValue);
});
```
+40 -17
View File
@@ -1,12 +1,11 @@
To start using NB-API, you either need to depend on its plugin version, or shade (include) it inside your plugin.
> [!IMPORTANT]
> Plugin and shaded versions have different ``artifactId``. Make sure to correctly choose the one you need!
# Option 1) NBT-API as a dependency
Add the following Entries to your Gradle build at the correct location:
```groovy
compileOnly("de.tr7zw:item-nbt-api-plugin:VERSION")
```
(Get the current Version from [here](https://www.spigotmc.org/resources/nbt-api.7939/))
Add the following entries to your Gradle build at the correct locations:
```groovy
repositories {
@@ -19,7 +18,13 @@ repositories {
}
```
Finally, add the API as dependency to your ``plugin.yml``
```groovy
compileOnly("de.tr7zw:item-nbt-api-plugin:VERSION")
```
(Get the current ``VERSION`` from [here](https://modrinth.com/plugin/nbtapi/versions))
Add the API as dependency to your ``plugin.yml``:
```yml
depend: [NBTAPI]
@@ -38,16 +43,9 @@ plugins {
```
The latest version of the shadow plugin can be found [here](https://github.com/johnrengelman/shadow/releases).
<br/>
Add NBT-API to your dependencies:
```groovy
implementation("de.tr7zw:item-nbt-api:VERSION")
```
(Get the current Version from [here](https://www.spigotmc.org/resources/nbt-api.7939/))
```groovy
repositories {
...
@@ -59,7 +57,16 @@ repositories {
}
```
After this you can add the shadowjar configuration to relocate the api package:
```groovy
implementation("de.tr7zw:item-nbt-api:VERSION")
```
(Get the current ``VERSION`` from [here](https://modrinth.com/plugin/nbtapi/versions))
> [!WARNING]
> Make sure you're using ``item-nbt-api`` as ``artifactId``, never shade the ``-plugin`` artifact!
After this you can add the shadowJar configuration to relocate the API package:
```groovy
shadowJar {
@@ -67,7 +74,7 @@ shadowJar {
}
```
If you want to run the shadowJar task when the build task is executed, you can write like this:
If you want to run the shadowJar task when the build task is executed, you can use this:
```groovy
build {
@@ -75,3 +82,19 @@ build {
}
```
###### Initializing NBT-API early
If you are shading NBT-API, you may call ``NBT.preloadApi()`` during ``onEnable`` to initialize NBT-API early and check whether everything works. If you omit this step, NBT-API will be initialized on the first call to the API.
```java
@Override
public void onEnable() {
if (!NBT.preloadApi()) {
getLogger().warning("NBT-API wasn't initialized properly, disabling the plugin");
getPluginLoader().disablePlugin(this);
return;
}
// Load other things
}
```
+71 -43
View File
@@ -1,6 +1,24 @@
To start using NB-API, you either need to depend on its plugin version, or shade (include) it inside your plugin.
> [!IMPORTANT]
> Plugin and shaded versions have different ``artifactId``. Make sure to correctly choose the one you need!
# Option 1) NBT-API as a dependency
Add the following Entries to your pom at the correct location:
Add the following entries to your pom at the correct locations:
```xml
<repositories>
...
<!-- CodeMC -->
<repository>
<id>codemc-repo</id>
<url>https://repo.codemc.io/repository/maven-public/</url>
<layout>default</layout>
</repository>
...
</repositories>
```
```xml
<dependency>
@@ -11,22 +29,9 @@ Add the following Entries to your pom at the correct location:
</dependency>
```
(Get the current Version from [here](https://modrinth.com/plugin/nbtapi/versions))
(Get the current ``VERSION`` from [here](https://modrinth.com/plugin/nbtapi/versions))
```xml
<repositories>
...
<!-- CodeMC -->
<repository>
<id>codemc-repo</id>
<url>https://repo.codemc.io/repository/maven-public/</url>
<layout>default</layout>
</repository>
...
</repositories>
```
Add the API as dependency to your plugin.yml
Add the API as dependency to your ``plugin.yml``:
```yaml
depend: [NBTAPI]
@@ -34,39 +39,16 @@ depend: [NBTAPI]
# Option 2) Shading the NBT-API into your plugin
Add the following Entries to your pom at the correct location:
To include NBT-API directly in your plugin, you can use the maven shade plugin.
```xml
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>VERSION</version>
</dependency>
```
(Get the current Version from [here](https://modrinth.com/plugin/nbtapi/versions))
**IMPORTANT: This is not the same ``artifactId`` as using it as dependency! Never shade the ``-plugin`` artifact!**
```xml
<repositories>
...
<!-- CodeMC -->
<repository>
<id>codemc-repo</id>
<url>https://repo.codemc.io/repository/maven-public/</url>
<layout>default</layout>
</repository>
...
</repositories>
```
Add the plugin to the build configuration, as shown here:
```xml
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<version>3.6.0</version>
<executions>
<execution>
<id>shade</id>
@@ -88,7 +70,9 @@ Add the following Entries to your pom at the correct location:
</plugins>
```
Example:
The latest version of the shade plugin can be found [here](https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-shade-plugin).
Replace ``YOUR PACKAGE WHERE THE API SHOULD END UP`` with your own unique package. For example:
```xml
<relocation>
@@ -97,3 +81,47 @@ Example:
</relocation>
```
Then, add NBT-API to your dependencies by including the following entries to your pom at the correct locations:
```xml
<repositories>
...
<!-- CodeMC -->
<repository>
<id>codemc-repo</id>
<url>https://repo.codemc.io/repository/maven-public/</url>
<layout>default</layout>
</repository>
...
</repositories>
```
```xml
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>VERSION</version>
</dependency>
```
(Get the current ``VERSION`` from [here](https://modrinth.com/plugin/nbtapi/versions))
> [!WARNING]
> Make sure you're using ``item-nbt-api`` as ``artifactId``, never shade the ``-plugin`` artifact!
###### Initializing NBT-API early
If you are shading NBT-API, you may call ``NBT.preloadApi()`` during ``onEnable`` to initialize NBT-API early and check whether everything works. If you omit this step, NBT-API will be initialized on the first call to the API.
```java
@Override
public void onEnable() {
if (!NBT.preloadApi()) {
getLogger().warning("NBT-API wasn't initialized properly, disabling the plugin");
getPluginLoader().disablePlugin(this);
return;
}
// Load other things
}
```
+403 -59
View File
@@ -1,88 +1,432 @@
## Using the ``NBT`` class (prefered)
## General usage
### Basics overview
Most of the things are exposed inside the [NBT](https://tr7zw.github.io/Item-NBT-API/v2-api/de/tr7zw/changeme/nbtapi/NBT.html) class. Make sure to explore the Javadoc, or ask your IDE for suggestions!
#### Basic getting and setting of data
[ReadableNBT](https://tr7zw.github.io/Item-NBT-API/v2-api/de/tr7zw/changeme/nbtapi/iface/ReadableNBT.html) and [ReadWriteNBT](https://tr7zw.github.io/Item-NBT-API/v2-api/de/tr7zw/changeme/nbtapi/iface/ReadWriteNBT.html) are used to read/write nbt:
```java
// Setting data on ItemStacks/Entities/BlockEntities
// Creating a new empty NBT tag
ReadWriteNBT nbt = NBT.createNBTObject();
// Setting nbt
nbt.setString("Stringtest", "Teststring");
nbt.setInteger("Inttest", 42);
nbt.setDouble("Doubletest", 1.5);
nbt.setBoolean("Booleantest", true);
// More are available! Ask your IDE, or see Javadoc for suggestions!
// Getting nbt
String s1 = nbt.getString("Stringtest");
int i1 = nbt.getInteger("Inttest");
double d = nbt.getDouble("Doubletest");
boolean b = nbt.getBoolean("Booleantest");
// Or, alternatively
String s2 = nbt.getOrDefault("Stringtest", "fallback_value");
Integer i2 = nbt.getOrNull("Inttest", Integer.class);
// Keys manipulation
nbt.getKeys(); // Get all Tags
nbt.hasTag("key"); // Check whether the Tag exists
nbt.hasTag("key", NbtType.NBTTagString); // Check whether the Tag exists and matches the type
nbt.removeKey("key"); // Remove the Tag
NBTType nbtType = nbt.getType("key"); // Get the type of the Tag
// Subtag compounds
nbt.getCompound("subtag"); // Get a subtag, or null
nbt.getOrCreateCompound("subtag"); // Get or create a subtag
```
#### Converting NBT to String and the String back to NBT
```java
// Parse Mojang-Json string to nbt
ReadWriteNBT nbt = NBT.parseNBT("{Health:20.0f,Motion:[0.0d,10.0d,0.0d],Silent:1b}");
// Get the NBT back as a Mojang-Json string (works with any NBT object)
String json = nbt.toString();
// Turn back into nbt again
ReadWriteNBT nbt2 = NBT.parseNBT(json);
```
#### Merging Compounds
You can "merge" the data from any given Compound onto some other Compound. This will overwrite the tags with the same name.
Example:
`Tag1: {Num1:1, Num2:2} Tag2: {Num1:7, Num3:3}`
After merging Tag2 on Tag1:
```java
tag1.mergeCompound(tag2);
```
`Tag1: {Num1:7, Num2:2, Num3:3} Tag2: {Num1:7, Num3:3}`
#### Resolving data
To simplify working with deeply nested NBT, resolve methods allow directly getting or working with these nested tags.
Compounds are separated by dots ``.`` In case you need a ``.`` inside a key, it can be escaped with a backslash ``\``.
```java
// For example, the following code:
nbt.resolveOrCreateCompound("foo.bar.baz");
// Will get/create the same subtag compound as:
nbt.getOrCreateCompound("foo").getOrCreateCompound("bar").getOrCreateCompound("baz");
// Get compound if exists, or null otherwise
nbt.resolveCompound("foo.some.key.baz");
// Sets foo/bar/baz/test to 42
nbt.resolveOrCreateCompound("foo.bar.baz").setInteger("test", 42);
// Example of a key with a . in it. Sets the key foo/some.key/baz/other to 123
nbt.resolveOrCreateCompound("foo.some\\.key.baz").setInteger("other", 123);
// Similarly, you may also fetch values from nested compounds
String s = nbt.resolveOrDefault("foo.bar.Stringtest", "fallback_value");
Integer i = nbt.resolveOrNull("foo\\.bar.baz.Inttest", Integer.class);
```
#### Accessing/creating lists and their data
> [!NOTE]
> The lists will be created if they do not exist, there are no setters for lists!
```java
// Get or create a string list
ReadWriteNBTList<String> stringList = nbt.getStringList("list_key");
stringList.add("value");
// Get the list type, NBTTagString in this case
NBTType type = nbt.getListType("list_key");
// You can obtain the value back just like with normal Lists
nbt.getStringList("list_key").get(0);
// Or by fetching it
nbt.resolveOrNull("list_key[0]", String.class); // Get the first value in list
// You can also use negative number to get the value from the end of the list/array
nbt.resolveOrDefault("list_key[-1]", "fallback_value"); // Get the last value in list, or use the default
// NBT compound lists
ReadWriteNBTCompoundList nbtList = nbt.getOrCreateCompound("foo").getCompoundList("other_key");
ReadWriteNBT nbtListEntry = addCompound();
nbtListEntry.setBoolean("bar", true);
// You can fetch compounds in lists
nbt.resolveCompound("foo.other_key[0]"); // Get the first compound in list, or null
nbt.resolveOrCreateCompound("foo.other_key[1]"); // Get the second compound in list, or create it
// Or fetch data from them
boolean bar = nbt.resolveOrDefault("foo.other_key[0].bar", false);
```
### Working with items
You can read/write nbt data on items using ``NBT.get``/``NBT.modify`` methods.
```java
// Setting data
NBT.modify(itemStack, nbt -> {
nbt.setString("Stringtest", "Teststring");
nbt.setInteger("Inttest", 42);
nbt.setDouble("Doubletest", 1.5d);
nbt.setBoolean("Booleantest", true);
//More are available! Ask your IDE/Javadocs for suggestions!
// More are available! Ask your IDE, or see Javadoc for suggestions!
});
// Getting data from ItemStacks
String string = NBT.get(itemStack, nbt -> nbt.getString("Stringtest"));
// Reading data
NBT.get(itemStack, nbt -> {
String stringTest = nbt.getString("Stringtest");
int intTest = nbt.getOrDefault("Inttest", 0);
// Do more stuff
});
// Getting data
String string = NBT.get(itemStack, nbt -> (String) nbt.getString("Stringtest"));
// Modifying and getting data
int someValue = NBT.modify(itemStack, nbt -> {
int i = nbt.getOrDefault("key", 0) + 1;
nbt.setInteger(i);
return i;
});
```
###### ItemMeta usage
> [!WARNING]
> Never mix the usage of ItemMeta and NBT.
```java
// Updating ItemMeta using NBT
NBT.modify(itemStack, nbt -> {
nbt.setInteger("kills", nbt.getOrDefault("kills", 0) + 1);
nbt.modifyMeta((meta, readOnlyNbt) -> { // do not modify the nbt while modifying the meta!
nbt.modifyMeta((meta, readOnlyNbt) -> { // Do not modify the nbt while modifying the meta!
meta.setDisplayName("Kills: " + readOnlyNbt.getOrDefault("kills", 0));
});
//Do more stuff
// Do more stuff
});
```
// Gameprofile to NBT
ReadWriteNBT nbt = NBT.gameProfileToNBT(profile);
// NBT to Gameprofile
GameProfile profile = NBT.nbtToGameProfile(nbt);
// ItemStack to NBT
###### Changing vanilla item nbt on 1.20.5+
> [!IMPORTANT]
> Since Minecraft 1.20.5 ItemStacks no longer have vanilla nbt during runtime.
> Any calls like ``NBT.get`` or ``NBT.modify`` will access only the item's ``custom_data`` component.
>
> As a workaround, you may use the following code:
```java
// NOTE: This code is only for 1.20.5+!
NBT.modifyComponents(item, nbt -> {
nbt.setString("minecraft:custom_name", "{\"extra\":[\"foobar\"],\"text\":\"\"}");
});
```
### Working with entities and block entities
Working with entities and block entities is similar to working with items.
#### Accessing vanilla nbt
The example code for entities is applicable for block entities too.
```java
// Obtain data
boolean silent = NBT.get(entity, nbt -> (boolean) nbt.getBoolean("Silent"));
// Modify data
NBT.modify(entity, nbt -> {
nbt.setBoolean("Silent", true);
nbt.setByte("CanPickUpLoot", (byte) 1);
});
```
#### Accessing custom data
For reading/storing custom data on (block-)entities, you should use methods that end with PersistentData.
> [!IMPORTANT]
> When working with block entities, make sure that the block entity exists in the world.
>
> For example, you may not be able to add data to a chest in `BlockPlaceEvent` because the chest hasn't been placed yet. In such case, you can delay your actions by one tick or set the block to chest manually.
```java
// Obtain data
boolean test = NBT.getPersistentData(entity, nbt -> (boolean) nbt.getBoolean("custom_key"));
// Modify data
NBT.modifyPersistentData(entity, nbt -> {
nbt.setBoolean("custom_key", true);
nbt.setByte("custom_byte", (byte) 1);
});
```
> [!NOTE]
> If you plan to store some data for players, you might also consider using an external storage instead to not clutter the players' data files inside the world folder. Since any data written to the persistent storage is there forever, you can leave redundant data behind when your plugin is removed, but it's perfectly fine to store data in there otherwise.
>
> Storage solutions like per-player [NBT files](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API#nbt-files) might be more than enough (and is basically what vanilla does, but you'll have your own file instead of using the one inside the world). Cache the file's data on join and save on quit/server shutdown, optionally adding auto saving.
#### Simulate the "/data merge" command
Applicable for items/block entities/entities/etc.
```java
NBT.modify(zombie, nbt -> {
nbt.mergeCompound(NBT.parseNBT("{Silent:1b,Invulnerable:1b,Glowing:1b,IsBaby:1b}"));
});
```
### Working with blocks
You can store data in block entities (block entities like chest, furnace, etc.) using the examples from the section above, but normal blocks do not have the nbt data.
Thus, you have to use your own block data storage to store custom block data.
You can store data inside Chunks since 1.16.4, and NBT-API allows you to do so by using ``NBTChunk``:
```java
ReadWriteNBT nbt = new NBTChunk(chunk).getPersistentDataContainer();
```
Similarly, there is ``NBTBlock``, which allows you to store block data inside chunk's data.
```java
// Block's data will be stored in Chunk's data in "blocks.x_y_z" subtag
ReadWriteNBT nbt = new NBTBlock(block).getData();
```
**However**, keep in mind that this data is linked only to the location, and if the block gets broken/changed/exploded/moved/etc., the data will still be on that location unless manually cleared/moved!
Moreover, since the data is stored inside a Chunk, this will increase the chunk's size on the disk.
## Extras
> [!TIP]
> Besides this page, you may also take a look at some code examples at [example usages](https://github.com/tr7zw/Item-NBT-API/wiki/Example-Usages).
### NBT files
```java
// Creating nbt file
// NBTFile will automatically create the file if it does not exist
NBTFile file = new NBTFile(new File("directory"), "test.nbt"); // Will be created at ./directory/test.nbt
// Setting data
file.setString("foo", "bar");
// Saving file
file.save();
// Alternatively, you may use helper methods in NBTFile class
// To read the file without creating it if does not exist:
ReadWriteNBT nbt = NBTFile.readFrom(file);
// To save nbt to the file:
NBTFile.saveTo(file, nbt);
```
### Converting Minecraft Objects to NBT and Strings
The basic idea is that you can convert data into different representations:
Minecraft Objects <-> NBT <-> String (Mojang-Json)
#### Items
While ``NBT.get/modify`` allows you to modify item's direct nbt (or only the ``custom_data`` container since 1.20.5), the ItemStack object nbt represents the item's serialized data. It includes item type, amount and all extra item tags.
For example, when ``NBT.get`` looks like this:
`{foo:"bar",points:12,test:1b}`
The ItemStack object nbt from ``NBT.itemStackToNBT`` may look like this:
`{components:{"minecraft:custom_data":{foo:"bar",points:12,test:1b}},count:2,id:"minecraft:stone"}`
Or like this in versions prior to 1.20.5:
`{Count:2b,id:"minecraft:stone",tag:{foo:"bar",points:12,test:1b}}`
###### Serializing/deserializing items
```java
// Saving
ReadWriteNBT nbt = NBT.itemStackToNBT(itemStack);
// NBT to ItemStack
ItemStack itemStack = NBT.itemStackFromNBT(nbt);
// ItemStack Array to NBT
ReadWriteNBT nbt = NBT.itemStackArrayToNBT(itemStacks);
// NBT to ItemStack Array
// Restoring
ItemStack itemStack = NBT.itemStackFromNBT(nbt);
ItemStack[] itemStacks = NBT.itemStackArrayFromNBT(nbt);
// Creating a new NBT tag
ReadWriteNBT nbt = NBT.createNBTObject();
// Parsing a Mojang-Json String to NBT
// Reminder (NBT <-> String)
String json = nbt.toString();
ReadWriteNBT nbt = NBT.parseNBT(json);
```
## Old style of creating a NBT Wrapper
#### Entities and block entities
```java
NBTItem nbti = new NBTItem(ItemStack);
NBTEntity nbtent = new NBTEntity(Entity); // Vanilla tags only!
NBTTileEntity tent = new NBTTileEntity(block.getState()); // Vanilla tags only!
NBTFile file = new NBTFile(new File("directory"), "test.nbt")); // Will be created at ./directory/test.nbt
NBTContainer container = new NBTContainer(json); // Parse in json
NBTContainer container = new NBTContainer(); // Empty NBTCompound
// Saving
ReadWriteNBT entityNbt = NBT.createNBTObject();
NBT.get(entity, entityNbt::mergeCompound);
// Restoring
NBT.modify(entity, nbt -> {
// You might also want to filter out entityNbt first,
// e.g. remove some data like location, uuid, entityId, etc.
nbt.mergeCompound(entityNbt);
});
```
## Using the wrapper(NBTCompound/)
#### Game profiles
```java
//Set
nbti.setString("Stringtest", "Teststring");
nbti.setInteger("Inttest", 42);
nbti.setDouble("Doubletest", 1.5d);
nbti.setBoolean("Booleantest", true);
//More are available! Ask your IDE for suggestions! Don't use deprecated methods!
//Access/create lists
nbtent.getCompoundList("Attributes");
nbtent.getStringList("Attributes");
//The list will be created if it doesn't exist, there is no setter for lists!
//Get
nbti.getString("Stringtest");
nbti.getInteger("Inttest");
nbti.getDouble("Doubletest");
nbti.getBoolean("Booleantest");
nbti.getKeys(); //Get all Tags
nbti.hasTag("Key");
nbti.removeKey("Key");
nbti.getOrCreateCompound("subtag"); // Get or create a subtag
NBTCompound comp = nbti.getCompound("subtag"); // Get the tag or null
B.mergeCompound(A); // Merge the data from compound A into B (Like the /data merge command)
comp.toString(); // Get the nbt as a Mojang-Json string
// Saving
ReadWriteNBT nbt = NBT.gameProfileToNBT(profile);
// Restoring
GameProfile profile = NBT.gameProfileFromNBT(nbt);
```
### Interface proxies
You may define your own interfaces extending ``NBTProxy`` to create wrappers around nbt.
Methods starting with ``has``/``get``/``set`` will be interpreted as their respective calls.
```java
interface TestInterface extends NBTProxy {
// Runs: return nbt.hasTag("kills");
boolean hasKills();
// Runs: nbt.setInteger("kills", amount);
void setKills(int amount);
// Runs: return nbt.getInteger("kills");
int getKills();
// Also supported
default void addKill() {
setKills(getKills() + 1);
}
}
```
Getters are also allowed to return other interfaces extending ``NBTProxy``.
And by using ``@NBTTarget`` annotation you may have a more gradual control over data. It allows setting the type of the method (``has``/``get``/``set``) and the data key.
```java
interface TestInterface extends NBTProxy {
// Will get PointsInterface from data in "other" key
@NBTTarget(type = Type.GET, value = "other")
PointsInterface getOtherInterface();
}
interface PointsInterface extends NBTProxy {
int getPoints();
void setPoints(int points);
}
```
To support other data types like ItemStacks, you need to override the init method and register appropriate handlers.
```java
interface TestInterface extends NBTProxy {
@Override
default void init() {
registerHandler(ItemStack.class, NBTHandlers.ITEM_STACK);
registerHandler(ReadableNBT.class, NBTHandlers.STORE_READABLE_TAG);
registerHandler(ReadWriteNBT.class, NBTHandlers.STORE_READWRITE_TAG);
}
ItemStack getItem();
void setItem(ItemStack item);
ReadWriteNBT getBlockStateTag();
void setBlockStateTag(ReadableNBT blockState);
}
```
``NBTHandlers`` class contains some pre-defined handlers.
###### Custom handlers
If you need to support custom data types that aren't available in ``NBTHandlers``, you can write your own by creating a new ``NBTHandler``.
You can refer to [NBTHandlers](https://github.com/tr7zw/Item-NBT-API/blob/master/item-nbt-api/src/main/java/de/tr7zw/changeme/nbtapi/handler/NBTHandlers.java) class to see how the default implementations are done.
### Data fixer utils
``DataFixerUtil`` allows updating nbt from older versions to more recent ones.
For example, given the input from 1.12.2:
`{Count:42,id:"cobblestone",tag:{display:{Name:"test"},ench:[{id:34,lvl:3}]}}`
You can update it to 1.20.6:
`{components:{"minecraft:custom_name":'{"text":"test"}',"minecraft:enchantments":{levels:{"minecraft:unbreaking":3}}},count:42,id:"minecraft:cobblestone"}`
By using the following code:
```java
DataFixerUtil.fixUpItemData(nbt, DataFixerUtil.VERSION1_12_2, DataFixerUtil.VERSION1_20_6);
```
You can also use ``DataFixerUtil.getCurrentVersion()`` to update the data to whatever version the server is running.
@@ -1,14 +0,0 @@
```java
Zombie zombie = (Zombie) b.getWorld().spawnEntity(b.getLocation().add(0, 1, 0), EntityType.ZOMBIE);
NBT.modify(zombie, nbt -> {
nbt.setByte("CanPickUpLoot", (byte) 1);
ReadWriteNBTCompoundList list = nbt.getCompoundList("Attributes");
for(int i = 0; i < list.size(); i++){
ReadWriteNBT lc = list.get(i);
if(lc.getString("Name").equals("generic.attackDamage")){
lc.setDouble("Base", 0.5d);
}
}
});
```
+2 -2
View File
@@ -1,5 +1,5 @@
[tr7zw](https://github.com/tr7zw)
[SpigotMC](https://www.spigotmc.org/resources/nbt-api.7939/)
[Modrinth](https://modrinth.com/plugin/nbtapi)
[Bukkit](https://dev.bukkit.org/projects/nbt-api)
[Hangar](https://hangar.papermc.io/tr7zw/NBTAPI)
[SpigotMC](https://www.spigotmc.org/resources/nbt-api.7939/)
[Bukkit](https://dev.bukkit.org/projects/nbt-api)
+12 -9
View File
@@ -1,21 +1,24 @@
[Home](https://github.com/tr7zw/Item-NBT-API/wiki)
[Using the NBT API](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API)
[Using Maven](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Maven) /
[Using Gradle](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Gradle)
[FAQ](https://github.com/tr7zw/Item-NBT-API/wiki/FAQ)
## Code Examples
### General
* [Converting Minecraft Objects to NBT and Strings](https://github.com/tr7zw/Item-NBT-API/wiki/Converting-Minecraft-Objects-to-NBT-and-Strings)
* [Merging Compounds](https://github.com/tr7zw/Item-NBT-API/wiki/Merging-Compounds-(Copy-the-data-from-one-onto-another-compound))
* [Basics](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API)
* [Items](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API#working-with-items)
* [Block-Entities/Entities](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API#working-with-entities-and-block-entities)
* [Blocks](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API#working-with-blocks)
### Items
### Extras
* [Set a skull's skin using NBT API](https://github.com/tr7zw/Item-NBT-API/wiki/Set-a-skull's-skin-using-NBT-API)
### Entities
* [Zombie that can pick up loot and does 0.5 hearths of damage](https://github.com/tr7zw/Item-NBT-API/wiki/Zombie-that-can-pick-up-loot-and-does-0.5-hearths-of-damage)
* [Example usages](https://github.com/tr7zw/Item-NBT-API/wiki/Example-Usages)
* [NBT files](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API#nbt-files)
* [NBT objects](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API#converting-minecraft-objects-to-nbt-and-strings)
* [Interface proxies](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API#interface-proxies)
* [Data fixer utils](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API#data-fixer-utils)