mirror of
https://github.com/tr7zw/Item-NBT-API.git
synced 2026-11-14 04:42:02 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
35f541d3db | ||
|
|
d4ee3b998c | ||
|
|
2902dca5a5 | ||
|
|
1c1e3c8664 | ||
|
|
7f8f021ced | ||
|
|
98ed1850f6 | ||
|
|
764e01503d | ||
|
|
43d8e2a351 | ||
|
|
689cd4fa3b | ||
|
|
c8f68f8b3b | ||
|
|
e52ba209e6 | ||
|
|
418f5bea07 | ||
|
|
1392e72a8a | ||
|
|
dc39d1d8ef | ||
|
|
a974142a55 | ||
|
|
f014e71020 | ||
|
|
da6be72d29 | ||
|
|
d9a93e9306 | ||
|
|
ba374fe69c | ||
|
|
aa35ee8333 | ||
|
|
3bb0bdd74c | ||
|
|
f3af749b11 | ||
|
|
d81c2b4e8e | ||
|
|
94192feb8f | ||
|
|
af3d9c8502 | ||
|
|
ae98859524 | ||
|
|
70f0bb62f9 | ||
|
|
505e172955 | ||
|
|
d2b2b6a506 | ||
|
|
e2e8aad70a | ||
|
|
4874366e30 | ||
|
|
d2de90ee25 | ||
|
|
a0f93e575e | ||
|
|
b339c9e9c2 | ||
|
|
3425a6672d | ||
|
|
67616266da | ||
|
|
b08e4aa12f | ||
|
|
27411e90da | ||
|
|
73776cfec4 | ||
|
|
bd674e31c0 | ||
|
|
3405ffe0a3 | ||
|
|
f1317bcb04 | ||
|
|
4a32343b95 | ||
|
|
3de6ed83eb | ||
|
|
e5bdce73ea | ||
|
|
410e88a35b | ||
|
|
e3142b4869 | ||
|
|
243a5c2bcd | ||
|
|
045c710366 | ||
|
|
4cd118671f | ||
|
|
d86c91f2e6 | ||
|
|
f8736c8188 | ||
|
|
b3aec54205 | ||
|
|
0f926998f6 | ||
|
|
3a44a5e989 | ||
|
|
30b931945c | ||
|
|
88d8629541 | ||
|
|
00ae0448f4 | ||
|
|
ce26e180e6 | ||
|
|
c939105e45 | ||
|
|
2079123a42 | ||
|
|
31b17fe9c9 | ||
|
|
b565902006 | ||
|
|
5280ba82a2 | ||
|
|
522f732ed1 | ||
|
|
ac84a4d69a | ||
|
|
d7e18c1cb6 | ||
|
|
ffa612634a | ||
|
|
739682122b | ||
|
|
2e20af40e5 | ||
|
|
e6527515be | ||
|
|
e6f33a35ae | ||
|
|
39801ada18 | ||
|
|
75fab7622a | ||
|
|
33eef1bcf1 | ||
|
|
877a42fd06 | ||
|
|
0a7e560e2e | ||
|
|
174728a681 | ||
|
|
79ba1dd275 | ||
|
|
25c59b0eae | ||
|
|
0057d3f2e8 | ||
|
|
59c67a3f0b | ||
|
|
3ec606ae21 | ||
|
|
ff0a94f279 | ||
|
|
53216d3b7d | ||
|
|
7cf23201ce | ||
|
|
fe1d586f44 |
No files matched your search
@@ -8,7 +8,7 @@ updates:
|
||||
ignore:
|
||||
- dependency-name: com.github.ekryd.sortpom:sortpom-maven-plugin
|
||||
versions:
|
||||
- 2.13.1
|
||||
- 2.13.3-SNAPSHOT
|
||||
- 2.14.0
|
||||
- 2.14.1
|
||||
- 2.15.0
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
- name: Copy artifacts
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p artifacts/v2-api && cp -r item-nbt-api/target/apidocs/* artifacts/v2-api
|
||||
mkdir -p artifacts/v2-api && cp -r item-nbt-api/target/reports/apidocs/* artifacts/v2-api
|
||||
mkdir -p artifacts/v2-plugin && cp -r item-nbt-plugin/target/apidocs/* artifacts/v2-plugin
|
||||
- name: Deploy 🚀
|
||||
uses: JamesIves/github-pages-deploy-action@v4.4.1
|
||||
|
||||
@@ -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
@@ -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:[, 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
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>item-nbt-parent</artifactId>
|
||||
<version>2.13.0</version>
|
||||
<version>2.15.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>item-nbt-api</artifactId>
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package de.tr7zw.changeme.nbtapi;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -11,6 +15,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.iface.NBTFileHandle;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteItemNBT;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadableItemNBT;
|
||||
@@ -19,6 +24,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 +40,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
|
||||
@@ -158,9 +204,9 @@ public class NBT {
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes a block entity and a function that takes a ReadableNBT and returns
|
||||
* a generic type T, and returns the result of the function, applied to the
|
||||
* block entities persistent data container
|
||||
* It takes a block entity and a function that takes a ReadableNBT and returns a
|
||||
* generic type T, and returns the result of the function, applied to the block
|
||||
* entities persistent data container
|
||||
*
|
||||
* @param blockState The block state of the block you want to get the data from.
|
||||
* @param getter A function that takes a ReadableNBT and returns a value of
|
||||
@@ -227,17 +273,17 @@ public class NBT {
|
||||
nbtEnt.setClosed();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* It takes an ItemStack and a Consumer<ReadWriteNBT>, and then applies
|
||||
* the Consumer to the ItemStacks Components as NBT. This is for 1.20.5+ only.
|
||||
* This method is quiet expensive, so don't overuse it.
|
||||
* This method is quite expensive, so don't overuse it.
|
||||
*
|
||||
* @param item The item you want to modify the components of
|
||||
* @param consumer The consumer that will be used to modify the components.
|
||||
*/
|
||||
public static void modifyComponents(ItemStack item, Consumer<ReadWriteNBT> consumer) {
|
||||
if(!MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
if (!MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
throw new NbtApiException("This method only works for 1.20.5+!");
|
||||
}
|
||||
ReadWriteNBT nbti = NBT.itemStackToNBT(item);
|
||||
@@ -245,18 +291,18 @@ public class NBT {
|
||||
ItemStack tmp = NBT.itemStackFromNBT(nbti);
|
||||
item.setItemMeta(tmp.getItemMeta());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* It takes an ItemStack and a Consumer<ReadWriteNBT>, and then applies
|
||||
* the Consumer to the ItemStacks Components as NBT. This is for 1.20.5+ only.
|
||||
* This method is quiet expensive, so don't overuse it.
|
||||
* This method is quite expensive, so don't overuse it.
|
||||
*
|
||||
* @param item The item you want to modify the components of
|
||||
* @param function The consumer that will be used to modify the components.
|
||||
* @return The return type is the same as the return type of the function.
|
||||
*/
|
||||
public static <T> T modifyComponents(ItemStack item, Function<ReadWriteNBT, T> function) {
|
||||
if(!MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
if (!MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
throw new NbtApiException("This method only works for 1.20.5+!");
|
||||
}
|
||||
ReadWriteNBT nbti = NBT.itemStackToNBT(item);
|
||||
@@ -266,6 +312,39 @@ public class NBT {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an ItemStack and a Consumer<ReadWriteNBT>, and then applies
|
||||
* the Consumer to the ItemStacks Components as NBT. This is for 1.20.5+ only.
|
||||
* This method is quite expensive, try to cache the results/use it smartly.
|
||||
*
|
||||
* @param item The item you want to read the components of
|
||||
* @param consumer The consumer that will be used to read the components.
|
||||
*/
|
||||
public static void getComponents(ItemStack item, Consumer<ReadableNBT> consumer) {
|
||||
if (!MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
throw new NbtApiException("This method only works for 1.20.5+!");
|
||||
}
|
||||
ReadWriteNBT nbti = NBT.itemStackToNBT(item);
|
||||
consumer.accept(nbti.getOrCreateCompound("components"));
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an ItemStack and a Consumer<ReadWriteNBT>, and then applies
|
||||
* the Consumer to the ItemStacks Components as NBT. This is for 1.20.5+ only.
|
||||
* This method is quite expensive, try to cache the results/use it smartly.
|
||||
*
|
||||
* @param item The item you want to read the components of
|
||||
* @param function The consumer that will be used to read the components.
|
||||
* @return The return type is the same as the return type of the function.
|
||||
*/
|
||||
public static <T> T getComponents(ItemStack item, Function<ReadableNBT, T> function) {
|
||||
if (!MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
throw new NbtApiException("This method only works for 1.20.5+!");
|
||||
}
|
||||
ReadWriteNBT nbti = NBT.itemStackToNBT(item);
|
||||
return function.apply(nbti.getOrCreateCompound("components"));
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an entity and a function that takes a ReadWriteNBT and applies the
|
||||
* function to the entity
|
||||
@@ -450,12 +529,70 @@ public class NBT {
|
||||
* It takes a nbt json string, and returns a ReadWriteNBT object
|
||||
*
|
||||
* @param nbtString The NBT string to parse.
|
||||
* @return A new NBTContainer object.
|
||||
* @return A new ReadWriteNBT object.
|
||||
*/
|
||||
public static ReadWriteNBT parseNBT(String nbtString) {
|
||||
return new NBTContainer(nbtString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads in an NBT stream and returns a ReadWriteNBT object
|
||||
*
|
||||
* @param stream The NBT stream to read.
|
||||
* @return A new ReadWriteNBT object.
|
||||
*/
|
||||
public static ReadWriteNBT readNBT(InputStream stream) {
|
||||
return new NBTContainer(stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for other developers using NMS. Allows to wrap any
|
||||
* net.minecraft.nbt.CompoundTag to a NBTAPI ReadWriteNBT object.
|
||||
*
|
||||
* @param nmsNbtTag Needs to be a valid net.minecraft.nbt.CompoundTag
|
||||
* @return A new ReadWriteNBT object.
|
||||
*/
|
||||
public static ReadWriteNBT wrapNMSTag(Object nmsNbtTag) {
|
||||
return new NBTContainer(nmsNbtTag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a NBTFileHandle that uses @param file to store its data. If this file
|
||||
* exists, the data will be loaded, otherwise a new file gets created.
|
||||
*
|
||||
* @param file
|
||||
* @throws IOException
|
||||
*/
|
||||
public static NBTFileHandle getFileHandle(File file) throws IOException {
|
||||
return new NBTFile(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads NBT data from the provided file.
|
||||
* <p>
|
||||
* Returns an empty tag if the file does not exist.
|
||||
*
|
||||
* @param file file to read
|
||||
* @return ReadWriteNBT of the files data
|
||||
* @throws IOException exception
|
||||
*/
|
||||
public static ReadWriteNBT readFile(File file) throws IOException {
|
||||
return NBTFile.readFrom(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves NBT data to the provided file.
|
||||
* <p>
|
||||
* Will fully override the file if it already exists.
|
||||
*
|
||||
* @param file file
|
||||
* @param nbt NBT data
|
||||
* @throws IOException exception
|
||||
*/
|
||||
public static void writeFile(File file, ReadWriteNBT nbt) throws IOException {
|
||||
NBTFile.saveTo(file, (NBTCompound) nbt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a read only proxy class for NBT, given an annotated interface.
|
||||
*
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
@@ -19,6 +20,7 @@ import de.tr7zw.changeme.nbtapi.iface.ReadableNBT;
|
||||
import de.tr7zw.changeme.nbtapi.utils.CheckUtil;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.changeme.nbtapi.utils.PathUtil;
|
||||
import de.tr7zw.changeme.nbtapi.utils.UUIDUtil;
|
||||
import de.tr7zw.changeme.nbtapi.utils.PathUtil.PathSegment;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.Forge1710Mappings;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
|
||||
@@ -98,10 +100,13 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
return readOnlyCache;
|
||||
}
|
||||
Object rootnbttag = getCompound();
|
||||
if (rootnbttag instanceof Optional<?>) {
|
||||
rootnbttag = ((Optional<Object>) rootnbttag).orElse(null);
|
||||
}
|
||||
if (rootnbttag == null) {
|
||||
return null;
|
||||
}
|
||||
if (!NBTReflectionUtil.valideCompound(this))
|
||||
if (!NBTReflectionUtil.validCompound(this))
|
||||
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
|
||||
Object workingtag = NBTReflectionUtil.getToCompount(rootnbttag, this);
|
||||
if (readOnly) {
|
||||
@@ -657,7 +662,9 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
public void setUUID(String key, UUID value) {
|
||||
try {
|
||||
writeLock.lock();
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R1)) {
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4)) {
|
||||
setIntArray(key, UUIDUtil.uuidToIntArray(value));
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R1)) {
|
||||
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_UUID, key, value);
|
||||
} else {
|
||||
setString(key, value.toString());
|
||||
@@ -678,10 +685,13 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
public UUID getUUID(String key) {
|
||||
try {
|
||||
readLock.lock();
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R1)
|
||||
&& getType(key) == NBTType.NBTTagIntArray) {
|
||||
NBTType type = getType(key);
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4) && type == NBTType.NBTTagIntArray) {
|
||||
return UUIDUtil.uuidFromIntArray(getIntArray(key));
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R1)
|
||||
&& type == NBTType.NBTTagIntArray) {
|
||||
return (UUID) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_UUID, key);
|
||||
} else if (getType(key) == NBTType.NBTTagString) {
|
||||
} else if (type == NBTType.NBTTagString) {
|
||||
try {
|
||||
return UUID.fromString(getString(key));
|
||||
} catch (IllegalArgumentException ex) {
|
||||
@@ -786,7 +796,7 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
if (getType(name) != NBTType.NBTTagCompound)
|
||||
return null;
|
||||
NBTCompound next = new NBTCompound(this, name, readOnly);
|
||||
if (NBTReflectionUtil.valideCompound(next))
|
||||
if (NBTReflectionUtil.validCompound(next))
|
||||
return next;
|
||||
return null;
|
||||
} finally {
|
||||
@@ -1343,7 +1353,13 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
Object nbtbase = NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET, name);
|
||||
if (nbtbase == null)
|
||||
return null;
|
||||
return NBTType.valueOf((byte) ReflectionMethod.COMPOUND_OWN_TYPE.run(nbtbase));
|
||||
return NBTType.valueOf((byte) ReflectionMethod.COMPOUND_OWN_TYPE_LEGACY.run(nbtbase));
|
||||
}
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4)) {
|
||||
Object o = NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET, name);
|
||||
if (o == null)
|
||||
return null;
|
||||
return NBTType.fromName((String)ReflectionMethod.TAGTYPE_GET_NAME.run(ReflectionMethod.TAGTYPE_OWN_TYPE.run(o)));
|
||||
}
|
||||
Object o = NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_TYPE, name);
|
||||
if (o == null)
|
||||
@@ -1460,7 +1476,107 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected static boolean isEqual(NBTCompound compA, NBTCompound compB, String key) {
|
||||
@Override
|
||||
public NBTCompound extractDifference(ReadableNBT other) {
|
||||
if (this == other)
|
||||
return new NBTContainer();
|
||||
|
||||
if (other instanceof NBTCompound) {
|
||||
return saveDiff(new NBTContainer(), this, (NBTCompound) other);
|
||||
} else {
|
||||
throw new NbtApiException("Unknown NBT object: " + other);
|
||||
}
|
||||
}
|
||||
|
||||
private static NBTCompound saveDiff(NBTCompound saveTo, NBTCompound compA, NBTCompound compB) {
|
||||
for (String key : compA.getKeys()) {
|
||||
saveDiff(saveTo, compA, compB, key);
|
||||
}
|
||||
return saveTo;
|
||||
}
|
||||
|
||||
private static void saveDiff(NBTCompound saveTo, NBTCompound compA, NBTCompound compB, String key) {
|
||||
boolean typeMismatch = compA.getType(key) != compB.getType(key);
|
||||
switch (compA.getType(key)) {
|
||||
case NBTTagByte:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setByte(key, compA.getByte(key));
|
||||
}
|
||||
return;
|
||||
case NBTTagByteArray:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setByteArray(key, compA.getByteArray(key));
|
||||
}
|
||||
return;
|
||||
case NBTTagCompound: {
|
||||
NBTCompound tmp1 = compA.getCompound(key);
|
||||
if (tmp1 == null) return;
|
||||
if (typeMismatch) {
|
||||
saveTo.addCompound(key).mergeCompound(tmp1);
|
||||
} else {
|
||||
NBTCompound tmp2 = compB.getCompound(key);
|
||||
if (tmp2 == null) {
|
||||
saveTo.addCompound(key).mergeCompound(tmp1);
|
||||
return;
|
||||
}
|
||||
NBTCompound tmpDiff = tmp1.extractDifference(tmp2);
|
||||
if (!tmpDiff.getKeys().isEmpty()) {
|
||||
saveTo.addCompound(key).mergeCompound(tmpDiff);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
case NBTTagDouble:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setDouble(key, compA.getDouble(key));
|
||||
}
|
||||
return;
|
||||
case NBTTagEnd:
|
||||
return; // ??
|
||||
case NBTTagFloat:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setFloat(key, compA.getFloat(key));
|
||||
}
|
||||
return;
|
||||
case NBTTagInt:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setInteger(key, compA.getInteger(key));
|
||||
}
|
||||
return;
|
||||
case NBTTagIntArray:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setIntArray(key, compA.getIntArray(key));
|
||||
}
|
||||
return;
|
||||
case NBTTagList:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.set(key, NBTReflectionUtil.getEntry(compA, key));
|
||||
}
|
||||
return;
|
||||
case NBTTagLong:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setLong(key, compA.getLong(key));
|
||||
}
|
||||
return;
|
||||
case NBTTagShort:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setShort(key, compA.getShort(key));
|
||||
}
|
||||
return;
|
||||
case NBTTagString:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setString(key, compA.getString(key));
|
||||
}
|
||||
return;
|
||||
case NBTTagLongArray:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setLongArray(key, compA.getLongArray(key));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isEqual(NBTCompound compA, NBTCompound compB, String key) {
|
||||
if (compA.getType(key) != compB.getType(key))
|
||||
return false;
|
||||
switch (compA.getType(key)) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package de.tr7zw.changeme.nbtapi;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBTCompoundList;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadableNBT;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
|
||||
@@ -56,7 +57,8 @@ public class NBTCompoundList extends NBTList<ReadWriteNBT> implements ReadWriteN
|
||||
}
|
||||
}
|
||||
|
||||
public NBTCompound addCompound(ReadWriteNBT comp) {
|
||||
@Override
|
||||
public ReadWriteNBT addCompound(ReadableNBT comp) {
|
||||
if (comp instanceof NBTCompound) {
|
||||
return addCompound((NBTCompound) comp);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,10 @@ public class NBTContainer extends NBTCompound {
|
||||
|
||||
/**
|
||||
* Creates an empty, standalone NBTCompound
|
||||
*
|
||||
* @deprecated use {@link NBT#createNBTObject()}
|
||||
*/
|
||||
@Deprecated
|
||||
public NBTContainer() {
|
||||
super(null, null);
|
||||
nbt = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
@@ -31,7 +34,9 @@ public class NBTContainer extends NBTCompound {
|
||||
* Takes in any NMS Compound to wrap it
|
||||
*
|
||||
* @param nbt
|
||||
* @deprecated Use NBT.wrapNMSTag
|
||||
*/
|
||||
@Deprecated
|
||||
public NBTContainer(Object nbt) {
|
||||
super(null, null);
|
||||
if (nbt == null) {
|
||||
@@ -47,7 +52,9 @@ public class NBTContainer extends NBTCompound {
|
||||
* Reads in a NBT InputStream
|
||||
*
|
||||
* @param inputsteam
|
||||
* @deprecated Use NBT.readNBT
|
||||
*/
|
||||
@Deprecated
|
||||
public NBTContainer(InputStream inputsteam) {
|
||||
super(null, null);
|
||||
this.nbt = NBTReflectionUtil.readNBT(inputsteam);
|
||||
@@ -58,7 +65,9 @@ public class NBTContainer extends NBTCompound {
|
||||
* {@link NbtApiException} in case something goes wrong.
|
||||
*
|
||||
* @param nbtString
|
||||
* @deprecated Use NBT.parseNBT
|
||||
*/
|
||||
@Deprecated
|
||||
public NBTContainer(String nbtString) {
|
||||
super(null, null);
|
||||
if (nbtString == null) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.iface.NBTFileHandle;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ObjectCreator;
|
||||
|
||||
/**
|
||||
@@ -12,7 +13,7 @@ import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ObjectCreator;
|
||||
* @author tr7zw
|
||||
*
|
||||
*/
|
||||
public class NBTFile extends NBTCompound {
|
||||
public class NBTFile extends NBTCompound implements NBTFileHandle {
|
||||
|
||||
private final File file;
|
||||
private Object nbt;
|
||||
@@ -23,7 +24,9 @@ public class NBTFile extends NBTCompound {
|
||||
*
|
||||
* @param file
|
||||
* @throws IOException
|
||||
* @deprecated Use NBT.getFileHandle(file)
|
||||
*/
|
||||
@Deprecated
|
||||
public NBTFile(File file) throws IOException {
|
||||
super(null, null);
|
||||
if (file == null) {
|
||||
@@ -43,6 +46,7 @@ public class NBTFile extends NBTCompound {
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
public void save() throws IOException {
|
||||
try {
|
||||
getWriteLock().lock();
|
||||
@@ -55,6 +59,7 @@ public class NBTFile extends NBTCompound {
|
||||
/**
|
||||
* @return The File used to store the data
|
||||
*/
|
||||
@Override
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
@@ -77,7 +82,9 @@ public class NBTFile extends NBTCompound {
|
||||
* @param file file to read
|
||||
* @return NBTCompound holding file's nbt data
|
||||
* @throws IOException exception
|
||||
* @deprecated Use NBT.readFile(file)
|
||||
*/
|
||||
@Deprecated
|
||||
public static NBTCompound readFrom(File file) throws IOException {
|
||||
if (!file.exists())
|
||||
return new NBTContainer();
|
||||
@@ -92,7 +99,9 @@ public class NBTFile extends NBTCompound {
|
||||
* @param file file
|
||||
* @param nbt NBT data
|
||||
* @throws IOException exception
|
||||
* @deprecated Use NBT.writeFile(file, nbt)
|
||||
*/
|
||||
@Deprecated
|
||||
public static void saveTo(File file, NBTCompound nbt) throws IOException {
|
||||
if (!file.exists()) {
|
||||
file.getParentFile().mkdirs();
|
||||
|
||||
@@ -304,8 +304,8 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
try {
|
||||
parent.getWriteLock().lock();
|
||||
int size = size();
|
||||
int id = -1;
|
||||
while ((id = indexOf(o)) != -1) {
|
||||
int id = indexOf(o);
|
||||
if (id != -1) {
|
||||
remove(id);
|
||||
}
|
||||
return size != size();
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.util.ArrayDeque;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -154,6 +155,9 @@ public class NBTReflectionUtil {
|
||||
public static void writeApiNBT(NBTCompound comp, OutputStream stream) {
|
||||
try {
|
||||
Object workingtag = comp.getResolvedObject();
|
||||
if (workingtag == null) {
|
||||
workingtag = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
|
||||
}
|
||||
ReflectionMethod.NBTFILE_WRITE.run(null, workingtag, stream);
|
||||
} catch (Exception e) {
|
||||
throw new NbtApiException("Exception while writing NBT!", e);
|
||||
@@ -213,11 +217,22 @@ public class NBTReflectionUtil {
|
||||
try {
|
||||
Object nmsComp = getToCompount(nbtcompound.getCompound(), nbtcompound);
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
if (nbtcompound.hasTag("tag")) {
|
||||
nmsComp = DataFixerUtil.fixUpRawItemData(nmsComp, DataFixerUtil.VERSION1_20_4,
|
||||
DataFixerUtil.getCurrentVersion());
|
||||
if (nbtcompound.hasTag("DataVersion", NBTType.NBTTagInt)) {
|
||||
int dataVersion = nbtcompound.getInteger("DataVersion");
|
||||
int currentVersion = DataFixerUtil.getCurrentVersion();
|
||||
if (dataVersion < currentVersion) {
|
||||
nmsComp = DataFixerUtil.fixUpRawItemData(nmsComp, dataVersion, currentVersion);
|
||||
}
|
||||
} else if (nbtcompound.hasTag("tag") || nbtcompound.hasTag("Count")) {
|
||||
nmsComp = DataFixerUtil.fixUpRawItemData(nmsComp, DataFixerUtil.VERSION1_20_4, DataFixerUtil.getCurrentVersion());
|
||||
}
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4)) {
|
||||
Optional<Object> opt = (Optional<Object>) ReflectionMethod.NMSITEM_LOAD_MODERN.run(null,
|
||||
registry_access, nmsComp);
|
||||
return opt.orElse(null);
|
||||
} else {
|
||||
return ReflectionMethod.NMSITEM_LOAD.run(null, registry_access, nmsComp);
|
||||
}
|
||||
return ReflectionMethod.NMSITEM_LOAD.run(null, registry_access, nmsComp);
|
||||
} else if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_11_R1.getVersionId()) {
|
||||
return ObjectCreator.NMS_COMPOUNDFROMITEM.getInstance(nmsComp);
|
||||
} else {
|
||||
@@ -236,13 +251,18 @@ public class NBTReflectionUtil {
|
||||
*/
|
||||
public static NBTContainer convertNMSItemtoNBTCompound(Object nmsitem) {
|
||||
try {
|
||||
NBTContainer container;
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
return new NBTContainer(ReflectionMethod.NMSITEM_SAVE_MODERN.run(nmsitem, registry_access));
|
||||
container = new NBTContainer(ReflectionMethod.NMSITEM_SAVE_MODERN.run(nmsitem, registry_access));
|
||||
} else {
|
||||
Object answer = ReflectionMethod.NMSITEM_SAVE.run(nmsitem,
|
||||
ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance());
|
||||
return new NBTContainer(answer);
|
||||
container = new NBTContainer(answer);
|
||||
}
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_12_R1)) {
|
||||
container.setInteger("DataVersion", DataFixerUtil.getCurrentVersion());
|
||||
}
|
||||
return container;
|
||||
} catch (Exception e) {
|
||||
throw new NbtApiException("Exception while converting NMS ItemStack to NBTCompound!", e);
|
||||
}
|
||||
@@ -383,7 +403,11 @@ public class NBTReflectionUtil {
|
||||
public static Object getSubNBTTagCompound(Object compound, String name) {
|
||||
try {
|
||||
if ((boolean) ReflectionMethod.COMPOUND_HAS_KEY.run(compound, name)) {
|
||||
return ReflectionMethod.COMPOUND_GET_COMPOUND.run(compound, name);
|
||||
Object comp = ReflectionMethod.COMPOUND_GET_COMPOUND.run(compound, name);
|
||||
if (comp instanceof Optional) {
|
||||
return ((Optional<?>) comp).orElse(null);
|
||||
}
|
||||
return comp;
|
||||
} else {
|
||||
throw new NbtApiException("Tried getting invalid compound '" + name + "' from '" + compound + "'!");
|
||||
}
|
||||
@@ -407,7 +431,7 @@ public class NBTReflectionUtil {
|
||||
if (nbttag == null) {
|
||||
nbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
}
|
||||
if (!valideCompound(comp)) {
|
||||
if (!validCompound(comp)) {
|
||||
return;
|
||||
}
|
||||
Object workingtag = getToCompount(nbttag, comp);
|
||||
@@ -424,10 +448,13 @@ public class NBTReflectionUtil {
|
||||
* Checks if the Compound is correctly linked to it's roots
|
||||
*
|
||||
* @param comp
|
||||
* @return true if this is a valide Compound, else false
|
||||
* @return true if this is a valid Compound, else false
|
||||
*/
|
||||
public static boolean valideCompound(NBTCompound comp) {
|
||||
public static boolean validCompound(NBTCompound comp) {
|
||||
Object root = comp.getCompound();
|
||||
if (root instanceof Optional) {
|
||||
root = ((Optional<?>) root).orElse(null);
|
||||
}
|
||||
if (root == null) {
|
||||
root = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
}
|
||||
@@ -442,9 +469,15 @@ public class NBTReflectionUtil {
|
||||
structure.add(comp.getName());
|
||||
comp = comp.getParent();
|
||||
}
|
||||
if (nbttag instanceof Optional) {
|
||||
nbttag = ((Optional<?>) nbttag).orElse(null);
|
||||
}
|
||||
while (!structure.isEmpty()) {
|
||||
String target = structure.pollLast();
|
||||
nbttag = getSubNBTTagCompound(nbttag, target);
|
||||
if (nbttag instanceof Optional) {
|
||||
nbttag = ((Optional<?>) nbttag).orElse(null);
|
||||
}
|
||||
if (nbttag == null) {
|
||||
throw new NbtApiException("Unable to find tag '" + target + "' in " + nbttag);
|
||||
}
|
||||
@@ -467,7 +500,7 @@ public class NBTReflectionUtil {
|
||||
if (rootnbttag == null) {
|
||||
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
}
|
||||
if (!valideCompound(comp))
|
||||
if (!validCompound(comp))
|
||||
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
|
||||
Object workingtag = getToCompount(rootnbttag, comp);
|
||||
try {
|
||||
@@ -494,7 +527,7 @@ public class NBTReflectionUtil {
|
||||
if (rootnbttag == null) {
|
||||
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
}
|
||||
if (!valideCompound(comp)) {
|
||||
if (!validCompound(comp)) {
|
||||
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
|
||||
}
|
||||
Object workingtag = getToCompount(rootnbttag, comp);
|
||||
@@ -522,7 +555,18 @@ public class NBTReflectionUtil {
|
||||
workingtag = dummyNBT.getCompound(); // it creates a new ListTag if needed, but its unlinked
|
||||
}
|
||||
try {
|
||||
Object nbt = ReflectionMethod.COMPOUND_GET_LIST.run(workingtag, key, type.getId());
|
||||
Object nbt = null;
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4)) {
|
||||
nbt = ReflectionMethod.COMPOUND_GET_LIST.run(workingtag, key);
|
||||
if (nbt instanceof Optional) {
|
||||
nbt = ((Optional<?>) nbt).orElse(null);
|
||||
}
|
||||
if (nbt == null) {
|
||||
nbt = ClassWrapper.NMS_NBTTAGLIST.getClazz().newInstance();
|
||||
}
|
||||
} else {
|
||||
nbt = ReflectionMethod.COMPOUND_GET_LIST_LEGACY.run(workingtag, key, type.getId());
|
||||
}
|
||||
if (clazz == String.class) {
|
||||
return (NBTList<T>) new NBTStringList(comp, key, type, nbt);
|
||||
} else if (clazz == NBTListCompound.class) {
|
||||
@@ -554,6 +598,26 @@ public class NBTReflectionUtil {
|
||||
}
|
||||
try {
|
||||
Object nbt = ReflectionMethod.COMPOUND_GET.run(workingtag, key);
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4)) {
|
||||
if (nbt instanceof Optional) {
|
||||
nbt = ((Optional<?>) nbt).orElse(null);
|
||||
}
|
||||
if (nbt == null) {
|
||||
return NBTType.NBTTagEnd;
|
||||
}
|
||||
if (new NBTStringList(comp, key, NBTType.NBTTagString, nbt).isEmpty()) {
|
||||
return NBTType.NBTTagEnd;
|
||||
}
|
||||
Object compound = ReflectionMethod.LIST_GET.run(nbt, 0);
|
||||
if (compound instanceof Optional) {
|
||||
compound = ((Optional<?>) compound).orElse(null);
|
||||
}
|
||||
if (compound == null) {
|
||||
return NBTType.NBTTagEnd;
|
||||
}
|
||||
return NBTType.fromName((String) ReflectionMethod.TAGTYPE_GET_NAME
|
||||
.run(ReflectionMethod.TAGTYPE_OWN_TYPE.run(compound)));
|
||||
}
|
||||
String fieldname = "type";
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_17_R1)) {
|
||||
fieldname = "w";
|
||||
@@ -628,7 +692,7 @@ public class NBTReflectionUtil {
|
||||
if (rootnbttag == null) {
|
||||
return;
|
||||
}
|
||||
if (!valideCompound(comp))
|
||||
if (!validCompound(comp))
|
||||
return;
|
||||
Object workingtag = getToCompount(rootnbttag, comp);
|
||||
ReflectionMethod.COMPOUND_REMOVE_KEY.run(workingtag, key);
|
||||
@@ -667,7 +731,7 @@ public class NBTReflectionUtil {
|
||||
if (rootnbttag == null) {
|
||||
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
}
|
||||
if (!valideCompound(comp))
|
||||
if (!validCompound(comp))
|
||||
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
|
||||
Object workingtag = getToCompount(rootnbttag, comp);
|
||||
type.run(workingtag, key, data);
|
||||
@@ -690,7 +754,41 @@ public class NBTReflectionUtil {
|
||||
if (workingtag == null) {
|
||||
workingtag = dummyNBT.getCompound();
|
||||
}
|
||||
return type.run(workingtag, key);
|
||||
if (workingtag instanceof Optional<?>) {
|
||||
workingtag = ((Optional<Object>) workingtag).orElseGet(() -> dummyNBT.getCompound());
|
||||
}
|
||||
Object obj = type.run(workingtag, key);
|
||||
if (obj instanceof Optional<?>) {
|
||||
return ((Optional<Object>) obj).orElseGet(() -> getDefaultValue(type));
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
private static Object getDefaultValue(ReflectionMethod type) {
|
||||
if (type == ReflectionMethod.COMPOUND_GET_STRING) {
|
||||
return "";
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_BYTE) {
|
||||
return (byte) 0;
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_SHORT) {
|
||||
return (short) 0;
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_BOOLEAN) {
|
||||
return false;
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_INT) {
|
||||
return 0;
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_LONG) {
|
||||
return 0L;
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_FLOAT) {
|
||||
return 0.0f;
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_DOUBLE) {
|
||||
return 0.0d;
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_BYTEARRAY) {
|
||||
return new byte[0];
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_INTARRAY) {
|
||||
return new int[0];
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_LONGARRAY) {
|
||||
return new long[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package de.tr7zw.changeme.nbtapi;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Optional;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
|
||||
@@ -21,7 +22,11 @@ public class NBTStringList extends NBTList<String> {
|
||||
@Override
|
||||
public String get(int index) {
|
||||
try {
|
||||
return (String) ReflectionMethod.LIST_GET_STRING.run(listObject, index);
|
||||
Object ret = ReflectionMethod.LIST_GET_STRING.run(listObject, index);
|
||||
if (ret instanceof Optional<?>) {
|
||||
return ((Optional<String>) ret).orElse("");
|
||||
}
|
||||
return (String) ret;
|
||||
} catch (Exception ex) {
|
||||
throw new NbtApiException(ex);
|
||||
}
|
||||
|
||||
@@ -8,14 +8,16 @@ package de.tr7zw.changeme.nbtapi;
|
||||
*/
|
||||
@SuppressWarnings("javadoc")
|
||||
public enum NBTType {
|
||||
NBTTagEnd(0), NBTTagByte(1), NBTTagShort(2), NBTTagInt(3), NBTTagLong(4), NBTTagFloat(5), NBTTagDouble(6),
|
||||
NBTTagByteArray(7), NBTTagString(8), NBTTagList(9), NBTTagCompound(10), NBTTagIntArray(11), NBTTagLongArray(12);
|
||||
NBTTagEnd(0, ""), NBTTagByte(1, "BYTE"), NBTTagShort(2, "SHORT"), NBTTagInt(3, "INT"), NBTTagLong(4, "LONG"), NBTTagFloat(5, "FLOAT"), NBTTagDouble(6, "DOUBLE"),
|
||||
NBTTagByteArray(7, "BYTE[]"), NBTTagString(8, "STRING"), NBTTagList(9, "LIST"), NBTTagCompound(10, "COMPOUND"), NBTTagIntArray(11, "INT[]"), NBTTagLongArray(12, "LONG[]");
|
||||
|
||||
NBTType(int i) {
|
||||
NBTType(int i, String name) {
|
||||
id = i;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private final int id;
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* @return Id used by Minecraft internally
|
||||
@@ -23,6 +25,13 @@ public enum NBTType {
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Name of the NBTType
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id Internal Minecraft id
|
||||
@@ -35,4 +44,11 @@ public enum NBTType {
|
||||
return NBTType.NBTTagEnd;
|
||||
}
|
||||
|
||||
public static NBTType fromName(String name) {
|
||||
for (NBTType t : values())
|
||||
if (t.getName().equals(name))
|
||||
return t;
|
||||
return NBTType.NBTTagEnd;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package de.tr7zw.changeme.nbtapi.iface;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public interface NBTFileHandle extends ReadWriteNBT {
|
||||
|
||||
/**
|
||||
* Saves the data to the file
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
void save() throws IOException;
|
||||
|
||||
/**
|
||||
* @return The File used to store the data
|
||||
*/
|
||||
File getFile();
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
+9
@@ -10,6 +10,15 @@ public interface ReadWriteNBTCompoundList extends ReadableNBTList<ReadWriteNBT>
|
||||
* @return A new instance of the class.
|
||||
*/
|
||||
ReadWriteNBT addCompound();
|
||||
|
||||
/**
|
||||
* Adds a copy of the Compound to the end of the List and returns it. When null
|
||||
* is given, a new Compound will be created
|
||||
*
|
||||
* @param comp
|
||||
* @return
|
||||
*/
|
||||
ReadWriteNBT addCompound(ReadableNBT comp);
|
||||
|
||||
/**
|
||||
* Removes the element at the specified position in this list
|
||||
|
||||
@@ -344,6 +344,17 @@ public interface ReadableNBT {
|
||||
*/
|
||||
void writeCompound(OutputStream stream);
|
||||
|
||||
/**
|
||||
* Compares this readable nbt to the other one
|
||||
* and returns the difference.
|
||||
* <p>Note: the result will only contain data that is present
|
||||
* in this readable nbt and is missing/different in the provided one.
|
||||
*
|
||||
* @param other other readable nbt
|
||||
* @return difference between readable nbts
|
||||
*/
|
||||
ReadWriteNBT extractDifference(ReadableNBT other);
|
||||
|
||||
/**
|
||||
* @return The NBT as printable NBT-Json.
|
||||
*/
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.mojang.datafixers.DataFixer;
|
||||
import com.mojang.serialization.Dynamic;
|
||||
import com.mojang.serialization.DynamicOps;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTContainer;
|
||||
import de.tr7zw.changeme.nbtapi.NBTReflectionUtil;
|
||||
@@ -16,6 +17,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 +30,10 @@ 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;
|
||||
public static final int VERSION1_21_2 = 4080;
|
||||
public static final int VERSION1_21_3 = 4189;
|
||||
public static final int VERSION1_21_5 = 4323;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Object fixUpRawItemData(Object nbt, int fromVersion, int toVersion)
|
||||
@@ -43,7 +51,7 @@ public class DataFixerUtil {
|
||||
|
||||
public static ReadWriteNBT fixUpItemData(ReadWriteNBT nbt, int fromVersion, int toVersion)
|
||||
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
|
||||
return new NBTContainer(fixUpRawItemData(
|
||||
return NBT.wrapNMSTag(fixUpRawItemData(
|
||||
NBTReflectionUtil.getToCompount(((NBTCompound) nbt).getCompound(), ((NBTCompound) nbt)), fromVersion,
|
||||
toVersion));
|
||||
}
|
||||
@@ -58,7 +66,15 @@ public class DataFixerUtil {
|
||||
* @return
|
||||
*/
|
||||
public static int getCurrentVersion() {
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4)) {
|
||||
return VERSION1_21_5;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R3)) {
|
||||
return VERSION1_21_3;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R2)) {
|
||||
return VERSION1_21_2;
|
||||
} else 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;
|
||||
|
||||
@@ -24,7 +24,7 @@ public enum MinecraftVersion {
|
||||
MC1_13_R1(1131), MC1_13_R2(1132), MC1_14_R1(1141), MC1_15_R1(1151), MC1_16_R1(1161), MC1_16_R2(1162),
|
||||
MC1_16_R3(1163), MC1_17_R1(1171), MC1_18_R1(1181, true), MC1_18_R2(1182, true), MC1_19_R1(1191, true),
|
||||
MC1_19_R2(1192, true), MC1_19_R3(1193, true), MC1_20_R1(1201, true), MC1_20_R2(1202, true), MC1_20_R3(1203, true),
|
||||
MC1_20_R4(1204, true), MC1_21_R1(1211, true);
|
||||
MC1_20_R4(1204, true), MC1_21_R1(1211, true), MC1_21_R2(1212, true), MC1_21_R3(1213, true), MC1_21_R4(1214, true);
|
||||
|
||||
private static MinecraftVersion version;
|
||||
private static Boolean hasGsonSupport;
|
||||
@@ -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.15.0";
|
||||
|
||||
private final int versionId;
|
||||
private final boolean mojangMapping;
|
||||
@@ -55,7 +55,12 @@ 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);
|
||||
this.put("1.21.2", MC1_21_R2);
|
||||
this.put("1.21.3", MC1_21_R2);
|
||||
this.put("1.21.4", MC1_21_R3);
|
||||
this.put("1.21.5", MC1_21_R4);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package de.tr7zw.changeme.nbtapi.utils;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.DataResult;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.MojangToMapping;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
|
||||
|
||||
public class NBTJsonUtil {
|
||||
|
||||
/**
|
||||
* 1.20.3-1.21.4 only. Used to convert items into Json, used in Chat Hover Components.
|
||||
*
|
||||
* @param itemStack
|
||||
* @return
|
||||
* @throws NbtApiException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static JsonElement itemStackToJson(ItemStack itemStack) {
|
||||
try {
|
||||
Codec<Object> itemStackCodec = (Codec<Object>) ClassWrapper.NMS_ITEMSTACK.getClazz()
|
||||
.getField(MojangToMapping.getMapping().get("net.minecraft.world.item.ItemStack#CODEC")).get(null);
|
||||
Object stack = ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, itemStack);
|
||||
DataResult<JsonElement> result = itemStackCodec.encode(stack, JsonOps.INSTANCE,
|
||||
JsonOps.INSTANCE.emptyMap());
|
||||
Optional<JsonElement> opt = (Optional<JsonElement>) result.getClass().getMethod("result").invoke(result);
|
||||
return opt.orElse(null);
|
||||
} catch (Exception ex) {
|
||||
throw new NbtApiException("Error trying to get Json of an ItemStack.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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("["));
|
||||
|
||||
+1
@@ -24,6 +24,7 @@ public enum ClassWrapper {
|
||||
CRAFT_PERSISTENTDATACONTAINER(PackageWrapper.CRAFTBUKKIT, "persistence.CraftPersistentDataContainer",
|
||||
MinecraftVersion.MC1_14_R1, null),
|
||||
NMS_NBTBASE(PackageWrapper.NMS, "NBTBase", null, null, "net.minecraft.nbt", "net.minecraft.nbt.Tag"),
|
||||
NMS_TAGTYPE(PackageWrapper.NMS, "NBTTagType", MinecraftVersion.MC1_21_R4, null, "net.minecraft.nbt", "net.minecraft.nbt.TagType"),
|
||||
NMS_NBTTAGSTRING(PackageWrapper.NMS, "NBTTagString", null, null, "net.minecraft.nbt",
|
||||
"net.minecraft.nbt.StringTag"),
|
||||
NMS_NBTTAGINT(PackageWrapper.NMS, "NBTTagInt", null, null, "net.minecraft.nbt", "net.minecraft.nbt.IntTag"),
|
||||
|
||||
+63
@@ -145,6 +145,7 @@ public class MojangToMapping {
|
||||
put("net.minecraft.world.entity.Entity#getEncodeId()", "bw");
|
||||
put("net.minecraft.world.level.block.entity.BlockEntity#saveWithId()", "p");
|
||||
put("net.minecraft.world.level.block.entity.BlockEntity#getBlockState()", "r");
|
||||
put("net.minecraft.world.item.ItemStack#CODEC", "a");
|
||||
}
|
||||
|
||||
};
|
||||
@@ -169,6 +170,7 @@ public class MojangToMapping {
|
||||
put("net.minecraft.util.datafix.DataFixers#getDataFixer()", "a");
|
||||
put("net.minecraft.util.datafix.fixes.References#ITEM_STACK", "t");
|
||||
put("net.minecraft.nbt.NbtOps#INSTANCE", "a");
|
||||
put("net.minecraft.world.item.ItemStack#CODEC", "b");
|
||||
}
|
||||
|
||||
};
|
||||
@@ -183,10 +185,71 @@ public class MojangToMapping {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static Map<String, String> MC1_21R2 = new HashMap<String, String>() {
|
||||
|
||||
{
|
||||
putAll(MC1_21R1);
|
||||
|
||||
put("net.minecraft.server.MinecraftServer#registryAccess()", "ba");
|
||||
put("net.minecraft.world.entity.Entity#getEncodeId()", "bK");
|
||||
put("net.minecraft.world.level.block.entity.BlockEntity#getBlockState()", "m");
|
||||
put("net.minecraft.world.item.ItemStack#CODEC", "a");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static Map<String, String> MC1_21R3 = new HashMap<String, String>() {
|
||||
|
||||
{
|
||||
putAll(MC1_21R2);
|
||||
|
||||
put("net.minecraft.world.item.component.CustomData#copyTag()", "d");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static Map<String, String> MC1_21R4 = new HashMap<String, String>() {
|
||||
|
||||
{
|
||||
putAll(MC1_21R3);
|
||||
|
||||
put("net.minecraft.nbt.CompoundTag#getShort(java.lang.String)", "d");
|
||||
put("net.minecraft.nbt.CompoundTag#getString(java.lang.String)", "i");
|
||||
put("net.minecraft.nbt.CompoundTag#contains(java.lang.String)", "b");
|
||||
put("net.minecraft.nbt.CompoundTag#getDouble(java.lang.String)", "h");
|
||||
put("net.minecraft.nbt.CompoundTag#getByteArray(java.lang.String)", "j");
|
||||
put("net.minecraft.nbt.CompoundTag#getFloat(java.lang.String)", "g");
|
||||
put("net.minecraft.nbt.CompoundTag#get(java.lang.String)", "a");
|
||||
put("net.minecraft.nbt.CompoundTag#getLong(java.lang.String)", "f");
|
||||
put("net.minecraft.nbt.CompoundTag#getLongArray(java.lang.String)", "l");
|
||||
put("net.minecraft.nbt.CompoundTag#getInt(java.lang.String)", "e");
|
||||
put("net.minecraft.nbt.CompoundTag#getIntArray(java.lang.String)", "k");
|
||||
put("net.minecraft.nbt.CompoundTag#getCompound(java.lang.String)", "m");
|
||||
put("net.minecraft.nbt.CompoundTag#getByte(java.lang.String)", "c");
|
||||
put("net.minecraft.nbt.ListTag#getString(int)", "m");
|
||||
put("net.minecraft.world.entity.Entity#saveWithoutId(net.minecraft.nbt.CompoundTag)", "h");
|
||||
put("net.minecraft.world.entity.Entity#getEncodeId()", "bI");
|
||||
put("net.minecraft.world.entity.Entity#load(net.minecraft.nbt.CompoundTag)", "i");
|
||||
put("net.minecraft.nbt.Tag#getType()", "c");
|
||||
put("net.minecraft.nbt.TagType#getName()", "a");
|
||||
put("net.minecraft.nbt.CompoundTag#getList(java.lang.String)", "o");
|
||||
put("net.minecraft.world.item.ItemStack#parse(net.minecraft.core.HolderLookup$Provider,net.minecraft.nbt.Tag)", "a");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public static Map<String, String> getMapping() {
|
||||
switch (MinecraftVersion.getVersion()) {
|
||||
case MC1_21_R4:
|
||||
return MC1_21R4;
|
||||
case MC1_21_R3:
|
||||
return MC1_21R3;
|
||||
case MC1_21_R2:
|
||||
return MC1_21R2;
|
||||
case MC1_21_R1:
|
||||
return MC1_21R1;
|
||||
case MC1_20_R4:
|
||||
|
||||
+18
-19
@@ -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;
|
||||
@@ -56,7 +54,7 @@ public enum ReflectionMethod {
|
||||
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setBoolean"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "putBoolean(java.lang.String,boolean)")),
|
||||
COMPOUND_SET_UUID(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, UUID.class },
|
||||
MinecraftVersion.MC1_16_R1, new Since(MinecraftVersion.MC1_16_R1, "a"),
|
||||
MinecraftVersion.MC1_16_R1, MinecraftVersion.MC1_21_R3, new Since(MinecraftVersion.MC1_16_R1, "a"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "putUUID(java.lang.String,java.util.UUID)")),
|
||||
COMPOUND_MERGE(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
|
||||
MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "a"),
|
||||
@@ -67,12 +65,18 @@ public enum ReflectionMethod {
|
||||
COMPOUND_GET(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "get"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "get(java.lang.String)")),
|
||||
COMPOUND_GET_LIST(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, int.class },
|
||||
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getList"),
|
||||
COMPOUND_GET_LIST_LEGACY(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, int.class },
|
||||
MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_21_R3, new Since(MinecraftVersion.MC1_7_R4, "getList"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "getList(java.lang.String,int)")),
|
||||
COMPOUND_GET_LIST(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_21_R4,
|
||||
MinecraftVersion.MC1_21_R4, new Since(MinecraftVersion.MC1_21_R4, "getList(java.lang.String)")),
|
||||
// Only needed for 1.7.10 getType
|
||||
COMPOUND_OWN_TYPE(ClassWrapper.NMS_NBTBASE, new Class[] {}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_7_R4,
|
||||
COMPOUND_OWN_TYPE_LEGACY(ClassWrapper.NMS_NBTBASE, new Class[] {}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "getTypeId")),
|
||||
TAGTYPE_OWN_TYPE(ClassWrapper.NMS_NBTBASE, new Class[] {}, MinecraftVersion.MC1_21_R4,
|
||||
new Since(MinecraftVersion.MC1_21_R4, "getType()")),
|
||||
TAGTYPE_GET_NAME(ClassWrapper.NMS_TAGTYPE, new Class[] {}, MinecraftVersion.MC1_21_R4,
|
||||
new Since(MinecraftVersion.MC1_21_R4, "getName()")),
|
||||
|
||||
COMPOUND_GET_FLOAT(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "getFloat"),
|
||||
@@ -107,14 +111,15 @@ public enum ReflectionMethod {
|
||||
COMPOUND_GET_BOOLEAN(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "getBoolean"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "getBoolean(java.lang.String)")),
|
||||
COMPOUND_GET_UUID(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_16_R1,
|
||||
COMPOUND_GET_UUID(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_16_R1, MinecraftVersion.MC1_21_R3,
|
||||
new Since(MinecraftVersion.MC1_16_R1, "a"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "getUUID(java.lang.String)")),
|
||||
COMPOUND_GET_COMPOUND(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
|
||||
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 +180,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 +188,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 +263,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 +275,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,
|
||||
@@ -304,7 +301,9 @@ public enum ReflectionMethod {
|
||||
NMSITEM_SAVE_MODERN(ClassWrapper.NMS_ITEMSTACK, new Class[] { ClassWrapper.NMS_PROVIDER.getClazz() },
|
||||
MinecraftVersion.MC1_20_R4, new Since(MinecraftVersion.MC1_20_R4, "save(net.minecraft.core.HolderLookup$Provider)")),
|
||||
NMSITEM_LOAD(ClassWrapper.NMS_ITEMSTACK, new Class[] { ClassWrapper.NMS_PROVIDER.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
|
||||
MinecraftVersion.MC1_20_R4, new Since(MinecraftVersion.MC1_20_R4, "parseOptional(net.minecraft.core.HolderLookup$Provider,net.minecraft.nbt.CompoundTag)")),
|
||||
MinecraftVersion.MC1_20_R4, MinecraftVersion.MC1_21_R3, new Since(MinecraftVersion.MC1_20_R4, "parseOptional(net.minecraft.core.HolderLookup$Provider,net.minecraft.nbt.CompoundTag)")),
|
||||
NMSITEM_LOAD_MODERN(ClassWrapper.NMS_ITEMSTACK, new Class[] { ClassWrapper.NMS_PROVIDER.getClazz(), ClassWrapper.NMS_NBTBASE.getClazz() },
|
||||
MinecraftVersion.MC1_21_R4, new Since(MinecraftVersion.MC1_20_R4, "parse(net.minecraft.core.HolderLookup$Provider,net.minecraft.nbt.Tag)")),
|
||||
NMSSERVER_GETREGISTRYACCESS(ClassWrapper.NMS_SERVER, new Class[] {},
|
||||
MinecraftVersion.MC1_20_R4, new Since(MinecraftVersion.MC1_20_R4, "registryAccess()")),
|
||||
NMSSERVER_GETSERVER(ClassWrapper.CRAFT_SERVER, new Class[] {},
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>item-nbt-parent</artifactId>
|
||||
<version>2.13.0</version>
|
||||
<version>2.15.0</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.15.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -7,7 +7,6 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
@@ -19,6 +18,7 @@ import de.tr7zw.nbtapi.plugin.tests.GameprofileTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.NBTFileTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.blocks.BlockNBTTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.chunks.ChunkNBTPersistentTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.compounds.CompoundDifferenceTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.compounds.EnumTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.compounds.EqualsTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.compounds.ForEachTest;
|
||||
@@ -41,6 +41,7 @@ import de.tr7zw.nbtapi.plugin.tests.items.DirectApplyMetaTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.items.DirectApplyTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.items.EmptyItemTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.items.ItemConversionTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.items.ItemJsonTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.items.ItemMergingTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.items.ItemStackConversionTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.items.LegacyItemTest;
|
||||
@@ -99,6 +100,7 @@ public class NBTAPI extends JavaPlugin {
|
||||
apiTests.add(new ForEachTest());
|
||||
apiTests.add(new StreamTest());
|
||||
apiTests.add(new EqualsTest());
|
||||
apiTests.add(new CompoundDifferenceTest());
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_8_R3)) // 1.7.10 list support is not complete at all
|
||||
apiTests.add(new IteratorTest());
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R1))
|
||||
@@ -112,6 +114,9 @@ public class NBTAPI extends JavaPlugin {
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
apiTests.add(new LegacyItemTest());
|
||||
}
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4) && !MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4)) {
|
||||
apiTests.add(new ItemJsonTest());
|
||||
}
|
||||
apiTests.add(new ComponentsTest());
|
||||
apiTests.add(new EmptyItemTest());
|
||||
apiTests.add(new SmuggleTest());
|
||||
|
||||
@@ -4,9 +4,9 @@ import java.util.UUID;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTGameProfile;
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
|
||||
public class GameprofileTest implements Test {
|
||||
|
||||
@@ -14,9 +14,9 @@ public class GameprofileTest implements Test {
|
||||
public void test() throws Exception {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
GameProfile profile = new GameProfile(uuid, "random");
|
||||
NBTCompound nbt = NBTGameProfile.toNBT(profile);
|
||||
ReadWriteNBT nbt = NBT.gameProfileToNBT(profile);
|
||||
profile = null;
|
||||
profile = NBTGameProfile.fromNBT(nbt);
|
||||
profile = NBT.gameProfileFromNBT(nbt);
|
||||
if (profile == null || !profile.getId().equals(uuid)) {
|
||||
throw new NbtApiException("Error when converting a GameProfile from/to NBT!");
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@ package de.tr7zw.nbtapi.plugin.tests;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTContainer;
|
||||
import de.tr7zw.changeme.nbtapi.NBTFile;
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.NBTFileHandle;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.nbtapi.plugin.NBTAPI;
|
||||
|
||||
public class NBTFileTest implements Test {
|
||||
@@ -16,18 +16,18 @@ public class NBTFileTest implements Test {
|
||||
NBTAPI.getInstance().getDataFolder().mkdirs();
|
||||
File testFile = new File(NBTAPI.getInstance().getDataFolder(), "test.nbt");
|
||||
Files.deleteIfExists(testFile.toPath());
|
||||
NBTFile file = new NBTFile(testFile);
|
||||
file.addCompound("testcomp").setString("test1", "ok");
|
||||
NBTCompound comp = file.getCompound("testcomp");
|
||||
NBTFileHandle file = NBT.getFileHandle(testFile);
|
||||
file.getOrCreateCompound("testcomp").setString("test1", "ok");
|
||||
ReadWriteNBT comp = file.getOrCreateCompound("testcomp");
|
||||
if (comp == null) {
|
||||
throw new NbtApiException("Error getting compound!");
|
||||
}
|
||||
comp.setString("test2", "ok");
|
||||
file.setLong("time", System.currentTimeMillis());
|
||||
file.setString("test", "test");
|
||||
NBTCompound chunks = file.addCompound("chunks");
|
||||
NBTCompound chunk = chunks.addCompound("somechunk");
|
||||
NBTCompound block = chunk.addCompound("someblock");
|
||||
ReadWriteNBT chunks = file.getOrCreateCompound("chunks");
|
||||
ReadWriteNBT chunk = chunks.getOrCreateCompound("somechunk");
|
||||
ReadWriteNBT block = chunk.getOrCreateCompound("someblock");
|
||||
block.setString("type", "wool");
|
||||
file.save();
|
||||
|
||||
@@ -35,25 +35,25 @@ public class NBTFileTest implements Test {
|
||||
throw new NbtApiException("SubCompounds did not work!");
|
||||
}
|
||||
|
||||
NBTFile fileLoaded = new NBTFile(testFile);
|
||||
NBTFileHandle fileLoaded = NBT.getFileHandle(testFile);
|
||||
if (!fileLoaded.getString("test").equals("test")) {
|
||||
throw new NbtApiException("Wasn't able to load NBT File with the correct content!");
|
||||
}
|
||||
Files.deleteIfExists(fileLoaded.getFile().toPath());
|
||||
// String
|
||||
String str = fileLoaded.toString();
|
||||
NBTContainer rebuild = new NBTContainer(str);
|
||||
ReadWriteNBT rebuild = NBT.parseNBT(str);
|
||||
if (!str.equals(rebuild.toString())) {
|
||||
throw new NbtApiException("Wasn't able to parse NBT from a String!");
|
||||
}
|
||||
|
||||
NBTCompound dummy = new NBTContainer();
|
||||
ReadWriteNBT dummy = NBT.createNBTObject();
|
||||
dummy.setString("test1", "key1");
|
||||
NBTFile.saveTo(testFile, dummy);
|
||||
dummy = new NBTContainer();
|
||||
NBT.writeFile(testFile, dummy);
|
||||
dummy = NBT.createNBTObject();
|
||||
dummy.setString("test2", "key2");
|
||||
NBTFile.saveTo(testFile, dummy);
|
||||
dummy = NBTFile.readFrom(testFile);
|
||||
NBT.writeFile(testFile, dummy);
|
||||
dummy = NBT.readFile(testFile);
|
||||
if (dummy.hasTag("test1") || !dummy.getString("test2").equals("key2")) {
|
||||
throw new NbtApiException("Wasn't able to save NBT File with the correct content!");
|
||||
}
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.compounds;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class CompoundDifferenceTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
ReadWriteNBT nbt1 = NBT.createNBTObject();
|
||||
nbt1.setInteger("intTag", 1);
|
||||
ReadWriteNBT tmp = NBT.createNBTObject();
|
||||
tmp.setInteger("foo", 1);
|
||||
nbt1.getCompoundList("compoundList1").addCompound(tmp);
|
||||
nbt1.setIntArray("intArray", new int[]{1, 2, 3});
|
||||
tmp = NBT.createNBTObject();
|
||||
tmp.setIntArray("foo", new int[]{1, 2, 3});
|
||||
nbt1.getCompoundList("compoundList2").addCompound(tmp);
|
||||
nbt1.getOrCreateCompound("compoundTag").setFloat("floatTag", 20F);
|
||||
nbt1.getOrCreateCompound("compoundTag").setBoolean("booleanTag", true);
|
||||
nbt1.getOrCreateCompound("compoundTag").getDoubleList("doubleList").addAll(Arrays.asList(1D, 2D, 3D));
|
||||
nbt1.getOrCreateCompound("compoundTag").getFloatList("floatList").addAll(Arrays.asList(1F, 2F));
|
||||
nbt1.getOrCreateCompound("compoundTagTwo").setString("stringTag", "string");
|
||||
ReadWriteNBT nbt2 = NBT.createNBTObject();
|
||||
nbt2.setInteger("intTag", 1);
|
||||
tmp = NBT.createNBTObject();
|
||||
tmp.setInteger("foo", 1);
|
||||
nbt2.getCompoundList("compoundList1").addCompound(tmp);
|
||||
nbt2.setInteger("alsoIntTag", 2);
|
||||
tmp = NBT.createNBTObject();
|
||||
tmp.setInteger("foo", 2);
|
||||
nbt2.getCompoundList("compoundList2").addCompound(tmp);
|
||||
nbt2.getOrCreateCompound("compoundTag").setFloat("floatTag", 20F);
|
||||
nbt2.getOrCreateCompound("compoundTag").setBoolean("booleanTag", false);
|
||||
nbt2.getOrCreateCompound("compoundTag").getDoubleList("doubleList").addAll(Arrays.asList(1D, 2D, 3D, 4D));
|
||||
nbt2.getOrCreateCompound("compoundTag").getFloatList("floatList").addAll(Arrays.asList(1F, 2F));
|
||||
nbt2.getOrCreateCompound("compoundTagTwo").setString("stringTag", "string");
|
||||
|
||||
ReadWriteNBT expectedDiff1 = NBT.createNBTObject();
|
||||
tmp = NBT.createNBTObject();
|
||||
tmp.setIntArray("foo", new int[]{1, 2, 3});
|
||||
expectedDiff1.getCompoundList("compoundList2").addCompound(tmp);
|
||||
expectedDiff1.setIntArray("intArray", new int[]{1, 2, 3});
|
||||
expectedDiff1.getOrCreateCompound("compoundTag").setBoolean("booleanTag", true);
|
||||
expectedDiff1.getOrCreateCompound("compoundTag").getDoubleList("doubleList").addAll(Arrays.asList(1D, 2D, 3D));
|
||||
ReadWriteNBT expectedDiff2 = NBT.createNBTObject();
|
||||
tmp = NBT.createNBTObject();
|
||||
tmp.setInteger("foo", 2);
|
||||
expectedDiff2.getCompoundList("compoundList2").addCompound(tmp);
|
||||
expectedDiff2.setInteger("alsoIntTag", 2);
|
||||
expectedDiff2.getOrCreateCompound("compoundTag").setBoolean("booleanTag", false);
|
||||
expectedDiff2.getOrCreateCompound("compoundTag").getDoubleList("doubleList").addAll(Arrays.asList(1D, 2D, 3D, 4D));
|
||||
|
||||
ReadWriteNBT diff1 = nbt1.extractDifference(nbt2);
|
||||
ReadWriteNBT diff2 = nbt2.extractDifference(nbt1);
|
||||
|
||||
if (!expectedDiff1.equals(diff1)) {
|
||||
throw new NbtApiException("Diff1: Compounds did not match! " + expectedDiff1 + " " + diff1);
|
||||
}
|
||||
if (!expectedDiff2.equals(diff2)) {
|
||||
throw new NbtApiException("Diff2: Compounds did not match! " + expectedDiff2 + " " + diff2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.compounds;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTContainer;
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTType;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class EnumTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
NBTCompound comp = new NBTContainer();
|
||||
ReadWriteNBT comp = NBT.createNBTObject();
|
||||
comp.setEnum("test", NBTType.NBTTagEnd);
|
||||
NBTType type = comp.getEnum("test", NBTType.class);
|
||||
NBTType typeNonNull = comp.getOrNull("test", NBTType.class);
|
||||
|
||||
+18
-18
@@ -5,44 +5,44 @@ import java.util.Arrays;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTContainer;
|
||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class EqualsTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
NBTContainer cont = new NBTContainer();
|
||||
ReadWriteNBT cont = NBT.createNBTObject();
|
||||
cont.setString("hello", "world");
|
||||
cont.setInteger("theAnswer", 42);
|
||||
cont.addCompound("sub").setString("me", "too");
|
||||
cont.getOrCreateCompound("sub").setString("me", "too");
|
||||
cont.getStringList("somelist").addAll(Arrays.asList("a", "b", "c"));
|
||||
ItemStack item = new ItemStack(Material.STONE);
|
||||
NBTItem nbti = new NBTItem(item);
|
||||
NBTCompound customData = nbti.addCompound("customData");
|
||||
// reverse order
|
||||
customData.addCompound("sub").setString("me", "too");
|
||||
customData.setInteger("theAnswer", 42);
|
||||
customData.setString("hello", "world");
|
||||
customData.getStringList("somelist").addAll(Arrays.asList("a", "b", "c"));
|
||||
if (!customData.equals(cont)) {
|
||||
throw new NbtApiException("Compounds did not match! " + customData + " " + cont);
|
||||
}
|
||||
NBT.modify(item, nbti -> {
|
||||
ReadWriteNBT customData = nbti.getOrCreateCompound("customData");
|
||||
// reverse order
|
||||
customData.getOrCreateCompound("sub").setString("me", "too");
|
||||
customData.setInteger("theAnswer", 42);
|
||||
customData.setString("hello", "world");
|
||||
customData.getStringList("somelist").addAll(Arrays.asList("a", "b", "c"));
|
||||
if (!customData.equals(cont)) {
|
||||
throw new NbtApiException("Compounds did not match! " + customData + " " + cont);
|
||||
}
|
||||
});
|
||||
|
||||
// empty test
|
||||
|
||||
if (!new NBTContainer().equals(new NBTContainer())) {
|
||||
if (!NBT.createNBTObject().equals(NBT.createNBTObject())) {
|
||||
throw new NbtApiException("Two empty tags did not match!");
|
||||
}
|
||||
|
||||
// not equal test
|
||||
NBTContainer part1 = new NBTContainer();
|
||||
ReadWriteNBT part1 = NBT.createNBTObject();
|
||||
part1.setString("a", "a");
|
||||
part1.setString("b", "b");
|
||||
NBTContainer part2 = new NBTContainer();
|
||||
ReadWriteNBT part2 = NBT.createNBTObject();
|
||||
part2.setString("a", "a");
|
||||
part2.setString("b", "a");
|
||||
if (part1.equals(part2)) {
|
||||
|
||||
+15
-17
@@ -3,24 +3,22 @@ package de.tr7zw.nbtapi.plugin.tests.compounds;
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompoundList;
|
||||
import de.tr7zw.changeme.nbtapi.NBTContainer;
|
||||
import de.tr7zw.changeme.nbtapi.NBTList;
|
||||
import de.tr7zw.changeme.nbtapi.NBTListCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTType;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBTCompoundList;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBTList;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class ListTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
NBTContainer comp = new NBTContainer();
|
||||
ReadWriteNBT comp = NBT.createNBTObject();
|
||||
|
||||
// Strings
|
||||
NBTList<String> list = comp.getStringList("testlist");
|
||||
ReadWriteNBTList<String> list = comp.getStringList("testlist");
|
||||
list.add("test1");
|
||||
list.add("test2");
|
||||
list.add("test3");
|
||||
@@ -32,14 +30,14 @@ public class ListTest implements Test {
|
||||
}
|
||||
|
||||
// Compound
|
||||
NBTCompoundList taglist = comp.getCompoundList("complist");
|
||||
NBTListCompound lcomp = taglist.addCompound();
|
||||
ReadWriteNBTCompoundList taglist = comp.getCompoundList("complist");
|
||||
ReadWriteNBT lcomp = taglist.addCompound();
|
||||
lcomp.setDouble("double1", 0.3333);
|
||||
lcomp.setInteger("int1", 42);
|
||||
lcomp.setString("test1", "test1");
|
||||
lcomp.setString("test2", "test2");
|
||||
lcomp.removeKey("test1");
|
||||
NBTCompound subsubcomp = lcomp.addCompound("listsubkey");
|
||||
ReadWriteNBT subsubcomp = lcomp.getOrCreateCompound("listsubkey");
|
||||
subsubcomp.setString("deep", "String");
|
||||
subsubcomp.getCompoundList("deeplist").addCompound().setString("test", "test");
|
||||
subsubcomp.getCompoundList("clonelist").addCompound(comp);
|
||||
@@ -73,11 +71,11 @@ public class ListTest implements Test {
|
||||
}
|
||||
|
||||
if (comp.getListType("complist") != NBTType.NBTTagCompound) {
|
||||
throw new NbtApiException("complist had the wrong type! The Item-NBT-API may not work!");
|
||||
throw new NbtApiException("complist had the wrong type(" + comp.getListType("complist") + ")! The Item-NBT-API may not work!");
|
||||
}
|
||||
|
||||
// Integer
|
||||
NBTList<Integer> intlist = comp.getIntegerList("inttest");
|
||||
ReadWriteNBTList<Integer> intlist = comp.getIntegerList("inttest");
|
||||
intlist.add(42);
|
||||
intlist.add(69);
|
||||
if (intlist.size() == 2 && intlist.get(0) == 42 && intlist.get(1) == 69) {
|
||||
@@ -91,7 +89,7 @@ public class ListTest implements Test {
|
||||
}
|
||||
|
||||
// Double
|
||||
NBTList<Double> doublelist = comp.getDoubleList("doubletest");
|
||||
ReadWriteNBTList<Double> doublelist = comp.getDoubleList("doubletest");
|
||||
doublelist.add(42.23d);
|
||||
doublelist.add(69.69d);
|
||||
if (doublelist.size() == 2 && doublelist.get(0) == 42.23d && doublelist.get(1) == 69.69d) {
|
||||
@@ -106,7 +104,7 @@ public class ListTest implements Test {
|
||||
}
|
||||
|
||||
// Float
|
||||
NBTList<Float> floatlist = comp.getFloatList("floattest");
|
||||
ReadWriteNBTList<Float> floatlist = comp.getFloatList("floattest");
|
||||
floatlist.add(42.23f);
|
||||
floatlist.add(69.69f);
|
||||
if (floatlist.size() == 2 && floatlist.get(0) == 42.23f && floatlist.get(1) == 69.69f) {
|
||||
@@ -120,7 +118,7 @@ public class ListTest implements Test {
|
||||
}
|
||||
|
||||
// Long
|
||||
NBTList<Long> longlist = comp.getLongList("longtest");
|
||||
ReadWriteNBTList<Long> longlist = comp.getLongList("longtest");
|
||||
longlist.add(1241234124124l);
|
||||
longlist.add(1231454321312l);
|
||||
if (longlist.size() == 2 && longlist.get(0) == 1241234124124l && longlist.get(1) == 1231454321312l) {
|
||||
@@ -134,7 +132,7 @@ public class ListTest implements Test {
|
||||
}
|
||||
|
||||
// int[]
|
||||
NBTList<int[]> intArrayList = comp.getIntArrayList("intatest");
|
||||
ReadWriteNBTList<int[]> intArrayList = comp.getIntArrayList("intatest");
|
||||
intArrayList.add(new int[] { 1, 2, 3 });
|
||||
intArrayList.add(new int[] { 4, 2, 0 });
|
||||
if (intArrayList.size() == 2 && Arrays.equals(new int[] { 1, 2, 3 }, intArrayList.get(0))
|
||||
@@ -149,7 +147,7 @@ public class ListTest implements Test {
|
||||
}
|
||||
|
||||
// UUID
|
||||
NBTList<UUID> uuidList = comp.getUUIDList("uuidtest");
|
||||
ReadWriteNBTList<UUID> uuidList = comp.getUUIDList("uuidtest");
|
||||
uuidList.add(UUID.fromString("fce0323d-7f50-4317-9720-5f6b14cf78ea"));
|
||||
uuidList.add(UUID.fromString("853c80ef-3c37-49fd-aa49-938b674adae6"));
|
||||
if (uuidList.size() == 2 && UUID.fromString("fce0323d-7f50-4317-9720-5f6b14cf78ea").equals(uuidList.get(0))
|
||||
|
||||
@@ -3,6 +3,10 @@ package de.tr7zw.nbtapi.plugin.tests.compounds;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTContainer;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
@@ -21,6 +25,11 @@ public class StreamTest implements Test {
|
||||
if (!container.toString().equals(base.getOrCreateCompound("sub").toString())) {
|
||||
throw new NbtApiException("Component content did not match! " + base.getCompound("sub") + " " + container);
|
||||
}
|
||||
ItemStack item = new ItemStack(Material.STICK);
|
||||
|
||||
NBT.modify(item, nbt -> {
|
||||
nbt.writeCompound(outStream);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.compounds;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTContainer;
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class SubCompoundsTest implements Test {
|
||||
@@ -19,9 +19,9 @@ public class SubCompoundsTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
NBTContainer cont = new NBTContainer();
|
||||
ReadWriteNBT cont = NBT.createNBTObject();
|
||||
|
||||
NBTCompound comp = cont.addCompound(COMP_TEST_KEY);
|
||||
ReadWriteNBT comp = cont.getOrCreateCompound(COMP_TEST_KEY);
|
||||
comp.setString(STRING_TEST_KEY, STRING_TEST_VALUE + "2");
|
||||
comp.setInteger(INT_TEST_KEY, INT_TEST_VALUE * 2);
|
||||
comp.setDouble(DOUBLE_TEST_KEY, DOUBLE_TEST_VALUE * 2);
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.compounds;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTContainer;
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTType;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class TypeTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
NBTCompound comp = new NBTContainer();
|
||||
ReadWriteNBT comp = NBT.createNBTObject();
|
||||
comp.setString("s", "test");
|
||||
comp.setInteger("i", 42);
|
||||
comp.addCompound("c");
|
||||
comp.getOrCreateCompound("c");
|
||||
if (comp.getType("s") != NBTType.NBTTagString || comp.getType("i") != NBTType.NBTTagInt
|
||||
|| comp.getType("c") != NBTType.NBTTagCompound)
|
||||
throw new NbtApiException("One parsed type did not match what it should have been!");
|
||||
|
||||
+11
-10
@@ -6,8 +6,7 @@ import org.bukkit.entity.Animals;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Monster;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTEntity;
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
@@ -23,14 +22,16 @@ public class EntityCustomNbtPersistentTest implements Test {
|
||||
try {
|
||||
if (!world.getEntitiesByClasses(Animals.class, Monster.class).isEmpty()) {
|
||||
Entity ent = world.getEntitiesByClasses(Animals.class, Monster.class).iterator().next();
|
||||
NBTEntity nbtEnt = new NBTEntity(ent);
|
||||
NBTCompound comp = nbtEnt.getPersistentDataContainer();
|
||||
comp.setString("Hello", "World");
|
||||
NBTEntity nbtent = new NBTEntity(ent);
|
||||
if (!nbtent.toString().contains("Hello:\"World\"")) {
|
||||
throw new NbtApiException("Custom Data did not save to the Entity!");
|
||||
}
|
||||
comp.removeKey("Hello");
|
||||
NBT.modifyPersistentData(ent, comp -> {
|
||||
comp.setString("Hello", "World");
|
||||
});
|
||||
|
||||
NBT.modifyPersistentData(ent, comp -> {
|
||||
if (!comp.toString().contains("Hello:\"World\"")) {
|
||||
throw new NbtApiException("Custom Data did not save to the Entity!");
|
||||
}
|
||||
comp.removeKey("Hello");
|
||||
});
|
||||
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
|
||||
+5
-1
@@ -27,7 +27,11 @@ public class ComponentsTest implements Test {
|
||||
throw new NbtApiException("ReadComponent didn't work!");
|
||||
}
|
||||
NBT.modifyComponents(item, nbt -> {
|
||||
nbt.setString("minecraft:custom_name", "{\"extra\":[\"foobar\"],\"text\":\"\"}");
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4)) {
|
||||
nbt.mergeCompound(NBT.parseNBT("{\"minecraft:custom_name\":[{\"text\":\"foobar\",\"italic\":false}]}"));
|
||||
} else {
|
||||
nbt.setString("minecraft:custom_name", "{\"extra\":[\"foobar\"],\"text\":\"\"}");
|
||||
}
|
||||
});
|
||||
if(!item.getItemMeta().getDisplayName().equals("foobar")) {
|
||||
throw new NbtApiException("ModifyComponent didn't work!");
|
||||
|
||||
+16
-7
@@ -1,13 +1,15 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.items;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTType;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTContainer;
|
||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
@@ -19,14 +21,21 @@ public class ItemConversionTest implements Test {
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setLore(Lists.newArrayList("Firest Line", "Second Line"));
|
||||
item.setItemMeta(meta);
|
||||
String nbt = NBTItem.convertItemtoNBT(item).toString();
|
||||
if (!nbt.contains("Firest Line") || !nbt.contains("Second Line"))
|
||||
throw new NbtApiException("The Item nbt '" + nbt + "' didn't contain the lore");
|
||||
ItemStack rebuild = NBTItem.convertNBTtoItem(new NBTContainer(nbt));
|
||||
|
||||
ReadWriteNBT nbt = NBT.itemStackToNBT(item);
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_12_R1)
|
||||
&& !nbt.hasTag("DataVersion", NBTType.NBTTagInt)) {
|
||||
throw new NbtApiException("The item nbt '" + nbt + "' didn't contain the data version");
|
||||
}
|
||||
|
||||
String nbtString = nbt.toString();
|
||||
if (!nbtString.contains("Firest Line") || !nbtString.contains("Second Line"))
|
||||
throw new NbtApiException("The Item nbt '" + nbtString + "' didn't contain the lore");
|
||||
ItemStack rebuild = NBT.itemStackFromNBT(NBT.parseNBT(nbtString));
|
||||
if (!item.isSimilar(rebuild))
|
||||
throw new NbtApiException("Rebuilt item did not match the original!");
|
||||
|
||||
NBTContainer cont = new NBTContainer();
|
||||
ReadWriteNBT cont = NBT.createNBTObject();
|
||||
cont.setItemStack("testItem", item);
|
||||
if (!item.isSimilar(cont.getItemStack("testItem")))
|
||||
throw new NbtApiException("Rebuilt item did not match the original!");
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.items;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.utils.NBTJsonUtil;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class ItemJsonTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
ItemStack item = new ItemStack(Material.STONE);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setDisplayName("test");
|
||||
meta.setUnbreakable(true);
|
||||
item.setItemMeta(meta);
|
||||
JsonElement elem = NBTJsonUtil.itemStackToJson(item);
|
||||
if (elem == null) {
|
||||
throw new NbtApiException("Getting the Json didn't work correctly! " + item);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -3,9 +3,9 @@ package de.tr7zw.nbtapi.plugin.tests.items;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class ItemStackConversionTest implements Test {
|
||||
@@ -14,8 +14,8 @@ public class ItemStackConversionTest implements Test {
|
||||
public void test() throws Exception {
|
||||
ItemStack[] src = new ItemStack[] { new ItemStack(Material.STONE), new ItemStack(Material.STICK),
|
||||
new ItemStack(Material.AIR), new ItemStack(Material.STONE) };
|
||||
NBTCompound comp = NBTItem.convertItemArraytoNBT(src);
|
||||
ItemStack[] recreated = NBTItem.convertNBTtoItemArray(comp);
|
||||
ReadWriteNBT comp = NBT.itemStackArrayToNBT(src);
|
||||
ItemStack[] recreated = NBT.itemStackArrayFromNBT(comp);
|
||||
if (recreated == null || src.length != recreated.length) {
|
||||
throw new NbtApiException("Size did not match!");
|
||||
}
|
||||
|
||||
@@ -29,6 +29,10 @@ public class LegacyItemTest implements Test {
|
||||
|| !"test".equals(item.getItemMeta().getDisplayName())) {
|
||||
throw new NbtApiException("1.12.2 item didn't load correctly! " + item);
|
||||
}
|
||||
|
||||
ItemStack item2 = NBT.itemStackFromNBT(NBT.parseNBT("{DataVersion:" + DataFixerUtil.VERSION1_12_2 + ",id:cobblestone,Count:42,tag:{display:{Name:\"test\"},ench:[{lvl:3,id:34}]}}"));
|
||||
if (!item.equals(item2))
|
||||
throw new NbtApiException("Data-fixed 1.12.2 item didn't load correctly! " + item2);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTTileEntity;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
@@ -22,8 +23,16 @@ 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);
|
||||
if (MinecraftVersion.isNewerThan(MinecraftVersion.MC1_21_R1)) {
|
||||
// 1.21 changed the lock logic. So just try to get/set data, dont check for now
|
||||
NBT.modify(block.getState(), nbt -> {
|
||||
nbt.setString("foo", "bar");
|
||||
});
|
||||
block.setType(Material.AIR);
|
||||
return;
|
||||
}
|
||||
NBTTileEntity tile = new NBTTileEntity(block.getState());
|
||||
if (!MinecraftVersion.isNewerThan(MinecraftVersion.MC1_17_R1)) {
|
||||
if (tile.getInteger("y") != 254) {
|
||||
|
||||
+12
-11
@@ -5,8 +5,7 @@ import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTTileEntity;
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
@@ -25,16 +24,18 @@ 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();
|
||||
persistentData.setString("Foo", "Bar");
|
||||
if (!new NBTTileEntity(block.getState()).getPersistentDataContainer().getString("Foo")
|
||||
.equals("Bar")) {
|
||||
block.setType(Material.AIR);
|
||||
throw new NbtApiException("Custom Data did not save to the Tile!");
|
||||
}
|
||||
NBT.modifyPersistentData(block.getState(), persistentData -> {
|
||||
persistentData.setString("Foo", "Bar");
|
||||
});
|
||||
NBT.getPersistentData(block.getState(), persistentData -> {
|
||||
if (!persistentData.getString("Foo").equals("Bar")) {
|
||||
block.setType(Material.AIR);
|
||||
throw new NbtApiException("Custom Data did not save to the Tile!");
|
||||
}
|
||||
return null;
|
||||
});
|
||||
block.setType(Material.AIR);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>item-nbt-parent</artifactId>
|
||||
<version>2.13.0</version>
|
||||
<version>2.15.0</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.15.0</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;
|
||||
@@ -25,7 +24,7 @@ public class MappingsParser {
|
||||
public static StringBuilder builder = new StringBuilder();
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
File input = new File("minecraft_server.1.21.txt");
|
||||
File input = new File("minecraft_server.1.21.4.txt");
|
||||
List<String> lines = Files.readAllLines(input.toPath());
|
||||
|
||||
Map<String, ClassWrapper> classes = new HashMap<>();
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>item-nbt-parent</artifactId>
|
||||
<version>2.13.0</version>
|
||||
<version>2.15.0</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.15.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>item-nbt-parent</artifactId>
|
||||
<version>2.13.0</version>
|
||||
<version>2.15.0</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.15.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -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.15.0</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>
|
||||
@@ -90,7 +88,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<version>3.14.0</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
@@ -112,7 +110,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.7.0</version>
|
||||
<version>3.11.2</version>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
</configuration>
|
||||
@@ -141,7 +139,7 @@
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>license-maven-plugin</artifactId>
|
||||
<version>2.4.0</version>
|
||||
<version>2.5.0</version>
|
||||
<configuration>
|
||||
<licenseName>mit</licenseName>
|
||||
<licenseFile>LICENSE</licenseFile>
|
||||
|
||||
@@ -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.15.0</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.15.0</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);
|
||||
```
|
||||
|
||||
@@ -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
|
||||
NBTFileHandle levelNbtFile = NBT.getFileHandle(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;
|
||||
}
|
||||
|
||||
NBTFileHandle playerNbtFile = NBT.getFileHandle(playerFile);
|
||||
|
||||
// Change player's health
|
||||
float health = playerNbtFile.getFloat("Health");
|
||||
playerNbtFile.setFloat("Health", health + 5);
|
||||
|
||||
// Once finished, save the file
|
||||
playerNbtFile.save();
|
||||
```
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
## 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.
|
||||
|
||||
See [this wiki section](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API#accessing-custom-data) on how to handle custom entity nbt data without NBTInjector.
|
||||
+8
-17
@@ -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 [](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}"));
|
||||
});
|
||||
```
|
||||
|
||||
+7
-4
@@ -1,10 +1,13 @@
|
||||
## 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)
|
||||
- [CommandAPI](https://github.com/JorelAli/CommandAPI)
|
||||
- [CommandAPI](https://github.com/CommandAPI/CommandAPI)
|
||||
- [SkBee](https://github.com/ShaneBeee/SkBee/)
|
||||
- [Monumenta](https://github.com/TeamMonumenta/monumenta-plugins-public/)
|
||||
- [SummonFriendlyMobs](https://github.com/ArmyFury/SummonFriendlyMobs)
|
||||
- [EvenMoreFish](https://github.com/Oheers/EvenMoreFish)
|
||||
|
||||
___
|
||||
|
||||
Want your plugin added to this list? Submit a PR editing this file located in `~/wiki/Plugins.md`!
|
||||
@@ -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);
|
||||
});
|
||||
```
|
||||
|
||||
+73
-28
@@ -1,53 +1,73 @@
|
||||
# Option 1) NBT-API as a dependency
|
||||
To start using NB-API, you either need to depend on its plugin version, or shade (include) it inside your plugin.
|
||||
|
||||
Add the following Entries to your Gradle build at the correct location:
|
||||
> [!IMPORTANT]
|
||||
> Plugin and shaded versions have different ``artifactId``. Make sure to correctly choose the one you need!
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Alternative ways of loading the api like Libby are not supported on Discord/Github issues.
|
||||
|
||||
# Option 1) NBT-API as a dependency (recommended)
|
||||
|
||||
Add the following entries to your Gradle build at the correct locations:
|
||||
|
||||
```groovy
|
||||
repositories {
|
||||
...
|
||||
maven {
|
||||
name = "CodeMC"
|
||||
url = uri("https://repo.codemc.io/repository/maven-public/")
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
```groovy
|
||||
compileOnly("de.tr7zw:item-nbt-api-plugin:VERSION")
|
||||
```
|
||||
|
||||
(Get the current Version from [here](https://www.spigotmc.org/resources/nbt-api.7939/))
|
||||
(Get the current ``VERSION`` from [here](https://modrinth.com/plugin/nbtapi/versions))
|
||||
|
||||
```groovy
|
||||
repositories {
|
||||
...
|
||||
maven {
|
||||
name = "CodeMC"
|
||||
url = uri("https://repo.codemc.io/repository/maven-public/")
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Finally, add the API as dependency to your ``plugin.yml``
|
||||
Add the API as dependency to your ``plugin.yml``:
|
||||
|
||||
```yml
|
||||
depend: [NBTAPI]
|
||||
```
|
||||
|
||||
# Option 2) Shading the NBT-API into your plugin
|
||||
Or, if you are using ``paper-plugin.yml``:
|
||||
|
||||
To include NBT-API directly in your plugin, you can use the gradle shadow plugin.
|
||||
```yml
|
||||
dependencies:
|
||||
server:
|
||||
NBTAPI:
|
||||
load: BEFORE
|
||||
required: true
|
||||
join-classpath: true
|
||||
```
|
||||
|
||||
# Option 2) Shading the NBT-API into your plugin (Not recommended)
|
||||
|
||||
> [!WARNING]
|
||||
> Due to the increasing amount of pitfalls in modern Paper, shading is not recommended. Please test with the normal plugin dependency before reporting issues.
|
||||
|
||||
To include NBT-API directly in your plugin, you can use the [Gradle Shadow Plugin](https://gradleup.com/shadow/).
|
||||
|
||||
Create an empty ``.mojang-mapped`` file in the META-INF folder of your plugin for 1.20+ Paper support.
|
||||
|
||||
> [!WARNING]
|
||||
> Not adding this flag will make the shaded api not work on the latest Paper. It might also break other reflections/nms logic!
|
||||
|
||||
Add the plugin to the build configuration, as shown here:
|
||||
|
||||
```groovy
|
||||
plugins {
|
||||
id("com.github.johnrengelman.shadow") version "VERSION"
|
||||
id("com.gradleup.shadow") version "VERSION"
|
||||
}
|
||||
```
|
||||
|
||||
The latest version of the shadow plugin can be found [here](https://github.com/johnrengelman/shadow/releases).
|
||||
<br/>
|
||||
The latest version of the shadow plugin can be found [here](https://plugins.gradle.org/plugin/com.gradleup.shadow).
|
||||
|
||||
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 +79,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 +96,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 +104,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
|
||||
}
|
||||
```
|
||||
|
||||
+92
-42
@@ -1,6 +1,27 @@
|
||||
# Option 1) NBT-API as a dependency
|
||||
To start using NB-API, you either need to depend on its plugin version, or shade (include) it inside your plugin.
|
||||
|
||||
Add the following Entries to your pom at the correct location:
|
||||
> [!IMPORTANT]
|
||||
> Plugin and shaded versions have different ``artifactId``. Make sure to correctly choose the one you need!
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Alternative ways of loading the api like Libby are not supported on Discord/Github issues.
|
||||
|
||||
# Option 1) NBT-API as a dependency (recommended)
|
||||
|
||||
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,62 +32,45 @@ 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]
|
||||
```
|
||||
|
||||
# Option 2) Shading the NBT-API into your plugin
|
||||
Or, if you are using ``paper-plugin.yml``:
|
||||
|
||||
Add the following Entries to your pom at the correct location:
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>item-nbt-api</artifactId>
|
||||
<version>VERSION</version>
|
||||
</dependency>
|
||||
```yml
|
||||
dependencies:
|
||||
server:
|
||||
NBTAPI:
|
||||
load: BEFORE
|
||||
required: true
|
||||
join-classpath: true
|
||||
```
|
||||
|
||||
(Get the current Version from [here](https://modrinth.com/plugin/nbtapi/versions))
|
||||
# Option 2) Shading the NBT-API into your plugin (Not recommended)
|
||||
|
||||
**IMPORTANT: This is not the same ``artifactId`` as using it as dependency! Never shade the ``-plugin`` artifact!**
|
||||
> [!WARNING]
|
||||
> Due to the increasing amount of pitfalls in modern Paper, shading is not recommended. Please test with the normal plugin dependency before reporting issues.
|
||||
|
||||
```xml
|
||||
<repositories>
|
||||
...
|
||||
<!-- CodeMC -->
|
||||
<repository>
|
||||
<id>codemc-repo</id>
|
||||
<url>https://repo.codemc.io/repository/maven-public/</url>
|
||||
<layout>default</layout>
|
||||
</repository>
|
||||
...
|
||||
</repositories>
|
||||
```
|
||||
To include NBT-API directly in your plugin, you can use the maven shade plugin.
|
||||
|
||||
Create an empty ``.mojang-mapped`` file in the META-INF folder of your plugin for 1.20+ Paper support.
|
||||
|
||||
> [!WARNING]
|
||||
> Not adding this flag will make the shaded api not work on the latest Paper. It might also break other reflections/nms logic!
|
||||
|
||||
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 +92,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 +103,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
|
||||
}
|
||||
```
|
||||
|
||||
+469
-60
@@ -1,88 +1,497 @@
|
||||
## 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. Your specific use-case might not yet be covered by the wiki, so make sure to explore the [Javadoc](https://tr7zw.github.io/Item-NBT-API/v2-api/), 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 SNBT to nbt
|
||||
ReadWriteNBT nbt = NBT.parseNBT("{Health:20.0f,Motion:[0.0d,10.0d,0.0d],Silent:1b}");
|
||||
// Get the NBT back as a SNBT (works with any NBT object)
|
||||
String snbt = nbt.toString();
|
||||
// Turn back into nbt again
|
||||
ReadWriteNBT nbt2 = NBT.parseNBT(snbt);
|
||||
```
|
||||
|
||||
#### Comparing NBT data
|
||||
|
||||
As with other objects in Java, you may compare nbt using `equals`.
|
||||
|
||||
To see what exactly mismatched, you can use `ReadableNBT#extractDifference`:
|
||||
|
||||
```java
|
||||
ReadWriteNBT nbt1 = NBT.parseNBT("{intTag:1,compoundTag:{floatTag:20.0f,booleanTag:1b}},intArray:[I;1,2]");
|
||||
ReadWriteNBT nbt2 = NBT.parseNBT("{intTag:1,compoundTag:{floatTag:20.0f,booleanTag:0b}},intArray:[I;1,2,3],alsoIntTag:2");
|
||||
|
||||
ReadWriteNBT diff1 = nbt1.extractDifference(nbt2);
|
||||
ReadWriteNBT diff2 = nbt2.extractDifference(nbt1);
|
||||
```
|
||||
|
||||
For the example above, `ReadableNBT#toString` will produce:
|
||||
|
||||
diff1: `{compoundTag:{booleanTag:1b},intArray:[I;1,2]}`
|
||||
|
||||
diff2: `{compoundTag:{booleanTag:0b},intArray:[I;1,2,3],alsoIntTag:2}`
|
||||
|
||||
#### 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
|
||||
// Get the list (will create it if needed)
|
||||
ReadWriteNBTCompoundList nbtList = nbt.getOrCreateCompound("foo").getCompoundList("other_key");
|
||||
// Add new compound to the list
|
||||
ReadWriteNBT nbtListEntry = nbtList.addCompound();
|
||||
nbtListEntry.setBoolean("bar", true);
|
||||
// Add existing nbt compound to the list
|
||||
ReadWriteNBT otherNbtListEntry = nbtList.addCompound(NBT.parseNBT("{foo_bar:1b}"));
|
||||
|
||||
// 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.
|
||||
> Setting ItemMeta will override any changes made to item's nbt.
|
||||
|
||||
```java
|
||||
// WRONG, do not do this!
|
||||
ItemMeta meta = itemStack.getItemMeta();
|
||||
meta.setDisplayName("Modified!");
|
||||
NBT.modify(itemStack, nbt -> nbt.setBoolean("modified", true));
|
||||
itemStack.setItemMeta(meta); // Will undo all changes to nbt!
|
||||
|
||||
|
||||
// Correct, both ItemMeta and NBT will be applied
|
||||
NBT.modify(itemStack, nbt -> nbt.setBoolean("modified", true));
|
||||
// Taking ItemMeta snapshot after changes to nbt
|
||||
ItemMeta meta = itemStack.getItemMeta();
|
||||
meta.setDisplayName("Modified!");
|
||||
itemStack.setItemMeta(meta);
|
||||
// If making any further changes with NBT & ItemMeta,
|
||||
// re-take the item's ItemMeta after changing the nbt!
|
||||
```
|
||||
|
||||
Alternatively, you may safely modify ItemMeta inside the NBT scope:
|
||||
|
||||
```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((readOnlyNbt, meta) -> { // Do not modify the nbt while modifying the meta!
|
||||
meta.setDisplayName("Kills: " + readOnlyNbt.getOrDefault("kills", 0));
|
||||
});
|
||||
//Do more stuff
|
||||
// Do more stuff
|
||||
});
|
||||
```
|
||||
|
||||
###### 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+!
|
||||
|
||||
// Only reading vanilla data
|
||||
NBT.getComponents(item, nbt -> {
|
||||
if (nbt.hasTag("minecraft:custom_name")) {
|
||||
String customName = nbt.getString("minecraft:custom_name");
|
||||
}
|
||||
});
|
||||
|
||||
// Gameprofile to NBT
|
||||
ReadWriteNBT nbt = NBT.gameProfileToNBT(profile);
|
||||
// NBT to Gameprofile
|
||||
GameProfile profile = NBT.nbtToGameProfile(nbt);
|
||||
// ItemStack to NBT
|
||||
// Modifying vanilla data
|
||||
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
|
||||
|
||||
> [!WARNING]
|
||||
> Persistent data storage for custom (block-)entity nbt is only available in 1.14+.
|
||||
>
|
||||
> If you need to support versions below that, for entities 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).
|
||||
|
||||
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
|
||||
|
||||
NBTFileHandle allows working with nbt files.
|
||||
|
||||
```java
|
||||
// Will automatically create the file if it does not exist
|
||||
NBTFileHandle nbtFile = NBT.getFileHandle(new File("directory", "test.nbt"));
|
||||
// Setting data
|
||||
nbtFile.setString("foo", "bar");
|
||||
// Saving the file after applying changes
|
||||
nbtFile.save();
|
||||
```
|
||||
|
||||
Alternatively, you may read the nbt file without maintaining the link to it.
|
||||
Unlike NBTFileHandle, the file won't be automatically created if it does not exist.
|
||||
|
||||
```java
|
||||
File file = new File("directory", "test.nbt");
|
||||
// Reading data from file (will return an empty compound if the file does not exist)
|
||||
ReadWriteNBT nbt = NBT.readFile(file);
|
||||
// Saving nbt to file
|
||||
NBT.writeFile(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 (SNBT)
|
||||
|
||||
#### 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
|
||||
ReadWriteNBT nbt = NBT.parseNBT(json);
|
||||
|
||||
// Reminder (NBT <-> String)
|
||||
String snbt = nbt.toString();
|
||||
ReadWriteNBT nbt = NBT.parseNBT(snbt);
|
||||
```
|
||||
|
||||
## 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
@@ -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
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user