mirror of
https://github.com/tr7zw/Item-NBT-API.git
synced 2026-11-04 16:50:12 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5bdddc134a | ||
|
|
733b871c09 | ||
|
|
bc48239fdd | ||
|
|
f182204b2f | ||
|
|
a424ce1e85 | ||
|
|
c881566c14 | ||
|
|
2d6aa142de | ||
|
|
cc1436cd09 | ||
|
|
4506dd37da | ||
|
|
bbc02e1299 | ||
|
|
ca9d5ad140 | ||
|
|
25c82a5ad0 | ||
|
|
17d40445d2 | ||
|
|
47ad3591df | ||
|
|
b3652ecf7d | ||
|
|
46a9116613 | ||
|
|
5776be4a35 | ||
|
|
9fbee68966 | ||
|
|
b277f0b01d | ||
|
|
e4793a0d46 | ||
|
|
7c34542b86 | ||
|
|
856bf5ed6d | ||
|
|
123da87a3a | ||
|
|
f3d7545c6b | ||
|
|
3b29fe399e | ||
|
|
c368318bb6 | ||
|
|
c1473dfa97 | ||
|
|
a360ca50f4 | ||
|
|
8b1ca8447e | ||
|
|
b66353d0d0 | ||
|
|
5bec1371d2 | ||
|
|
8cbb6af964 | ||
|
|
309455ecfc | ||
|
|
22c0b0385b | ||
|
|
bc6bd56ce9 | ||
|
|
fcdf0929f9 | ||
|
|
e1c6ce2575 | ||
|
|
2fcc1d82ab | ||
|
|
eec2c0980e | ||
|
|
3ddf3e53dc | ||
|
|
70d5ab12eb | ||
|
|
a63e9ba8f4 | ||
|
|
d8a59d6383 | ||
|
|
943c7d23d6 | ||
|
|
6c70ce2ccc | ||
|
|
c1b7854fbb | ||
|
|
f9f1c204b6 | ||
|
|
789f1fea96 | ||
|
|
0e40144f09 | ||
|
|
1c6315e014 | ||
|
|
91f345adf2 | ||
|
|
71783a8dc9 | ||
|
|
5d06ae9275 | ||
|
|
835fdf48cd | ||
|
|
31d77d25f9 | ||
|
|
6cb08ac919 | ||
|
|
08a92ac06c |
No files matched your search
@@ -1,13 +1,14 @@
|
||||
# Item-NBT-API
|
||||
|
||||
[](https://modrinth.com/plugin/nbtapi)
|
||||
[](https://discordapp.com/invite/yk4caxM)
|
||||
|
||||
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
|
||||
|
||||
[](https://ci.codemc.org/job/Tr7zw/job/Item-NBT-API/)[](https://sonarcloud.io/summary/overall?id=tr7zw_Item-NBT-API)[](https://sonarcloud.io/summary/overall?id=tr7zw_Item-NBT-API)[](https://sonarcloud.io/summary/overall?id=tr7zw_Item-NBT-API)
|
||||
[](https://discordapp.com/invite/yk4caxM)
|
||||
[](https://www.patreon.com/tr7zw)
|
||||
|
||||
### SpigotMC Status
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>item-nbt-parent</artifactId>
|
||||
<version>2.15.1</version>
|
||||
<version>2.16.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>item-nbt-api</artifactId>
|
||||
@@ -21,7 +21,7 @@
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.2.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
@@ -38,7 +38,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<version>3.6.2</version>
|
||||
<configuration>
|
||||
<relocations>
|
||||
<relocation>
|
||||
|
||||
@@ -9,6 +9,9 @@ import java.util.logging.Level;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.utils.CheckUtil;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -727,4 +730,204 @@ public class NBT {
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads block‑specific data that was previously stored in the chunk's
|
||||
* persistent data container.
|
||||
* <p>
|
||||
* The data is stored inside the {@code blocks} compound of the chunk's
|
||||
* persistent data container, using a key formed as {@code X_Y_Z} where
|
||||
* X, Y, Z are the block's coordinates.
|
||||
* <p>
|
||||
* <b>Minecraft version:</b> this method requires <b>1.16.4 or newer</b>.
|
||||
*
|
||||
* @param block the block whose stored data is to be read
|
||||
* @param consumer the consumer that receives a {@link ReadableNBT} view of the data
|
||||
*/
|
||||
public static void readChunkPDC(Block block, Consumer<ReadableNBT> consumer) {
|
||||
processBlockChunkPDC(block, false, nbt -> {
|
||||
consumer.accept(nbt);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads block‑specific data from the chunk's persistent data container and
|
||||
* applies a function to produce a result.
|
||||
* <p>
|
||||
* The data is stored inside the {@code blocks} compound of the chunk's
|
||||
* persistent data container, using a key formed as {@code X_Y_Z} where
|
||||
* X, Y, Z are the block's coordinates.
|
||||
* <p>
|
||||
* <b>Minecraft version:</b> this method requires <b>1.16.4 or newer</b>.
|
||||
*
|
||||
* @param block the block whose stored data is to be read
|
||||
* @param function the function that processes the {@link ReadableNBT} and
|
||||
* returns a value
|
||||
* @param <T> the type of the returned value
|
||||
* @return the result of the function applied to the data
|
||||
*/
|
||||
public static <T> T readAndGetChunkPDC(Block block, Function<ReadableNBT, T> function) {
|
||||
return processBlockChunkPDC(block, false, function::apply);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies block‑specific data stored in the chunk's persistent data container.
|
||||
* <p>
|
||||
* The data is stored inside the {@code blocks} compound of the chunk's
|
||||
* persistent data container, using a key formed as {@code X_Y_Z} where
|
||||
* X, Y, Z are the block's coordinates.
|
||||
* <p>
|
||||
* <b>Caution:</b> the data remains even if the block is broken, replaced, moved,
|
||||
* or exploded, etc. You should manually remove the data when it is no longer needed.
|
||||
* <p>
|
||||
* <b>Minecraft version:</b> this method requires <b>1.16.4 or newer</b>.
|
||||
*
|
||||
* @param block the block whose data is to be modified
|
||||
* @param consumer the consumer that receives the {@link ReadWriteNBT} and
|
||||
* applies modifications
|
||||
*/
|
||||
public static void modifyChunkPDC(Block block, Consumer<ReadWriteNBT> consumer) {
|
||||
processBlockChunkPDC(block, true, nbt -> {
|
||||
consumer.accept(nbt);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies block‑specific data in the chunk's persistent data container and
|
||||
* returns a result computed from the modified data.
|
||||
* <p>
|
||||
* The data is stored inside the {@code blocks} compound of the chunk's
|
||||
* persistent data container, using a key formed as {@code X_Y_Z} where
|
||||
* X, Y, Z are the block's coordinates.
|
||||
* <p>
|
||||
* <b>Caution:</b> the data remains even if the block is broken, replaced, moved,
|
||||
* or exploded, etc. You should manually remove the data when it is no longer needed.
|
||||
* <p>
|
||||
* <b>Minecraft version:</b> this method requires <b>1.16.4 or newer</b>.
|
||||
*
|
||||
* @param block the block whose data is to be modified
|
||||
* @param function the function that receives the {@link ReadWriteNBT}, modifies
|
||||
* it, and returns a value
|
||||
* @param <T> the type of the returned value
|
||||
* @return the result of the function after modification
|
||||
*/
|
||||
public static <T> T modifyAndGetChunkPDC(Block block, Function<ReadWriteNBT, T> function) {
|
||||
return processBlockChunkPDC(block, true, function::apply);
|
||||
}
|
||||
|
||||
private static <T> T processBlockChunkPDC(Block block, boolean createIfAbsent, Function<NBTCompound, T> action) {
|
||||
CheckUtil.assertAvailable(MinecraftVersion.MC1_16_R3);
|
||||
|
||||
String blockKey = block.getX() + "_" + block.getY() + "_" + block.getZ();
|
||||
|
||||
NBTCompound chunkData = new NBTPersistentDataContainer(block.getChunk().getPersistentDataContainer(), !createIfAbsent);
|
||||
|
||||
NBTCompound blocksData = createIfAbsent
|
||||
? chunkData.getOrCreateCompound("blocks")
|
||||
: chunkData.getCompound("blocks");
|
||||
|
||||
NBTCompound blockData;
|
||||
if (createIfAbsent) {
|
||||
blockData = blocksData.getOrCreateCompound(blockKey);
|
||||
} else {
|
||||
blockData = blocksData == null ? null : blocksData.getCompound(blockKey);
|
||||
if (blockData == null) {
|
||||
blockData = new NBTContainer().setReadOnly(true);
|
||||
}
|
||||
}
|
||||
|
||||
T result = action.apply(blockData);
|
||||
|
||||
if (createIfAbsent) {
|
||||
if (blockData.isEmpty()) {
|
||||
blocksData.removeKey(blockKey);
|
||||
}
|
||||
if (blocksData.isEmpty()) {
|
||||
chunkData.removeKey("blocks");
|
||||
}
|
||||
}
|
||||
|
||||
if (result instanceof ReadableNBT || result instanceof ReadableNBTList<?>) {
|
||||
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the chunk's persistent data container.
|
||||
* <p>
|
||||
* <b>Minecraft version:</b> this method requires <b>1.16.4 or newer</b>.
|
||||
*
|
||||
* @param chunk the chunk whose persistent data is to be read
|
||||
* @param consumer the consumer that receives a {@link ReadableNBT} view of the data
|
||||
*/
|
||||
public static void readChunkPDC(Chunk chunk, Consumer<ReadableNBT> consumer) {
|
||||
processChunkPDC(chunk, false, nbt -> {
|
||||
consumer.accept(nbt);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the chunk's persistent data container and applies a function to produce a result.
|
||||
* <p>
|
||||
* <b>Minecraft version:</b> this method requires <b>1.16.4 or newer</b>.
|
||||
*
|
||||
* @param chunk the chunk whose persistent data is to be read
|
||||
* @param function the function that processes the {@link ReadableNBT} and
|
||||
* returns a value
|
||||
* @param <T> the type of the returned value
|
||||
* @return the result of the function applied to the data
|
||||
*/
|
||||
public static <T> T readAndGetChunkPDC(Chunk chunk, Function<ReadableNBT, T> function) {
|
||||
return processChunkPDC(chunk, false, function::apply);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the chunk's persistent data container.
|
||||
* <p>
|
||||
* <b>Minecraft version:</b> this method requires <b>1.16.4 or newer</b>.
|
||||
*
|
||||
* @param chunk the chunk whose persistent data is to be modified
|
||||
* @param consumer the consumer that receives the {@link ReadWriteNBT} and
|
||||
* applies modifications
|
||||
*/
|
||||
public static void modifyChunkPDC(Chunk chunk, Consumer<ReadWriteNBT> consumer) {
|
||||
processChunkPDC(chunk, true, nbt -> {
|
||||
consumer.accept(nbt);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the chunk's persistent data container and returns a result computed from the modified data.
|
||||
* <p>
|
||||
* <b>Minecraft version:</b> this method requires <b>1.16.4 or newer</b>.
|
||||
*
|
||||
* @param chunk the chunk whose persistent data is to be modified
|
||||
* @param function the function that receives the {@link ReadWriteNBT}, modifies
|
||||
* it, and returns a value
|
||||
* @param <T> the type of the returned value
|
||||
* @return the result of the function after modification
|
||||
*/
|
||||
public static <T> T modifyAndGetChunkPDC(Chunk chunk, Function<ReadWriteNBT, T> function) {
|
||||
return processChunkPDC(chunk, true, function::apply);
|
||||
}
|
||||
|
||||
private static <T> T processChunkPDC(Chunk chunk, boolean createIfAbsent, Function<NBTCompound, T> action) {
|
||||
CheckUtil.assertAvailable(MinecraftVersion.MC1_16_R3);
|
||||
|
||||
NBTCompound chunkData = new NBTPersistentDataContainer(chunk.getPersistentDataContainer(), !createIfAbsent);
|
||||
|
||||
T result = action.apply(chunkData);
|
||||
|
||||
if (result instanceof ReadableNBT || result instanceof ReadableNBTList<?>) {
|
||||
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,16 +7,17 @@ import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
/**
|
||||
* Helper class to store NBT data to Block Locations. Use getData() to get the
|
||||
* NBT instance. Important notes:
|
||||
*
|
||||
* <p>
|
||||
* - Non BlockEntities can not have NBT data. This stores the data to the chunk
|
||||
* instead!
|
||||
*
|
||||
* <p>
|
||||
* - The data is really just on the location. If the block gets
|
||||
* broken/changed/exploded/moved etc., the data is still on that location!
|
||||
*
|
||||
* @author tr7zw
|
||||
*
|
||||
* @deprecated use methods in {@link NBT} class to read/modify block's NBT
|
||||
*/
|
||||
@Deprecated
|
||||
public class NBTBlock {
|
||||
|
||||
private final Block block;
|
||||
@@ -30,6 +31,13 @@ public class NBTBlock {
|
||||
nbtChunk = new NBTChunk(block.getChunk());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the block NBT data stored within the chunk's PDC.
|
||||
*
|
||||
* @return block NBT data
|
||||
* @deprecated use methods in {@link NBT} class to read/modify block's NBT
|
||||
*/
|
||||
@Deprecated
|
||||
public NBTCompound getData() {
|
||||
return nbtChunk.getPersistentDataContainer().getOrCreateCompound("blocks")
|
||||
.getOrCreateCompound(block.getX() + "_" + block.getY() + "_" + block.getZ());
|
||||
|
||||
@@ -5,6 +5,12 @@ import org.bukkit.Chunk;
|
||||
import de.tr7zw.changeme.nbtapi.utils.CheckUtil;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
|
||||
/**
|
||||
* Helper class to store NBT data to {@link Chunk}'s PDC (persistent data container).
|
||||
*
|
||||
* @deprecated use methods in {@link NBT} class to read/modify chunk's nbt
|
||||
*/
|
||||
@Deprecated
|
||||
public class NBTChunk {
|
||||
|
||||
private final Chunk chunk;
|
||||
|
||||
@@ -11,7 +11,11 @@ public class NBTPersistentDataContainer extends NBTCompound {
|
||||
private final PersistentDataContainer container;
|
||||
|
||||
public NBTPersistentDataContainer(PersistentDataContainer container) {
|
||||
super(null, null);
|
||||
this(container, false);
|
||||
}
|
||||
|
||||
protected NBTPersistentDataContainer(PersistentDataContainer container, boolean readOnly) {
|
||||
super(null, null, readOnly);
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
|
||||
@@ -174,6 +174,15 @@ public interface ReadableNBT {
|
||||
*/
|
||||
Set<String> getKeys();
|
||||
|
||||
/**
|
||||
* Checks whether this NBT is empty (has no stored data).
|
||||
*
|
||||
* @return whether this NBT is empty
|
||||
*/
|
||||
default boolean isEmpty() {
|
||||
return getKeys().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* @return The Compound instance or null
|
||||
@@ -274,7 +283,7 @@ public interface ReadableNBT {
|
||||
* {@code Boolean, Byte, Short, Integer, Long, Float, Double, byte[], int[], long[]},
|
||||
* {@link String}, {@link UUID}, and {@link Enum}
|
||||
*
|
||||
* @param key Path key, seperated by '.'. For example: "foo.bar.baz". Dots can
|
||||
* @param key Path key, separated by '.'. For example: "foo.bar.baz". Dots can
|
||||
* be escaped with a backslash.
|
||||
* @param type data type
|
||||
* @param <T> value type
|
||||
@@ -290,7 +299,7 @@ public interface ReadableNBT {
|
||||
* {@code Boolean, Byte, Short, Integer, Long, Float, Double, byte[], int[], long[]},
|
||||
* {@link String}, {@link UUID}, and {@link Enum}
|
||||
*
|
||||
* @param key Path key, seperated by '.'. For example: "foo.bar.baz".
|
||||
* @param key Path key, separated by '.'. For example: "foo.bar.baz".
|
||||
* Dots can be escaped with a backslash.
|
||||
* @param defaultValue default non-null value
|
||||
* @param <T> value type
|
||||
@@ -302,7 +311,7 @@ public interface ReadableNBT {
|
||||
* Returns the resolved Compound if exists, or null.
|
||||
* <p>
|
||||
*
|
||||
* @param key Path key, seperated by '.'. For example: "foo.bar.baz". Dots can
|
||||
* @param key Path key, separated by '.'. For example: "foo.bar.baz". Dots can
|
||||
* be escaped with a backslash.
|
||||
* @return The resolved value if exists, or null.
|
||||
*/
|
||||
|
||||
@@ -15,23 +15,58 @@ 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
|
||||
// https://minecraft.wiki/w/Data_version
|
||||
public static final int VERSION1_12R1 = 1343;
|
||||
public static final int VERSION1_16R1 = 2586;
|
||||
public static final int VERSION1_17R1 = 2730;
|
||||
public static final int VERSION1_18R1 = 2975;
|
||||
public static final int VERSION1_19R1 = 3120;
|
||||
public static final int VERSION1_19R3 = 3337;
|
||||
public static final int VERSION1_20R1 = 3465;
|
||||
public static final int VERSION1_20R2 = 3578;
|
||||
public static final int VERSION1_20R3 = 3700;
|
||||
public static final int VERSION1_20R4 = 3837;
|
||||
public static final int VERSION1_21R1 = 3953;
|
||||
public static final int VERSION1_21R2 = 4080;
|
||||
public static final int VERSION1_21R3 = 4189;
|
||||
public static final int VERSION1_21R4 = 4323;
|
||||
public static final int VERSION1_21R5 = 4435;
|
||||
public static final int VERSION1_21R6 = 4554;
|
||||
public static final int VERSION1_21R7 = 4671;
|
||||
public static final int VERSION_26_1 = 4786;
|
||||
public static final int VERSION_26_2 = 4903;
|
||||
public static final int VERSION_26_3 = 5023;
|
||||
// There was a mixup between version numbers and revisions, kept for compatibility, use the above revision numbers
|
||||
@Deprecated
|
||||
public static final int VERSION1_12_2 = 1343;
|
||||
@Deprecated
|
||||
public static final int VERSION1_16_5 = 2586;
|
||||
@Deprecated
|
||||
public static final int VERSION1_17_1 = 2730;
|
||||
@Deprecated
|
||||
public static final int VERSION1_18_2 = 2975;
|
||||
@Deprecated
|
||||
public static final int VERSION1_19_2 = 3120;
|
||||
@Deprecated
|
||||
public static final int VERSION1_19_4 = 3337;
|
||||
@Deprecated
|
||||
public static final int VERSION1_20_1 = 3465;
|
||||
@Deprecated
|
||||
public static final int VERSION1_20_2 = 3578;
|
||||
@Deprecated
|
||||
public static final int VERSION1_20_4 = 3700;
|
||||
@Deprecated
|
||||
public static final int VERSION1_20_5 = 3837;
|
||||
// the 1.21 versions use Revision instead of patch versions, unlike the other above. kept for compatibility
|
||||
@Deprecated
|
||||
public static final int VERSION1_21 = 3953;
|
||||
@Deprecated
|
||||
public static final int VERSION1_21_2 = 4080;
|
||||
@Deprecated
|
||||
public static final int VERSION1_21_3 = 4189;
|
||||
@Deprecated
|
||||
public static final int VERSION1_21_4 = 4323;
|
||||
@Deprecated
|
||||
public static final int VERSION1_21_5 = 4435;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -47,9 +82,16 @@ public class DataFixerUtil {
|
||||
|
||||
public static ReadWriteNBT fixUpItemData(ReadWriteNBT nbt, int fromVersion, int toVersion)
|
||||
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
|
||||
return NBT.wrapNMSTag(fixUpRawItemData(
|
||||
ReadWriteNBT tag = NBT.wrapNMSTag(fixUpRawItemData(
|
||||
NBTReflectionUtil.getToCompount(((NBTCompound) nbt).getCompound(), ((NBTCompound) nbt)), fromVersion,
|
||||
toVersion));
|
||||
tag.setInteger("DataVersion", toVersion);
|
||||
return tag;
|
||||
}
|
||||
|
||||
public static ReadWriteNBT fixUpItemData(ReadWriteNBT nbt, int fromVersion)
|
||||
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
|
||||
return fixUpItemData(nbt, fromVersion, getCurrentVersion());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,34 +104,44 @@ public class DataFixerUtil {
|
||||
* @return
|
||||
*/
|
||||
public static int getCurrentVersion() {
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R5)) {
|
||||
return VERSION1_21_5;
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC26_3)) {
|
||||
return VERSION_26_3;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC26_2)) {
|
||||
return VERSION_26_2;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC26_1)) {
|
||||
return VERSION_26_1;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R7)) {
|
||||
return VERSION1_21R7;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R6)) {
|
||||
return VERSION1_21R6;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R5)) {
|
||||
return VERSION1_21R5;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4)) {
|
||||
return VERSION1_21_4;
|
||||
return VERSION1_21R4;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R3)) {
|
||||
return VERSION1_21_3;
|
||||
return VERSION1_21R3;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R2)) {
|
||||
return VERSION1_21_2;
|
||||
return VERSION1_21R2;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R1)) {
|
||||
return VERSION1_21;
|
||||
return VERSION1_21R1;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
return VERSION1_20_5;
|
||||
return VERSION1_20R4;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R3)) {
|
||||
return VERSION1_20_4;
|
||||
return VERSION1_20R3;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R1)) {
|
||||
return VERSION1_20_1;
|
||||
return VERSION1_20R1;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_19_R3)) {
|
||||
return VERSION1_19_4;
|
||||
return VERSION1_19R3;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_19_R1)) {
|
||||
return VERSION1_19_2;
|
||||
return VERSION1_19R1;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_18_R1)) {
|
||||
return VERSION1_18_2;
|
||||
return VERSION1_18R1;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_17_R1)) {
|
||||
return VERSION1_17_1;
|
||||
return VERSION1_17R1;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R1)) {
|
||||
return VERSION1_16_5;
|
||||
return VERSION1_16R1;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_12_R1)) {
|
||||
return VERSION1_12_2;
|
||||
return VERSION1_12R1;
|
||||
}
|
||||
throw new NbtApiException(
|
||||
"Trying to update data *to* a version before 1.12.2? Something is probably going wrong, contact the plugin author.");
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
package de.tr7zw.changeme.nbtapi.utils;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.PropertyMap;
|
||||
|
||||
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.ReadableNBT;
|
||||
@@ -14,15 +18,42 @@ import de.tr7zw.changeme.nbtapi.iface.ReadableNBTList;
|
||||
|
||||
public class GameprofileUtil {
|
||||
|
||||
private static Method GET_NAME = null;
|
||||
private static Method GET_ID = null;
|
||||
private static Method GET_VALUE = null;
|
||||
private static Method GET_SIGNATURE = null;
|
||||
private static Method GET_PROPERTY_NAME = null;
|
||||
private static Method GET_PROPERTIES = null;
|
||||
|
||||
static {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R6)) {
|
||||
try {
|
||||
GET_NAME = GameProfile.class.getDeclaredMethod("name");
|
||||
GET_ID = GameProfile.class.getDeclaredMethod("id");
|
||||
GET_VALUE = com.mojang.authlib.properties.Property.class.getDeclaredMethod("value");
|
||||
GET_SIGNATURE = com.mojang.authlib.properties.Property.class.getDeclaredMethod("signature");
|
||||
GET_PROPERTY_NAME = com.mojang.authlib.properties.Property.class.getDeclaredMethod("name");
|
||||
GET_PROPERTIES = GameProfile.class.getDeclaredMethod("properties");
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static GameProfile readGameProfile(ReadableNBT arg) {
|
||||
String string = null;
|
||||
UUID uUID = null;
|
||||
if (arg.hasTag("Name") && arg.getType("Name") == NBTType.NBTTagString) {
|
||||
string = arg.getString("Name");
|
||||
} else if (arg.hasTag("name") && arg.getType("name") == NBTType.NBTTagString) {
|
||||
string = arg.getString("name");
|
||||
}
|
||||
if (arg.hasTag("Id") && arg.getType("Id") == NBTType.NBTTagIntArray && arg.getIntArray("Id").length == 4) {
|
||||
uUID = arg.getUUID("Id");
|
||||
} else if (arg.hasTag("id") && arg.getType("id") == NBTType.NBTTagIntArray
|
||||
&& arg.getIntArray("id").length == 4) {
|
||||
uUID = arg.getUUID("id");
|
||||
}
|
||||
try {
|
||||
GameProfile gameProfile = new GameProfile(uUID, string);
|
||||
@@ -43,6 +74,21 @@ public class GameprofileUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (arg.getType("properties") == NBTType.NBTTagList) { // 1.20.5+
|
||||
ReadableNBTList<ReadWriteNBT> listTag = arg.getCompoundList("properties");
|
||||
for (int i = 0; i < listTag.size(); ++i) {
|
||||
ReadableNBT compoundTag2 = listTag.get(i);
|
||||
String string2 = compoundTag2.getString("name");
|
||||
String string3 = compoundTag2.getString("value");
|
||||
if (compoundTag2.hasTag("signature")
|
||||
&& compoundTag2.getType("signature") == NBTType.NBTTagString) {
|
||||
gameProfile.getProperties().put(string2, new com.mojang.authlib.properties.Property(string2,
|
||||
string3, compoundTag2.getString("signature")));
|
||||
} else {
|
||||
gameProfile.getProperties().put(string2,
|
||||
new com.mojang.authlib.properties.Property(string2, string3));
|
||||
}
|
||||
}
|
||||
}
|
||||
return gameProfile;
|
||||
} catch (Throwable var11) {
|
||||
@@ -51,26 +97,115 @@ public class GameprofileUtil {
|
||||
}
|
||||
|
||||
public static ReadWriteNBT writeGameProfile(ReadWriteNBT arg, GameProfile gameProfile) {
|
||||
if (!(gameProfile.getName() == null || gameProfile.getName().isEmpty())) {
|
||||
arg.setString("Name", gameProfile.getName());
|
||||
String name = getName(gameProfile);
|
||||
if (!(name == null || name.isEmpty())) {
|
||||
String nameKey = MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4) ? "name" : "Name";
|
||||
arg.setString(nameKey, getName(gameProfile));
|
||||
}
|
||||
if (gameProfile.getId() != null) {
|
||||
arg.setUUID("Id", gameProfile.getId());
|
||||
UUID id = getId(gameProfile);
|
||||
if (id != null) {
|
||||
String idKey = MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4) ? "id" : "Id";
|
||||
arg.setUUID(idKey, id);
|
||||
}
|
||||
if (!gameProfile.getProperties().isEmpty()) {
|
||||
ReadWriteNBT compoundTag = arg.getOrCreateCompound("Properties");
|
||||
for (String string : gameProfile.getProperties().keySet()) {
|
||||
ReadWriteNBTCompoundList list = compoundTag.getCompoundList(string);
|
||||
for (com.mojang.authlib.properties.Property property : gameProfile.getProperties().get(string)) {
|
||||
ReadWriteNBT tag = list.addCompound();
|
||||
tag.setString("Value", property.getValue());
|
||||
if (property.hasSignature()) {
|
||||
tag.setString("Signature", property.getSignature());
|
||||
PropertyMap properties = getProperties(gameProfile);
|
||||
if (!properties.isEmpty()) {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
ReadWriteNBTCompoundList list = arg.getCompoundList("properties");
|
||||
for (com.mojang.authlib.properties.Property property : properties.values()) {
|
||||
ReadWriteNBT tag = list.addCompound();
|
||||
tag.setString("name", getPropertyName(property));
|
||||
tag.setString("value", getValue(property));
|
||||
if (property.hasSignature()) {
|
||||
tag.setString("signature", getSignature(property));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ReadWriteNBT compoundTag = arg.getOrCreateCompound("Properties");
|
||||
for (String string : gameProfile.getProperties().keySet()) {
|
||||
ReadWriteNBTCompoundList list = compoundTag.getCompoundList(string);
|
||||
for (com.mojang.authlib.properties.Property property : properties.get(string)) {
|
||||
ReadWriteNBT tag = list.addCompound();
|
||||
tag.setString("Value", getValue(property));
|
||||
if (property.hasSignature()) {
|
||||
tag.setString("Signature", getSignature(property));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
private static String getName(GameProfile profile) {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R6)) {
|
||||
try {
|
||||
return GET_NAME.invoke(profile).toString();
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
throw new NbtApiException("Failed to get GameProfile name via reflection", e);
|
||||
}
|
||||
} else {
|
||||
return profile.getName();
|
||||
}
|
||||
}
|
||||
|
||||
private static UUID getId(GameProfile profile) {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R6)) {
|
||||
try {
|
||||
return (UUID) GET_ID.invoke(profile);
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
throw new NbtApiException("Failed to get GameProfile id via reflection", e);
|
||||
}
|
||||
} else {
|
||||
return profile.getId();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getValue(com.mojang.authlib.properties.Property property) {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R6)) {
|
||||
try {
|
||||
return GET_VALUE.invoke(property).toString();
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
throw new NbtApiException("Failed to get Property value via reflection", e);
|
||||
}
|
||||
} else {
|
||||
return property.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getSignature(com.mojang.authlib.properties.Property property) {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R6)) {
|
||||
try {
|
||||
return GET_SIGNATURE.invoke(property).toString();
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
throw new NbtApiException("Failed to get Property signature via reflection", e);
|
||||
}
|
||||
} else {
|
||||
return property.getSignature();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getPropertyName(com.mojang.authlib.properties.Property property) {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R6)) {
|
||||
try {
|
||||
return GET_PROPERTY_NAME.invoke(property).toString();
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
throw new NbtApiException("Failed to get Property name via reflection", e);
|
||||
}
|
||||
} else {
|
||||
return property.getName();
|
||||
}
|
||||
}
|
||||
|
||||
private static PropertyMap getProperties(GameProfile profile) {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R6)) {
|
||||
try {
|
||||
return (PropertyMap) GET_PROPERTIES.invoke(profile);
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
throw new NbtApiException("Failed to get GameProfile properties via reflection", e);
|
||||
}
|
||||
} else {
|
||||
return profile.getProperties();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package de.tr7zw.changeme.nbtapi.utils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -31,7 +32,8 @@ public enum MinecraftVersion {
|
||||
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_21_R2(1212, true), MC1_21_R3(1213, true), MC1_21_R4(1214, true),
|
||||
MC1_21_R5(1215, true);
|
||||
MC1_21_R5(1215, true), MC1_21_R6(1216, true), MC1_21_R7(1217, true), MC26_1(260100, true), MC26_2(260200, true),
|
||||
MC26_3(260300, true);
|
||||
|
||||
private static MinecraftVersion version;
|
||||
private static Boolean hasGsonSupport;
|
||||
@@ -48,13 +50,12 @@ public enum MinecraftVersion {
|
||||
private static Logger logger = Logger.getLogger("NBTAPI");
|
||||
|
||||
// NBT-API Version
|
||||
protected static final String VERSION = "2.15.1";
|
||||
protected static final String VERSION = "2.16.1";
|
||||
|
||||
private final int versionId;
|
||||
private final boolean mojangMapping;
|
||||
|
||||
// TODO: not nice
|
||||
@SuppressWarnings("serial")
|
||||
private static final Map<String, MinecraftVersion> VERSION_TO_REVISION = new HashMap<String, MinecraftVersion>() {
|
||||
{
|
||||
this.put("1.20", MC1_20_R1);
|
||||
@@ -72,6 +73,13 @@ public enum MinecraftVersion {
|
||||
this.put("1.21.5", MC1_21_R4);
|
||||
this.put("1.21.6", MC1_21_R5);
|
||||
this.put("1.21.7", MC1_21_R5);
|
||||
this.put("1.21.8", MC1_21_R5);
|
||||
this.put("1.21.9", MC1_21_R6);
|
||||
this.put("1.21.10", MC1_21_R6);
|
||||
this.put("1.21.11", MC1_21_R7);
|
||||
this.put("26.1", MC26_1);
|
||||
this.put("26.2", MC26_2);
|
||||
this.put("26.3", MC26_3);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -153,8 +161,22 @@ public enum MinecraftVersion {
|
||||
} catch (Exception ex) {
|
||||
logger.info("[NBTAPI] Found Minecraft: " + Bukkit.getServer().getBukkitVersion().split("-")[0]
|
||||
+ "! Trying to find NMS support");
|
||||
version = VERSION_TO_REVISION.getOrDefault(Bukkit.getServer().getBukkitVersion().split("-")[0],
|
||||
MinecraftVersion.UNKNOWN);
|
||||
version = VERSION_TO_REVISION.get(Bukkit.getServer().getBukkitVersion().split("-")[0]);
|
||||
if (version == null) {
|
||||
// check for modern versions with the new versioning scheme, also the new paper version format
|
||||
String versionString = Bukkit.getServer().getBukkitVersion().split("-")[0].split(".build")[0];
|
||||
for (Entry<String, MinecraftVersion> entry : VERSION_TO_REVISION.entrySet()) {
|
||||
if (versionString.startsWith(entry.getKey()) && version == null) {
|
||||
version = entry.getValue();
|
||||
// pick the highest revision that matches the version string, in case 26.1.3 is somehow different to 26.1
|
||||
} else if (versionString.startsWith(entry.getKey()) && entry.getValue().getVersionId() > version.getVersionId()) {
|
||||
version = entry.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (version == null) {
|
||||
version = UNKNOWN;
|
||||
}
|
||||
}
|
||||
if (version != UNKNOWN) {
|
||||
logger.info("[NBTAPI] NMS support '" + version.name() + "' loaded!");
|
||||
|
||||
+2
-2
@@ -56,8 +56,8 @@ public class Forge1710Mappings {
|
||||
methodMap.put("COMPOUND_MERGE", "merge");// Only present on Crucible
|
||||
methodMap.put("COMPOUND_SET", "func_74782_a");
|
||||
methodMap.put("COMPOUND_GET", "func_74781_a");
|
||||
methodMap.put("COMPOUND_GET_LIST", "func_150295_c");
|
||||
methodMap.put("COMPOUND_OWN_TYPE", "func_74732_a");
|
||||
methodMap.put("COMPOUND_GET_LIST_LEGACY", "func_150295_c");
|
||||
methodMap.put("COMPOUND_OWN_TYPE_LEGACY", "func_74732_a");
|
||||
methodMap.put("COMPOUND_GET_FLOAT", "func_74760_g");
|
||||
methodMap.put("COMPOUND_GET_STRING", "func_74779_i");
|
||||
methodMap.put("COMPOUND_GET_INT", "func_74762_e");
|
||||
|
||||
+43
-1
@@ -1,5 +1,6 @@
|
||||
package de.tr7zw.changeme.nbtapi.utils.nmsmappings;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -238,6 +239,7 @@ public class MojangToMapping {
|
||||
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");
|
||||
put("net.minecraft.world.item.ItemStack#CODEC", "b");
|
||||
}
|
||||
|
||||
};
|
||||
@@ -283,9 +285,49 @@ public class MojangToMapping {
|
||||
|
||||
};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static Map<String, String> MC1_21R6 = new HashMap<String, String>() {
|
||||
|
||||
{
|
||||
putAll(MC1_21R5);
|
||||
|
||||
put("net.minecraft.server.MinecraftServer#registryAccess()", "bg");
|
||||
put("net.minecraft.world.entity.Entity#load(net.minecraft.world.level.storage.ValueInput)", "d");
|
||||
put("net.minecraft.world.entity.Entity#getEncodeId()", "bW");
|
||||
put("net.minecraft.world.item.component.CustomData#copyTag()", "b");
|
||||
put("net.minecraft.world.level.block.entity.BlockEntity#getBlockState()", "o");
|
||||
put("net.minecraft.util.datafix.fixes.References#ITEM_STACK", "v");
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static Map<String, String> MC1_21R7 = new HashMap<String, String>() {
|
||||
|
||||
{
|
||||
putAll(MC1_21R6);
|
||||
|
||||
put("net.minecraft.nbt.NbtAccounter#unlimitedHeap()", "c");
|
||||
put("net.minecraft.server.MinecraftServer#registryAccess()", "bc");
|
||||
put("net.minecraft.world.entity.Entity#getEncodeId()", "ca");
|
||||
put("net.minecraft.util.datafix.fixes.References#ITEM_STACK", "x");
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
public static Map<String, String> getMapping() {
|
||||
// No mappings after 26.1
|
||||
if(MinecraftVersion.getVersion() != MinecraftVersion.UNKNOWN && MinecraftVersion.getVersion().isAtLeastVersion(MinecraftVersion.MC26_1)) {
|
||||
return Collections.EMPTY_MAP;
|
||||
}
|
||||
switch (MinecraftVersion.getVersion()) {
|
||||
case MC1_21_R7:
|
||||
return MC1_21R7;
|
||||
case MC1_21_R6:
|
||||
return MC1_21R6;
|
||||
case MC1_21_R5:
|
||||
return MC1_21R5;
|
||||
case MC1_21_R4:
|
||||
@@ -315,7 +357,7 @@ public class MojangToMapping {
|
||||
case MC1_18_R1:
|
||||
return MC1_18R1;
|
||||
case UNKNOWN:
|
||||
return MC1_20R2; // assume it's a future version, so try the latest known mappings
|
||||
return MC1_21R7; // assume it's a future version, so try the latest known mappings
|
||||
default:
|
||||
// this should never happen, unless a version is forgotten here(like 1.19R3 which uses the 1.19R2 mappings)
|
||||
throw new NbtApiException("No fitting mapping found for version " + MinecraftVersion.getVersion() + ". This is a bug!");
|
||||
|
||||
+12
-1
@@ -175,7 +175,8 @@ public enum ReflectionMethod {
|
||||
ITEMSTACK_NMSCOPY(ClassWrapper.CRAFT_ITEMSTACK, new Class[] { ItemStack.class }, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "asNMSCopy")),
|
||||
ITEMSTACK_BUKKITMIRROR(ClassWrapper.CRAFT_ITEMSTACK, new Class[] { ClassWrapper.NMS_ITEMSTACK.getClazz() },
|
||||
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "asCraftMirror")),
|
||||
MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, resolveItemStackBukkitMirrorMethodName())),
|
||||
|
||||
CRAFT_WORLD_GET_HANDLE(ClassWrapper.CRAFT_WORLD, new Class[] {}, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "getHandle")),
|
||||
@@ -413,6 +414,16 @@ public enum ReflectionMethod {
|
||||
this(targetClass, args, addedSince, null, methodnames);
|
||||
}
|
||||
|
||||
private static String resolveItemStackBukkitMirrorMethodName() {
|
||||
try {
|
||||
ClassWrapper.CRAFT_ITEMSTACK.getClazz().getDeclaredMethod("asCraftMirror",
|
||||
ClassWrapper.NMS_ITEMSTACK.getClazz());
|
||||
return "asCraftMirror";
|
||||
} catch (NullPointerException | NoSuchMethodException | SecurityException ignored) {
|
||||
return "asBukkitMirror";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the method on a given target object using the given args.
|
||||
*
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>item-nbt-parent</artifactId>
|
||||
<version>2.15.1</version>
|
||||
<version>2.16.1</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.15.1</version>
|
||||
<version>2.16.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -24,7 +24,7 @@
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.2.1</version>
|
||||
<!-- Overwrite to provided -->
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
@@ -40,7 +40,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<version>3.6.2</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>true</createDependencyReducedPom>
|
||||
<relocations>
|
||||
|
||||
@@ -15,9 +15,8 @@ public class GameprofileTest implements Test {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
GameProfile profile = new GameProfile(uuid, "random");
|
||||
ReadWriteNBT nbt = NBT.gameProfileToNBT(profile);
|
||||
profile = null;
|
||||
profile = NBT.gameProfileFromNBT(nbt);
|
||||
if (profile == null || !profile.getId().equals(uuid)) {
|
||||
GameProfile profile2 = NBT.gameProfileFromNBT(nbt);
|
||||
if (profile == null || !profile.equals(profile2)) {
|
||||
throw new NbtApiException("Error when converting a GameProfile from/to NBT!");
|
||||
}
|
||||
}
|
||||
|
||||
+56
-19
@@ -1,40 +1,77 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.blocks;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTType;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadableNBT;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTBlock;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BlockNBTTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
if (MinecraftVersion.getVersion().getVersionId() < MinecraftVersion.MC1_16_R3.getVersionId())
|
||||
return;
|
||||
if (!Bukkit.getWorlds().isEmpty()) {
|
||||
World world = Bukkit.getWorlds().get(0);
|
||||
try {
|
||||
if (world.getLoadedChunks().length > 1) {
|
||||
Chunk chunk = world.getLoadedChunks()[0];
|
||||
Block block = chunk.getBlock(0, 254, 0);
|
||||
NBTBlock comp = new NBTBlock(block);
|
||||
comp.getData().removeKey("Too");
|
||||
if (comp.getData().hasTag("Too")) {
|
||||
throw new NbtApiException("Unable to remove key from Block!");
|
||||
}
|
||||
comp.getData().setString("Too", "Bar");
|
||||
if (!new NBTBlock(block).getData().getString("Too").equals("Bar")) {
|
||||
throw new NbtApiException("Custom Data did not save to a Block!");
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new NbtApiException("Wasn't able to use NBTBlocks!", ex);
|
||||
|
||||
List<World> loadedWorlds = Bukkit.getWorlds();
|
||||
if (loadedWorlds.isEmpty())
|
||||
return;
|
||||
|
||||
World world = loadedWorlds.get(0);
|
||||
Chunk[] loadedChunks = world.getLoadedChunks();
|
||||
if (loadedChunks.length == 0)
|
||||
return;
|
||||
|
||||
try {
|
||||
Chunk chunk = loadedChunks[0];
|
||||
Block block = chunk.getBlock(0, 254, 0);
|
||||
String blockKey = block.getX() + "_" + block.getY() + "_" + block.getZ();
|
||||
|
||||
NBT.modifyChunkPDC(block, nbt -> nbt.setString("Too", "Bar"));
|
||||
boolean storedDataPresent = NBT.readAndGetChunkPDC(chunk, nbt -> {
|
||||
if (!nbt.hasTag("blocks", NBTType.NBTTagCompound)) return false;
|
||||
|
||||
ReadableNBT blocksNbt = nbt.getCompound("blocks");
|
||||
if (blocksNbt == null || !blocksNbt.hasTag(blockKey, NBTType.NBTTagCompound)) return false;
|
||||
|
||||
ReadableNBT blockNbt = blocksNbt.getCompound(blockKey);
|
||||
return blockNbt != null && blockNbt.hasTag("Too", NBTType.NBTTagString) && "Bar".equals(blockNbt.getString("Too"));
|
||||
});
|
||||
if (!storedDataPresent) {
|
||||
throw new NbtApiException("Custom Data did not save to a Block!");
|
||||
}
|
||||
if (!NBT.readAndGetChunkPDC(block, nbt -> nbt.hasTag("Too"))) {
|
||||
throw new NbtApiException("Custom Data did not save to a Block!");
|
||||
}
|
||||
|
||||
boolean blockHadOnlyTestKey = NBT.readAndGetChunkPDC(block, nbt -> nbt.getKeys().size() == 1);
|
||||
boolean chunkHadOnlyOneBlock = NBT.readAndGetChunkPDC(chunk, nbt -> nbt.getCompound("blocks").getKeys().size() == 1);
|
||||
|
||||
NBT.modifyChunkPDC(block, nbt -> nbt.removeKey("Too"));
|
||||
|
||||
if (NBT.readAndGetChunkPDC(block, nbt -> nbt.hasTag("Too"))) {
|
||||
throw new NbtApiException("Unable to remove key from Block!");
|
||||
}
|
||||
|
||||
if (chunkHadOnlyOneBlock) {
|
||||
if (NBT.readAndGetChunkPDC(chunk, nbt -> nbt.hasTag("blocks"))) {
|
||||
throw new NbtApiException("Chunk data wasn't cleaned up (hanging \"blocks\" compound)!");
|
||||
}
|
||||
} else if (blockHadOnlyTestKey) {
|
||||
if (NBT.readAndGetChunkPDC(chunk, nbt -> nbt.getCompound("blocks").hasTag(blockKey))) {
|
||||
throw new NbtApiException("Chunk data wasn't cleaned up (hanging block location compound)!");
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new NbtApiException("Wasn't able to use NBTBlocks!", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+26
-20
@@ -1,40 +1,46 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.chunks;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTType;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTChunk;
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ChunkNBTPersistentTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
if (MinecraftVersion.getVersion().getVersionId() < MinecraftVersion.MC1_16_R3.getVersionId())
|
||||
return;
|
||||
if (!Bukkit.getWorlds().isEmpty()) {
|
||||
World world = Bukkit.getWorlds().get(0);
|
||||
try {
|
||||
if (world.getLoadedChunks().length > 1) {
|
||||
Chunk chunk = world.getLoadedChunks()[0];
|
||||
NBTChunk comp = new NBTChunk(chunk);
|
||||
NBTCompound persistentData = comp.getPersistentDataContainer();
|
||||
persistentData.removeKey("Foo");
|
||||
if (persistentData.hasTag("Foo")) {
|
||||
throw new NbtApiException("Unable to remove key from Chunk!");
|
||||
}
|
||||
persistentData.setString("Foo", "Bar");
|
||||
if (!new NBTChunk(chunk).getPersistentDataContainer().getString("Foo").equals("Bar")) {
|
||||
throw new NbtApiException("Custom Data did not save to the Chunk!");
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new NbtApiException("Wasn't able to use NBTChunks!", ex);
|
||||
|
||||
List<World> loadedWorlds = Bukkit.getWorlds();
|
||||
if (loadedWorlds.isEmpty())
|
||||
return;
|
||||
|
||||
World world = loadedWorlds.get(0);
|
||||
Chunk[] loadedChunks = world.getLoadedChunks();
|
||||
if (loadedChunks.length == 0)
|
||||
return;
|
||||
|
||||
Chunk chunk = loadedChunks[0];
|
||||
try {
|
||||
NBT.modifyChunkPDC(chunk, nbt -> nbt.setString("Foo", "Bar"));
|
||||
if (!NBT.readAndGetChunkPDC(chunk, nbt -> nbt.hasTag("Foo", NBTType.NBTTagString) && "Bar".equals(nbt.getString("Foo")))) {
|
||||
throw new NbtApiException("Custom Data did not save to the Chunk!");
|
||||
}
|
||||
|
||||
NBT.modifyChunkPDC(chunk, nbt -> nbt.removeKey("Foo"));
|
||||
if (NBT.readAndGetChunkPDC(chunk, nbt -> nbt.hasTag("Foo"))) {
|
||||
throw new NbtApiException("Unable to remove key from Chunk!");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new NbtApiException("Wasn't able to use NBTChunks!", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,11 @@ public class LegacyItemTest implements Test {
|
||||
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);
|
||||
|
||||
ReadWriteNBT testNBT = NBT.parseNBT("{id:cobblestone,Count:42,tag:{display:{Name:\"test\"},ench:[{lvl:3,id:34}]},DataVersion:1343}");
|
||||
testNBT = DataFixerUtil.fixUpItemData(testNBT, DataFixerUtil.VERSION1_12R1);
|
||||
if (testNBT.getInteger("DataVersion") != DataFixerUtil.getCurrentVersion())
|
||||
throw new NbtApiException("DataVersion wasn't updated correctly! " + testNBT);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>item-nbt-parent</artifactId>
|
||||
<version>2.15.1</version>
|
||||
<version>2.16.1</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.15.1</version>
|
||||
<version>2.16.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -24,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.6.txt");
|
||||
File input = new File("minecraft_server.1.21.9.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.15.1</version>
|
||||
<version>2.16.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>nbt-data-api</artifactId>
|
||||
@@ -14,7 +14,7 @@
|
||||
<dependency>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>item-nbt-api</artifactId>
|
||||
<version>2.15.1</version>
|
||||
<version>2.16.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>item-nbt-parent</artifactId>
|
||||
<version>2.15.1</version>
|
||||
<version>2.16.1</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.15.1</version>
|
||||
<version>2.16.1</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.15.1</version>
|
||||
<version>2.16.1</version>
|
||||
<packaging>pom</packaging>
|
||||
<inceptionYear>2015</inceptionYear>
|
||||
<organization>
|
||||
@@ -88,7 +88,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.14.0</version>
|
||||
<version>3.16.0</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
@@ -97,7 +97,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
<version>3.4.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
@@ -110,7 +110,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.11.2</version>
|
||||
<version>3.12.0</version>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
</configuration>
|
||||
@@ -139,7 +139,7 @@
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>license-maven-plugin</artifactId>
|
||||
<version>2.6.0</version>
|
||||
<version>2.7.1</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.15.1</version>
|
||||
<version>2.16.1</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.15.1</version>
|
||||
<version>2.16.1</version>
|
||||
</dependency>
|
||||
...
|
||||
<plugins>
|
||||
|
||||
@@ -306,20 +306,26 @@ You can store data in block entities (block entities like chest, furnace, etc.)
|
||||
|
||||
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``:
|
||||
You can store data inside Chunks using their PDC (Persistent Data Container) since Minecraft **1.16.4**. The NBT‑API provides read and modify methods in the `NBT` class to interact with it:
|
||||
|
||||
```java
|
||||
ReadWriteNBT nbt = new NBTChunk(chunk).getPersistentDataContainer();
|
||||
// Read the entire PDC or a specific value
|
||||
NBT.readChunkPDC(chunk, nbt -> { /* ... */ });
|
||||
String str = NBT.readAndGetChunkPDC(chunk, nbt -> nbt.getOrNull("key", String.class));
|
||||
```
|
||||
|
||||
Similarly, there is ``NBTBlock``, which allows you to store block data inside chunk's data.
|
||||
For convenience, you can also pass Blocks into `NBT#read/modify[AndGet]ChunkPDC` methods to store block data inside Chunk's PDC.
|
||||
Blocks are stored inside their chunk's PDC under a `blocks` compound, using the block's location (`X_Y_Z`) as the key for a subcompound.
|
||||
|
||||
```java
|
||||
// Block's data will be stored in Chunk's data in "blocks.x_y_z" subtag
|
||||
ReadWriteNBT nbt = new NBTBlock(block).getData();
|
||||
// Modify and retrieve data for a specific block
|
||||
boolean bool = NBT.modifyAndGetChunkPDC(block, nbt -> {
|
||||
nbt.setString("owner_name", "Player123");
|
||||
return nbt.getOrDefault("key", false);
|
||||
});
|
||||
```
|
||||
|
||||
**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!
|
||||
**However**, keep in mind that the block's 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.
|
||||
|
||||
|
||||
Reference in new issue
Block a user