diff --git a/buildSrc/src/main/kotlin/LibsConfig.kt b/buildSrc/src/main/kotlin/LibsConfig.kt index 29c5bfa3a8..959b39f9cd 100644 --- a/buildSrc/src/main/kotlin/LibsConfig.kt +++ b/buildSrc/src/main/kotlin/LibsConfig.kt @@ -28,7 +28,8 @@ fun Project.applyLibrariesConfiguration() { val relocations = mapOf( "net.kyori.text" to "com.sk89q.worldedit.util.formatting.text", - "net.kyori.minecraft" to "com.sk89q.worldedit.util.kyori" + "net.kyori.minecraft" to "com.sk89q.worldedit.util.kyori", + "net.kyori.adventure.nbt" to "com.sk89q.worldedit.util.nbt" ) tasks.register("jar") { diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java index a5f5d615a9..95dd3216ff 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java @@ -39,6 +39,7 @@ import com.sk89q.worldedit.util.formatting.text.adapter.bukkit.TextAdapter; import com.sk89q.worldedit.util.formatting.text.event.ClickEvent; import com.sk89q.worldedit.util.formatting.text.format.TextColor; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockStateHolder; @@ -295,11 +296,12 @@ public > void sendFakeBlock(BlockVector3 pos, B bl player.sendBlockChange(loc, player.getWorld().getBlockAt(loc).getBlockData()); } else { player.sendBlockChange(loc, BukkitAdapter.adapt(block)); - if (block instanceof BaseBlock && ((BaseBlock) block).hasNbtData()) { - BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); - if (adapter != null) { - if (block.getBlockType() == BlockTypes.STRUCTURE_BLOCK) { - adapter.sendFakeNBT(player, pos, ((BaseBlock) block).getNbtData()); + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + if (adapter != null) { + if (block.getBlockType() == BlockTypes.STRUCTURE_BLOCK && block instanceof BaseBlock) { + CompoundBinaryTag nbt = ((BaseBlock) block).getNbt(); + if (nbt != null) { + adapter.sendFakeNBT(player, pos, nbt); adapter.sendFakeOP(player); } } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index 4d6edd2616..720ff750b1 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -149,8 +149,8 @@ public com.sk89q.worldedit.entity.Entity createEntity(com.sk89q.worldedit.util.L } } catch (Exception e) { logger.warn("Corrupt entity found when creating: " + entity.getType().getId()); - if (entity.getNbtData() != null) { - logger.warn(entity.getNbtData().toString()); + if (entity.getNbt() != null) { + logger.warn(entity.getNbt().toString()); } e.printStackTrace(); return null; @@ -457,9 +457,9 @@ public > boolean setBlock(BlockVector3 position, B try { return worldNativeAccess.setBlock(position, block, sideEffects); } catch (Exception e) { - if (block instanceof BaseBlock && ((BaseBlock) block).getNbtData() != null) { + if (block instanceof BaseBlock && ((BaseBlock) block).getNbt() != null) { logger.warn("Tried to set a corrupt tile entity at " + position.toString() - + ": " + ((BaseBlock) block).getNbtData(), e); + + ": " + ((BaseBlock) block).getNbt(), e); } else { logger.warn("Failed to set block via adapter, falling back to generic", e); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java index f3d46ebb22..c9e0743d31 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.bukkit.adapter; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.entity.BaseEntity; @@ -31,6 +30,7 @@ import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.RegenOptions; import com.sk89q.worldedit.world.block.BaseBlock; @@ -151,7 +151,7 @@ default void tickWatchdog() { * @param pos The position * @param nbtData The NBT Data */ - void sendFakeNBT(Player player, BlockVector3 pos, CompoundTag nbtData); + void sendFakeNBT(Player player, BlockVector3 pos, CompoundBinaryTag nbtData); /** * Make the client think it has operator status. diff --git a/worldedit-bukkit/src/main/resources/worldedit-adapters.jar b/worldedit-bukkit/src/main/resources/worldedit-adapters.jar index 31237d7c46..5f9fa5a89b 100644 Binary files a/worldedit-bukkit/src/main/resources/worldedit-adapters.jar and b/worldedit-bukkit/src/main/resources/worldedit-adapters.jar differ diff --git a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java index a43ef366d5..eadad40842 100644 --- a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java +++ b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java @@ -37,7 +37,11 @@ /** * A mob spawner block. + * + * @deprecated WorldEdit does not handle interpreting NBT, + * deprecated for removal without replacement */ +@Deprecated public class MobSpawnerBlock extends BaseBlock { private String mobType; diff --git a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SignBlock.java b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SignBlock.java index db8c4b2be9..070df964ff 100644 --- a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SignBlock.java +++ b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SignBlock.java @@ -31,7 +31,11 @@ /** * Represents a sign block. + * + * @deprecated WorldEdit does not handle interpreting NBT, + * deprecated for removal without replacement */ +@Deprecated public class SignBlock extends BaseBlock { private String[] text; diff --git a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SkullBlock.java b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SkullBlock.java index e754fb4536..88d0fe593a 100644 --- a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SkullBlock.java +++ b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SkullBlock.java @@ -31,7 +31,11 @@ /** * A skull block. + * + * @deprecated WorldEdit does not handle interpreting NBT, + * deprecated for removal without replacement */ +@Deprecated public class SkullBlock extends BaseBlock { private String owner = ""; // notchian diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/AdventureNBTConverter.java b/worldedit-core/src/main/java/com/sk89q/jnbt/AdventureNBTConverter.java new file mode 100644 index 0000000000..13c58e6931 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/AdventureNBTConverter.java @@ -0,0 +1,105 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.jnbt; + +import com.google.common.collect.BiMap; +import com.google.common.collect.ImmutableBiMap; +import com.google.common.collect.ImmutableMap; +import com.sk89q.worldedit.util.nbt.BinaryTag; +import com.sk89q.worldedit.util.nbt.BinaryTagType; +import com.sk89q.worldedit.util.nbt.BinaryTagTypes; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; + +/** + * Converts between JNBT and Adventure-NBT classes. + * + * @deprecated JNBT is being removed in WE8. + */ +@Deprecated +public class AdventureNBTConverter { + private static final BiMap, BinaryTagType> TAG_TYPES = + new ImmutableBiMap.Builder, BinaryTagType>() + .put(ByteArrayTag.class, BinaryTagTypes.BYTE_ARRAY) + .put(ByteTag.class, BinaryTagTypes.BYTE) + .put(CompoundTag.class, BinaryTagTypes.COMPOUND) + .put(DoubleTag.class, BinaryTagTypes.DOUBLE) + .put(EndTag.class, BinaryTagTypes.END) + .put(FloatTag.class, BinaryTagTypes.FLOAT) + .put(IntArrayTag.class, BinaryTagTypes.INT_ARRAY) + .put(IntTag.class, BinaryTagTypes.INT) + .put(ListTag.class, BinaryTagTypes.LIST) + .put(LongArrayTag.class, BinaryTagTypes.LONG_ARRAY) + .put(LongTag.class, BinaryTagTypes.LONG) + .put(ShortTag.class, BinaryTagTypes.SHORT) + .put(StringTag.class, BinaryTagTypes.STRING) + .build(); + + private static final Map, Function> CONVERSION; + + static { + ImmutableMap.Builder, Function> conversion = + ImmutableMap.builder(); + + for (Map.Entry, BinaryTagType> tag : TAG_TYPES.entrySet()) { + Constructor[] constructors = tag.getKey().getConstructors(); + for (Constructor c : constructors) { + if (c.getParameterCount() == 1 && BinaryTag.class.isAssignableFrom(c.getParameterTypes()[0])) { + conversion.put(tag.getValue(), binaryTag -> { + try { + return (Tag) c.newInstance(binaryTag); + } catch (InstantiationException | IllegalAccessException e) { + throw new IllegalStateException(e); + } catch (InvocationTargetException e) { + // I assume this is always a RuntimeException since we control the ctor + throw (RuntimeException) e.getCause(); + } + }); + break; + } + } + } + + CONVERSION = conversion.build(); + } + + public static BinaryTagType getAdventureType(Class type) { + return Objects.requireNonNull(TAG_TYPES.get(type), () -> "Missing entry for " + type); + } + + public static Class getJNBTType(BinaryTagType type) { + return Objects.requireNonNull(TAG_TYPES.inverse().get(type), () -> "Missing entry for " + type); + } + + private AdventureNBTConverter() { + } + + public static Tag fromAdventure(BinaryTag other) { + Function conversion = CONVERSION.get(other.type()); + if (conversion == null) { + throw new IllegalArgumentException("Can't convert other of type " + other.getClass().getCanonicalName()); + } + return conversion.apply(other); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/ByteArrayTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/ByteArrayTag.java index 78a9d7521b..279e7a71a7 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/ByteArrayTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/ByteArrayTag.java @@ -19,14 +19,19 @@ package com.sk89q.jnbt; +import com.sk89q.worldedit.util.nbt.ByteArrayBinaryTag; + import java.util.Locale; /** * The {@code TAG_Byte_Array} tag. + * + * @deprecated Use {@link ByteArrayBinaryTag}. */ +@Deprecated public final class ByteArrayTag extends Tag { - private final byte[] value; + private final ByteArrayBinaryTag innerTag; /** * Creates the tag with an empty name. @@ -35,25 +40,21 @@ public final class ByteArrayTag extends Tag { */ public ByteArrayTag(byte[] value) { super(); - this.value = value; + this.innerTag = ByteArrayBinaryTag.of(value); + } + + public ByteArrayTag(ByteArrayBinaryTag adventureTag) { + super(); + this.innerTag = adventureTag; } @Override public byte[] getValue() { - return value; + return innerTag.value(); } @Override - public String toString() { - StringBuilder hex = new StringBuilder(); - for (byte b : value) { - String hexDigits = Integer.toHexString(b).toUpperCase(Locale.ROOT); - if (hexDigits.length() == 1) { - hex.append("0"); - } - hex.append(hexDigits).append(" "); - } - return "TAG_Byte_Array(" + hex + ")"; + public ByteArrayBinaryTag asBinaryTag() { + return innerTag; } - } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/ByteTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/ByteTag.java index e7fe1cc407..2a804a1f24 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/ByteTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/ByteTag.java @@ -19,12 +19,17 @@ package com.sk89q.jnbt; +import com.sk89q.worldedit.util.nbt.ByteBinaryTag; + /** * The {@code TAG_Byte} tag. + * + * @deprecated Use {@link ByteBinaryTag}. */ +@Deprecated public final class ByteTag extends Tag { - private final byte value; + private final ByteBinaryTag innerTag; /** * Creates the tag with an empty name. @@ -33,17 +38,21 @@ public final class ByteTag extends Tag { */ public ByteTag(byte value) { super(); - this.value = value; + this.innerTag = ByteBinaryTag.of(value); + } + + public ByteTag(ByteBinaryTag adventureTag) { + super(); + this.innerTag = adventureTag; } @Override public Byte getValue() { - return value; + return innerTag.value(); } @Override - public String toString() { - return "TAG_Byte(" + value + ")"; + public ByteBinaryTag asBinaryTag() { + return innerTag; } - } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTag.java index 3a382effec..247d6eaee8 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTag.java @@ -19,17 +19,26 @@ package com.sk89q.jnbt; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import com.sk89q.worldedit.util.nbt.BinaryTag; +import com.sk89q.worldedit.util.nbt.BinaryTagLike; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; +import com.sk89q.worldedit.util.nbt.NumberBinaryTag; + import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; /** * The {@code TAG_Compound} tag. + * + * @deprecated Use {@link com.sk89q.worldedit.util.nbt.CompoundBinaryTag}. */ +@Deprecated public final class CompoundTag extends Tag { - private final Map value; + private final CompoundBinaryTag innerTag; /** * Creates the tag with an empty name. @@ -37,8 +46,13 @@ public final class CompoundTag extends Tag { * @param value the value of the tag */ public CompoundTag(Map value) { - super(); - this.value = Collections.unmodifiableMap(value); + this(CompoundBinaryTag.builder() + .put(Maps.transformValues(value, BinaryTagLike::asBinaryTag)) + .build()); + } + + public CompoundTag(CompoundBinaryTag adventureTag) { + this.innerTag = adventureTag; } /** @@ -48,12 +62,16 @@ public CompoundTag(Map value) { * @return true if the tag contains the given key */ public boolean containsKey(String key) { - return value.containsKey(key); + return innerTag.keySet().contains(key); } @Override public Map getValue() { - return value; + ImmutableMap.Builder map = ImmutableMap.builder(); + for (String key : innerTag.keySet()) { + map.put(key, AdventureNBTConverter.fromAdventure(innerTag.get(key))); + } + return map.build(); } /** @@ -72,7 +90,7 @@ public CompoundTag setValue(Map value) { * @return the builder */ public CompoundTagBuilder createBuilder() { - return new CompoundTagBuilder(new HashMap<>(value)); + return new CompoundTagBuilder(innerTag); } /** @@ -85,12 +103,7 @@ public CompoundTagBuilder createBuilder() { * @return a byte array */ public byte[] getByteArray(String key) { - Tag tag = value.get(key); - if (tag instanceof ByteArrayTag) { - return ((ByteArrayTag) tag).getValue(); - } else { - return new byte[0]; - } + return this.innerTag.getByteArray(key); } /** @@ -103,12 +116,7 @@ public byte[] getByteArray(String key) { * @return a byte */ public byte getByte(String key) { - Tag tag = value.get(key); - if (tag instanceof ByteTag) { - return ((ByteTag) tag).getValue(); - } else { - return (byte) 0; - } + return this.innerTag.getByte(key); } /** @@ -121,12 +129,7 @@ public byte getByte(String key) { * @return a double */ public double getDouble(String key) { - Tag tag = value.get(key); - if (tag instanceof DoubleTag) { - return ((DoubleTag) tag).getValue(); - } else { - return 0; - } + return this.innerTag.getDouble(key); } /** @@ -140,28 +143,11 @@ public double getDouble(String key) { * @return a double */ public double asDouble(String key) { - Tag tag = value.get(key); - if (tag instanceof ByteTag) { - return ((ByteTag) tag).getValue(); - - } else if (tag instanceof ShortTag) { - return ((ShortTag) tag).getValue(); - - } else if (tag instanceof IntTag) { - return ((IntTag) tag).getValue(); - - } else if (tag instanceof LongTag) { - return ((LongTag) tag).getValue(); - - } else if (tag instanceof FloatTag) { - return ((FloatTag) tag).getValue(); - - } else if (tag instanceof DoubleTag) { - return ((DoubleTag) tag).getValue(); - - } else { - return 0; + BinaryTag tag = this.innerTag.get(key); + if (tag instanceof NumberBinaryTag) { + return ((NumberBinaryTag) tag).doubleValue(); } + return 0; } /** @@ -174,12 +160,7 @@ public double asDouble(String key) { * @return a float */ public float getFloat(String key) { - Tag tag = value.get(key); - if (tag instanceof FloatTag) { - return ((FloatTag) tag).getValue(); - } else { - return 0; - } + return this.innerTag.getFloat(key); } /** @@ -192,12 +173,7 @@ public float getFloat(String key) { * @return an int array */ public int[] getIntArray(String key) { - Tag tag = value.get(key); - if (tag instanceof IntArrayTag) { - return ((IntArrayTag) tag).getValue(); - } else { - return new int[0]; - } + return this.innerTag.getIntArray(key); } /** @@ -210,12 +186,7 @@ public int[] getIntArray(String key) { * @return an int */ public int getInt(String key) { - Tag tag = value.get(key); - if (tag instanceof IntTag) { - return ((IntTag) tag).getValue(); - } else { - return 0; - } + return this.innerTag.getInt(key); } /** @@ -229,28 +200,11 @@ public int getInt(String key) { * @return an int */ public int asInt(String key) { - Tag tag = value.get(key); - if (tag instanceof ByteTag) { - return ((ByteTag) tag).getValue(); - - } else if (tag instanceof ShortTag) { - return ((ShortTag) tag).getValue(); - - } else if (tag instanceof IntTag) { - return ((IntTag) tag).getValue(); - - } else if (tag instanceof LongTag) { - return ((LongTag) tag).getValue().intValue(); - - } else if (tag instanceof FloatTag) { - return ((FloatTag) tag).getValue().intValue(); - - } else if (tag instanceof DoubleTag) { - return ((DoubleTag) tag).getValue().intValue(); - - } else { - return 0; + BinaryTag tag = this.innerTag.get(key); + if (tag instanceof NumberBinaryTag) { + return ((NumberBinaryTag) tag).intValue(); } + return 0; } /** @@ -263,12 +217,7 @@ public int asInt(String key) { * @return a list of tags */ public List getList(String key) { - Tag tag = value.get(key); - if (tag instanceof ListTag) { - return ((ListTag) tag).getValue(); - } else { - return Collections.emptyList(); - } + return getListTag(key).getValue(); } /** @@ -281,12 +230,7 @@ public List getList(String key) { * @return a tag list instance */ public ListTag getListTag(String key) { - Tag tag = value.get(key); - if (tag instanceof ListTag) { - return (ListTag) tag; - } else { - return new ListTag(StringTag.class, Collections.emptyList()); - } + return new ListTag(this.innerTag.getList(key)); } /** @@ -304,14 +248,9 @@ public ListTag getListTag(String key) { */ @SuppressWarnings("unchecked") public List getList(String key, Class listType) { - Tag tag = value.get(key); - if (tag instanceof ListTag) { - ListTag listTag = (ListTag) tag; - if (listTag.getType().equals(listType)) { - return (List) listTag.getValue(); - } else { - return Collections.emptyList(); - } + ListTag listTag = getListTag(key); + if (listTag.getType().equals(listType)) { + return (List) listTag.getValue(); } else { return Collections.emptyList(); } @@ -327,12 +266,7 @@ public List getList(String key, Class listType) { * @return an int array */ public long[] getLongArray(String key) { - Tag tag = value.get(key); - if (tag instanceof LongArrayTag) { - return ((LongArrayTag) tag).getValue(); - } else { - return new long[0]; - } + return this.innerTag.getLongArray(key); } /** @@ -345,12 +279,7 @@ public long[] getLongArray(String key) { * @return a long */ public long getLong(String key) { - Tag tag = value.get(key); - if (tag instanceof LongTag) { - return ((LongTag) tag).getValue(); - } else { - return 0L; - } + return this.innerTag.getLong(key); } /** @@ -364,28 +293,11 @@ public long getLong(String key) { * @return a long */ public long asLong(String key) { - Tag tag = value.get(key); - if (tag instanceof ByteTag) { - return ((ByteTag) tag).getValue(); - - } else if (tag instanceof ShortTag) { - return ((ShortTag) tag).getValue(); - - } else if (tag instanceof IntTag) { - return ((IntTag) tag).getValue(); - - } else if (tag instanceof LongTag) { - return ((LongTag) tag).getValue(); - - } else if (tag instanceof FloatTag) { - return ((FloatTag) tag).getValue().longValue(); - - } else if (tag instanceof DoubleTag) { - return ((DoubleTag) tag).getValue().longValue(); - - } else { - return 0L; + BinaryTag tag = this.innerTag.get(key); + if (tag instanceof NumberBinaryTag) { + return ((NumberBinaryTag) tag).longValue(); } + return 0; } /** @@ -398,12 +310,7 @@ public long asLong(String key) { * @return a short */ public short getShort(String key) { - Tag tag = value.get(key); - if (tag instanceof ShortTag) { - return ((ShortTag) tag).getValue(); - } else { - return 0; - } + return this.innerTag.getShort(key); } /** @@ -416,23 +323,11 @@ public short getShort(String key) { * @return a string */ public String getString(String key) { - Tag tag = value.get(key); - if (tag instanceof StringTag) { - return ((StringTag) tag).getValue(); - } else { - return ""; - } + return this.innerTag.getString(key); } @Override - public String toString() { - StringBuilder bldr = new StringBuilder(); - bldr.append("TAG_Compound").append(": ").append(value.size()).append(" entries\r\n{\r\n"); - for (Map.Entry entry : value.entrySet()) { - bldr.append(" ").append(entry.getValue().toString().replaceAll("\r\n", "\r\n ")).append("\r\n"); - } - bldr.append("}"); - return bldr.toString(); + public CompoundBinaryTag asBinaryTag() { + return this.innerTag; } - } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTagBuilder.java b/worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTagBuilder.java index 7267a72e0a..198176916b 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTagBuilder.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTagBuilder.java @@ -19,33 +19,39 @@ package com.sk89q.jnbt; -import java.util.HashMap; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; + import java.util.Map; +import java.util.Objects; import static com.google.common.base.Preconditions.checkNotNull; /** * Helps create compound tags. + * + * @deprecated Use {@link com.sk89q.worldedit.util.nbt.CompoundBinaryTag.Builder}. */ +@Deprecated public class CompoundTagBuilder { - private final Map entries; + private final CompoundBinaryTag.Builder builder = CompoundBinaryTag.builder(); /** * Create a new instance. */ CompoundTagBuilder() { - this.entries = new HashMap<>(); } /** * Create a new instance and use the given map (which will be modified). * - * @param value the value + * @param source the value */ - CompoundTagBuilder(Map value) { - checkNotNull(value); - this.entries = value; + CompoundTagBuilder(CompoundBinaryTag source) { + checkNotNull(source); + for (String key : source.keySet()) { + this.builder.put(key, Objects.requireNonNull(source.get(key))); + } } /** @@ -58,7 +64,7 @@ public class CompoundTagBuilder { public CompoundTagBuilder put(String key, Tag value) { checkNotNull(key); checkNotNull(value); - entries.put(key, value); + this.builder.put(key, value.asBinaryTag()); return this; } @@ -71,7 +77,8 @@ public CompoundTagBuilder put(String key, Tag value) { * @return this object */ public CompoundTagBuilder putByteArray(String key, byte[] value) { - return put(key, new ByteArrayTag(value)); + this.builder.putByteArray(key, value); + return this; } /** @@ -83,7 +90,8 @@ public CompoundTagBuilder putByteArray(String key, byte[] value) { * @return this object */ public CompoundTagBuilder putByte(String key, byte value) { - return put(key, new ByteTag(value)); + this.builder.putByte(key, value); + return this; } /** @@ -95,7 +103,8 @@ public CompoundTagBuilder putByte(String key, byte value) { * @return this object */ public CompoundTagBuilder putDouble(String key, double value) { - return put(key, new DoubleTag(value)); + this.builder.putDouble(key, value); + return this; } /** @@ -107,7 +116,8 @@ public CompoundTagBuilder putDouble(String key, double value) { * @return this object */ public CompoundTagBuilder putFloat(String key, float value) { - return put(key, new FloatTag(value)); + this.builder.putFloat(key, value); + return this; } /** @@ -119,7 +129,8 @@ public CompoundTagBuilder putFloat(String key, float value) { * @return this object */ public CompoundTagBuilder putIntArray(String key, int[] value) { - return put(key, new IntArrayTag(value)); + this.builder.putIntArray(key, value); + return this; } /** @@ -130,7 +141,8 @@ public CompoundTagBuilder putIntArray(String key, int[] value) { * @return this object */ public CompoundTagBuilder putInt(String key, int value) { - return put(key, new IntTag(value)); + this.builder.putInt(key, value); + return this; } /** @@ -142,7 +154,8 @@ public CompoundTagBuilder putInt(String key, int value) { * @return this object */ public CompoundTagBuilder putLongArray(String key, long[] value) { - return put(key, new LongArrayTag(value)); + this.builder.putLongArray(key, value); + return this; } /** @@ -154,7 +167,8 @@ public CompoundTagBuilder putLongArray(String key, long[] value) { * @return this object */ public CompoundTagBuilder putLong(String key, long value) { - return put(key, new LongTag(value)); + this.builder.putLong(key, value); + return this; } /** @@ -166,7 +180,8 @@ public CompoundTagBuilder putLong(String key, long value) { * @return this object */ public CompoundTagBuilder putShort(String key, short value) { - return put(key, new ShortTag(value)); + this.builder.putShort(key, value); + return this; } /** @@ -178,7 +193,8 @@ public CompoundTagBuilder putShort(String key, short value) { * @return this object */ public CompoundTagBuilder putString(String key, String value) { - return put(key, new StringTag(value)); + this.builder.putString(key, value); + return this; } /** @@ -189,7 +205,7 @@ public CompoundTagBuilder putString(String key, String value) { */ public CompoundTagBuilder remove(String key) { checkNotNull(key); - entries.remove(key); + this.builder.remove(key); return this; } @@ -213,7 +229,7 @@ public CompoundTagBuilder putAll(Map value) { * @return the new compound tag */ public CompoundTag build() { - return new CompoundTag(new HashMap<>(entries)); + return new CompoundTag(this.builder.build()); } /** diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/DoubleTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/DoubleTag.java index b579308571..12cc99f1c4 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/DoubleTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/DoubleTag.java @@ -19,12 +19,17 @@ package com.sk89q.jnbt; +import com.sk89q.worldedit.util.nbt.DoubleBinaryTag; + /** * The {@code TAG_Double} tag. + * + * @deprecated Use {@link DoubleBinaryTag}. */ +@Deprecated public final class DoubleTag extends Tag { - private final double value; + private final DoubleBinaryTag innerTag; /** * Creates the tag with an empty name. @@ -33,17 +38,22 @@ public final class DoubleTag extends Tag { */ public DoubleTag(double value) { super(); - this.value = value; + this.innerTag = DoubleBinaryTag.of(value); + } + + public DoubleTag(DoubleBinaryTag adventureTag) { + super(); + this.innerTag = adventureTag; } @Override - public Double getValue() { - return value; + public DoubleBinaryTag asBinaryTag() { + return this.innerTag; } @Override - public String toString() { - return "TAG_Double(" + value + ")"; + public Double getValue() { + return innerTag.value(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/EndTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/EndTag.java index c6fc635983..3f179e54fd 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/EndTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/EndTag.java @@ -19,9 +19,14 @@ package com.sk89q.jnbt; +import com.sk89q.worldedit.util.nbt.EndBinaryTag; + /** * The {@code TAG_End} tag. + * + * @deprecated Use {@link com.sk89q.worldedit.util.nbt.EndBinaryTag}. */ +@Deprecated public final class EndTag extends Tag { @Override @@ -30,8 +35,7 @@ public Object getValue() { } @Override - public String toString() { - return "TAG_End"; + public EndBinaryTag asBinaryTag() { + return EndBinaryTag.get(); } - } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/FloatTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/FloatTag.java index e1281ea131..80ebbd7cd3 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/FloatTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/FloatTag.java @@ -19,12 +19,17 @@ package com.sk89q.jnbt; +import com.sk89q.worldedit.util.nbt.FloatBinaryTag; + /** * The {@code TAG_Float} tag. + * + * @deprecated Use {@link FloatBinaryTag}. */ +@Deprecated public final class FloatTag extends Tag { - private final float value; + private final FloatBinaryTag innerTag; /** * Creates the tag with an empty name. @@ -33,17 +38,22 @@ public final class FloatTag extends Tag { */ public FloatTag(float value) { super(); - this.value = value; + this.innerTag = FloatBinaryTag.of(value); + } + + public FloatTag(FloatBinaryTag adventureTag) { + super(); + this.innerTag = adventureTag; } @Override - public Float getValue() { - return value; + public FloatBinaryTag asBinaryTag() { + return this.innerTag; } @Override - public String toString() { - return "TAG_Float(" + value + ")"; + public Float getValue() { + return innerTag.value(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/IntArrayTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/IntArrayTag.java index 39c6217359..86bb182a9b 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/IntArrayTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/IntArrayTag.java @@ -19,16 +19,19 @@ package com.sk89q.jnbt; -import java.util.Locale; +import com.sk89q.worldedit.util.nbt.IntArrayBinaryTag; import static com.google.common.base.Preconditions.checkNotNull; /** * The {@code TAG_Int_Array} tag. + * + * @deprecated Use {@link IntArrayBinaryTag}. */ +@Deprecated public final class IntArrayTag extends Tag { - private final int[] value; + private final IntArrayBinaryTag innerTag; /** * Creates the tag with an empty name. @@ -38,25 +41,22 @@ public final class IntArrayTag extends Tag { public IntArrayTag(int[] value) { super(); checkNotNull(value); - this.value = value; + this.innerTag = IntArrayBinaryTag.of(value); + } + + public IntArrayTag(IntArrayBinaryTag adventureTag) { + super(); + this.innerTag = adventureTag; } @Override - public int[] getValue() { - return value; + public IntArrayBinaryTag asBinaryTag() { + return this.innerTag; } @Override - public String toString() { - StringBuilder hex = new StringBuilder(); - for (int b : value) { - String hexDigits = Integer.toHexString(b).toUpperCase(Locale.ROOT); - if (hexDigits.length() == 1) { - hex.append("0"); - } - hex.append(hexDigits).append(" "); - } - return "TAG_Int_Array(" + hex + ")"; + public int[] getValue() { + return innerTag.value(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/IntTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/IntTag.java index 359cf85b9b..fd7076eb27 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/IntTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/IntTag.java @@ -19,12 +19,17 @@ package com.sk89q.jnbt; +import com.sk89q.worldedit.util.nbt.IntBinaryTag; + /** * The {@code TAG_Int} tag. + * + * @deprecated Use {@link IntBinaryTag}. */ +@Deprecated public final class IntTag extends Tag { - private final int value; + private final IntBinaryTag innerTag; /** * Creates the tag with an empty name. @@ -33,17 +38,22 @@ public final class IntTag extends Tag { */ public IntTag(int value) { super(); - this.value = value; + this.innerTag = IntBinaryTag.of(value); + } + + public IntTag(IntBinaryTag adventureTag) { + super(); + this.innerTag = adventureTag; } @Override - public Integer getValue() { - return value; + public IntBinaryTag asBinaryTag() { + return this.innerTag; } @Override - public String toString() { - return "TAG_Int(" + value + ")"; + public Integer getValue() { + return innerTag.value(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/ListTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/ListTag.java index 8134a3f74e..15bc76afb7 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/ListTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/ListTag.java @@ -19,19 +19,27 @@ package com.sk89q.jnbt; +import com.sk89q.worldedit.util.nbt.BinaryTag; +import com.sk89q.worldedit.util.nbt.BinaryTagLike; +import com.sk89q.worldedit.util.nbt.ListBinaryTag; +import com.sk89q.worldedit.util.nbt.NumberBinaryTag; + import java.util.Collections; import java.util.List; +import java.util.function.IntFunction; +import java.util.function.Supplier; +import java.util.stream.Collectors; import javax.annotation.Nullable; -import static com.google.common.base.Preconditions.checkNotNull; - /** * The {@code TAG_List} tag. + * + * @deprecated Use {@link com.sk89q.worldedit.util.nbt.ListBinaryTag}. */ +@Deprecated public final class ListTag extends Tag { - private final Class type; - private final List value; + private final ListBinaryTag innerTag; /** * Creates the tag with an empty name. @@ -40,10 +48,19 @@ public final class ListTag extends Tag { * @param value the value of the tag */ public ListTag(Class type, List value) { - super(); - checkNotNull(value); - this.type = type; - this.value = Collections.unmodifiableList(value); + this(ListBinaryTag.of( + AdventureNBTConverter.getAdventureType(type), + value.stream().map(BinaryTagLike::asBinaryTag).collect(Collectors.toList()) + )); + } + + public ListTag(ListBinaryTag adventureTag) { + this.innerTag = adventureTag; + } + + @Override + public ListBinaryTag asBinaryTag() { + return this.innerTag; } /** @@ -52,12 +69,14 @@ public ListTag(Class type, List value) { * @return The type of item in this list. */ public Class getType() { - return type; + return AdventureNBTConverter.getJNBTType(this.innerTag.elementType()); } @Override public List getValue() { - return value; + return this.innerTag.stream() + .map(AdventureNBTConverter::fromAdventure) + .collect(Collectors.toList()); } /** @@ -70,6 +89,13 @@ public ListTag setValue(List list) { return new ListTag(getType(), list); } + private T accessIfExists(int index, Supplier defaultValue, IntFunction accessor) { + if (index >= this.innerTag.size()) { + return defaultValue.get(); + } + return accessor.apply(index); + } + /** * Get the tag if it exists at the given index. * @@ -78,10 +104,11 @@ public ListTag setValue(List list) { */ @Nullable public Tag getIfExists(int index) { - if (index >= value.size()) { - return null; - } - return value.get(index); + return accessIfExists( + index, + () -> null, + i -> AdventureNBTConverter.fromAdventure(this.innerTag.get(i)) + ); } /** @@ -94,12 +121,11 @@ public Tag getIfExists(int index) { * @return a byte array */ public byte[] getByteArray(int index) { - Tag tag = getIfExists(index); - if (tag instanceof ByteArrayTag) { - return ((ByteArrayTag) tag).getValue(); - } else { - return new byte[0]; - } + return accessIfExists( + index, + () -> new byte[0], + this.innerTag::getByteArray + ); } /** @@ -112,12 +138,11 @@ public byte[] getByteArray(int index) { * @return a byte */ public byte getByte(int index) { - Tag tag = getIfExists(index); - if (tag instanceof ByteTag) { - return ((ByteTag) tag).getValue(); - } else { - return (byte) 0; - } + return accessIfExists( + index, + () -> (byte) 0, + this.innerTag::getByte + ); } /** @@ -130,12 +155,11 @@ public byte getByte(int index) { * @return a double */ public double getDouble(int index) { - Tag tag = getIfExists(index); - if (tag instanceof DoubleTag) { - return ((DoubleTag) tag).getValue(); - } else { - return 0; - } + return accessIfExists( + index, + () -> 0.0, + this.innerTag::getDouble + ); } /** @@ -149,28 +173,17 @@ public double getDouble(int index) { * @return a double */ public double asDouble(int index) { - Tag tag = getIfExists(index); - if (tag instanceof ByteTag) { - return ((ByteTag) tag).getValue(); - - } else if (tag instanceof ShortTag) { - return ((ShortTag) tag).getValue(); - - } else if (tag instanceof IntTag) { - return ((IntTag) tag).getValue(); - - } else if (tag instanceof LongTag) { - return ((LongTag) tag).getValue(); - - } else if (tag instanceof FloatTag) { - return ((FloatTag) tag).getValue(); - - } else if (tag instanceof DoubleTag) { - return ((DoubleTag) tag).getValue(); - - } else { - return 0; - } + return accessIfExists( + index, + () -> 0.0, + i -> { + BinaryTag tag = this.innerTag.get(i); + if (tag instanceof NumberBinaryTag) { + return ((NumberBinaryTag) tag).doubleValue(); + } + return 0.0; + } + ); } /** @@ -183,12 +196,11 @@ public double asDouble(int index) { * @return a float */ public float getFloat(int index) { - Tag tag = getIfExists(index); - if (tag instanceof FloatTag) { - return ((FloatTag) tag).getValue(); - } else { - return 0; - } + return accessIfExists( + index, + () -> 0.0f, + this.innerTag::getFloat + ); } /** @@ -201,12 +213,11 @@ public float getFloat(int index) { * @return an int array */ public int[] getIntArray(int index) { - Tag tag = getIfExists(index); - if (tag instanceof IntArrayTag) { - return ((IntArrayTag) tag).getValue(); - } else { - return new int[0]; - } + return accessIfExists( + index, + () -> new int[0], + this.innerTag::getIntArray + ); } /** @@ -219,12 +230,11 @@ public int[] getIntArray(int index) { * @return an int */ public int getInt(int index) { - Tag tag = getIfExists(index); - if (tag instanceof IntTag) { - return ((IntTag) tag).getValue(); - } else { - return 0; - } + return accessIfExists( + index, + () -> 0, + this.innerTag::getInt + ); } /** @@ -238,28 +248,17 @@ public int getInt(int index) { * @return an int */ public int asInt(int index) { - Tag tag = getIfExists(index); - if (tag instanceof ByteTag) { - return ((ByteTag) tag).getValue(); - - } else if (tag instanceof ShortTag) { - return ((ShortTag) tag).getValue(); - - } else if (tag instanceof IntTag) { - return ((IntTag) tag).getValue(); - - } else if (tag instanceof LongTag) { - return ((LongTag) tag).getValue().intValue(); - - } else if (tag instanceof FloatTag) { - return ((FloatTag) tag).getValue().intValue(); - - } else if (tag instanceof DoubleTag) { - return ((DoubleTag) tag).getValue().intValue(); - - } else { - return 0; - } + return accessIfExists( + index, + () -> 0, + i -> { + BinaryTag tag = this.innerTag.get(i); + if (tag instanceof NumberBinaryTag) { + return ((NumberBinaryTag) tag).intValue(); + } + return 0; + } + ); } /** @@ -272,12 +271,7 @@ public int asInt(int index) { * @return a list of tags */ public List getList(int index) { - Tag tag = getIfExists(index); - if (tag instanceof ListTag) { - return ((ListTag) tag).getValue(); - } else { - return Collections.emptyList(); - } + return getListTag(index).getValue(); } /** @@ -290,12 +284,11 @@ public List getList(int index) { * @return a tag list instance */ public ListTag getListTag(int index) { - Tag tag = getIfExists(index); - if (tag instanceof ListTag) { - return (ListTag) tag; - } else { - return new ListTag(StringTag.class, Collections.emptyList()); - } + return new ListTag(accessIfExists( + index, + ListBinaryTag::empty, + this.innerTag::getList + )); } /** @@ -313,14 +306,9 @@ public ListTag getListTag(int index) { */ @SuppressWarnings("unchecked") public List getList(int index, Class listType) { - Tag tag = getIfExists(index); - if (tag instanceof ListTag) { - ListTag listTag = (ListTag) tag; - if (listTag.getType().equals(listType)) { - return (List) listTag.getValue(); - } else { - return Collections.emptyList(); - } + ListTag listTag = getListTag(index); + if (listTag.getType().equals(listType)) { + return (List) listTag.getValue(); } else { return Collections.emptyList(); } @@ -336,12 +324,11 @@ public List getList(int index, Class listType) { * @return a long */ public long getLong(int index) { - Tag tag = getIfExists(index); - if (tag instanceof LongTag) { - return ((LongTag) tag).getValue(); - } else { - return 0L; - } + return accessIfExists( + index, + () -> 0L, + this.innerTag::getLong + ); } /** @@ -355,28 +342,17 @@ public long getLong(int index) { * @return a long */ public long asLong(int index) { - Tag tag = getIfExists(index); - if (tag instanceof ByteTag) { - return ((ByteTag) tag).getValue(); - - } else if (tag instanceof ShortTag) { - return ((ShortTag) tag).getValue(); - - } else if (tag instanceof IntTag) { - return ((IntTag) tag).getValue(); - - } else if (tag instanceof LongTag) { - return ((LongTag) tag).getValue(); - - } else if (tag instanceof FloatTag) { - return ((FloatTag) tag).getValue().longValue(); - - } else if (tag instanceof DoubleTag) { - return ((DoubleTag) tag).getValue().longValue(); - - } else { - return 0; - } + return accessIfExists( + index, + () -> 0L, + i -> { + BinaryTag tag = this.innerTag.get(i); + if (tag instanceof NumberBinaryTag) { + return ((NumberBinaryTag) tag).longValue(); + } + return 0L; + } + ); } /** @@ -389,12 +365,11 @@ public long asLong(int index) { * @return a short */ public short getShort(int index) { - Tag tag = getIfExists(index); - if (tag instanceof ShortTag) { - return ((ShortTag) tag).getValue(); - } else { - return 0; - } + return accessIfExists( + index, + () -> (short) 0, + this.innerTag::getShort + ); } /** @@ -407,23 +382,11 @@ public short getShort(int index) { * @return a string */ public String getString(int index) { - Tag tag = getIfExists(index); - if (tag instanceof StringTag) { - return ((StringTag) tag).getValue(); - } else { - return ""; - } - } - - @Override - public String toString() { - StringBuilder bldr = new StringBuilder(); - bldr.append("TAG_List").append(": ").append(value.size()).append(" entries of type ").append(NBTUtils.getTypeName(type)).append("\r\n{\r\n"); - for (Tag t : value) { - bldr.append(" ").append(t.toString().replaceAll("\r\n", "\r\n ")).append("\r\n"); - } - bldr.append("}"); - return bldr.toString(); + return accessIfExists( + index, + () -> "", + this.innerTag::getString + ); } } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/ListTagBuilder.java b/worldedit-core/src/main/java/com/sk89q/jnbt/ListTagBuilder.java index b98c667e50..df19227036 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/ListTagBuilder.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/ListTagBuilder.java @@ -19,30 +19,36 @@ package com.sk89q.jnbt; -import java.util.ArrayList; +import com.sk89q.worldedit.util.nbt.BinaryTag; +import com.sk89q.worldedit.util.nbt.BinaryTagType; +import com.sk89q.worldedit.util.nbt.ListBinaryTag; + import java.util.Arrays; import java.util.Collection; -import java.util.List; import static com.google.common.base.Preconditions.checkNotNull; /** * Helps create list tags. + * + * @deprecated Use {@link com.sk89q.worldedit.util.nbt.ListBinaryTag.Builder}. */ +@Deprecated public class ListTagBuilder { - private final Class type; - private final List entries; + private final ListBinaryTag.Builder builder; /** * Create a new instance. * * @param type of tag contained in this list */ + @SuppressWarnings("unchecked") ListTagBuilder(Class type) { checkNotNull(type); - this.type = type; - this.entries = new ArrayList<>(); + this.builder = type != EndTag.class + ? ListBinaryTag.builder((BinaryTagType) AdventureNBTConverter.getAdventureType(type)) + : ListBinaryTag.builder(); } /** @@ -53,10 +59,7 @@ public class ListTagBuilder { */ public ListTagBuilder add(Tag value) { checkNotNull(value); - if (!type.isInstance(value)) { - throw new IllegalArgumentException(value.getClass().getCanonicalName() + " is not of expected type " + type.getCanonicalName()); - } - entries.add(value); + builder.add(value.asBinaryTag()); return this; } @@ -80,7 +83,7 @@ public ListTagBuilder addAll(Collection value) { * @return the new list tag */ public ListTag build() { - return new ListTag(type, new ArrayList<>(entries)); + return new ListTag(this.builder.build()); } /** diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/LongArrayTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/LongArrayTag.java index c2e9688d08..cd177c8601 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/LongArrayTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/LongArrayTag.java @@ -19,16 +19,19 @@ package com.sk89q.jnbt; -import java.util.Locale; +import com.sk89q.worldedit.util.nbt.LongArrayBinaryTag; import static com.google.common.base.Preconditions.checkNotNull; /** * The {@code TAG_Long_Array} tag. + * + * @deprecated Use {@link LongArrayBinaryTag}. */ +@Deprecated public class LongArrayTag extends Tag { - private final long[] value; + private final LongArrayBinaryTag innerTag; /** * Creates the tag with an empty name. @@ -38,25 +41,22 @@ public class LongArrayTag extends Tag { public LongArrayTag(long[] value) { super(); checkNotNull(value); - this.value = value; + this.innerTag = LongArrayBinaryTag.of(value); + } + + public LongArrayTag(LongArrayBinaryTag adventureTag) { + super(); + this.innerTag = adventureTag; } @Override - public long[] getValue() { - return value; + public LongArrayBinaryTag asBinaryTag() { + return this.innerTag; } @Override - public String toString() { - StringBuilder hex = new StringBuilder(); - for (long b : value) { - String hexDigits = Long.toHexString(b).toUpperCase(Locale.ROOT); - if (hexDigits.length() == 1) { - hex.append("0"); - } - hex.append(hexDigits).append(" "); - } - return "TAG_Long_Array(" + hex + ")"; + public long[] getValue() { + return innerTag.value(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/LongTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/LongTag.java index 8f894520a2..35c6b0fe58 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/LongTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/LongTag.java @@ -19,12 +19,17 @@ package com.sk89q.jnbt; +import com.sk89q.worldedit.util.nbt.LongBinaryTag; + /** * The {@code TAG_Long} tag. + * + * @deprecated Use {@link LongBinaryTag}. */ +@Deprecated public final class LongTag extends Tag { - private final long value; + private final LongBinaryTag innerTag; /** * Creates the tag with an empty name. @@ -33,17 +38,22 @@ public final class LongTag extends Tag { */ public LongTag(long value) { super(); - this.value = value; + this.innerTag = LongBinaryTag.of(value); + } + + public LongTag(LongBinaryTag adventureTag) { + super(); + this.innerTag = adventureTag; } @Override - public Long getValue() { - return value; + public LongBinaryTag asBinaryTag() { + return this.innerTag; } @Override - public String toString() { - return "TAG_Long(" + value + ")"; + public Long getValue() { + return innerTag.value(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTConstants.java b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTConstants.java index db6689cb52..dc6a7125f9 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTConstants.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTConstants.java @@ -19,15 +19,14 @@ package com.sk89q.jnbt; -import java.nio.charset.Charset; - /** * A class which holds constant values. + * + * @deprecated JNBT is being removed for adventure-nbt in WorldEdit 8. */ +@Deprecated public final class NBTConstants { - public static final Charset CHARSET = Charset.forName("UTF-8"); - public static final int TYPE_END = 0; public static final int TYPE_BYTE = 1; public static final int TYPE_SHORT = 2; diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTInputStream.java b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTInputStream.java index 35a0bb62e1..3c9d701e9e 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTInputStream.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTInputStream.java @@ -19,13 +19,14 @@ package com.sk89q.jnbt; +import com.sk89q.worldedit.util.nbt.BinaryTagIO; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; + import java.io.Closeable; +import java.io.DataInput; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; import java.util.Map; /** @@ -38,7 +39,10 @@ * found at * https://minecraft.gamepedia.com/NBT_format. *

+ * + * @deprecated JNBT is being removed for adventure-nbt in WorldEdit 8. */ +@Deprecated public final class NBTInputStream implements Closeable { private final DataInputStream is; @@ -60,115 +64,10 @@ public NBTInputStream(InputStream is) { * @throws IOException if an I/O error occurs. */ public NamedTag readNamedTag() throws IOException { - return readNamedTag(0); - } - - /** - * Reads an NBT from the stream. - * - * @param depth the depth of this tag - * @return The tag that was read. - * @throws IOException if an I/O error occurs. - */ - private NamedTag readNamedTag(int depth) throws IOException { - int type = is.readByte() & 0xFF; - - String name; - if (type != NBTConstants.TYPE_END) { - int nameLength = is.readShort() & 0xFFFF; - byte[] nameBytes = new byte[nameLength]; - is.readFully(nameBytes); - name = new String(nameBytes, NBTConstants.CHARSET); - } else { - name = ""; - } - - return new NamedTag(name, readTagPayload(type, depth)); - } - - /** - * Reads the payload of a tag given the type. - * - * @param type the type - * @param depth the depth - * @return the tag - * @throws IOException if an I/O error occurs. - */ - private Tag readTagPayload(int type, int depth) throws IOException { - switch (type) { - case NBTConstants.TYPE_END: - if (depth == 0) { - throw new IOException( - "TAG_End found without a TAG_Compound/TAG_List tag preceding it."); - } else { - return new EndTag(); - } - case NBTConstants.TYPE_BYTE: - return new ByteTag(is.readByte()); - case NBTConstants.TYPE_SHORT: - return new ShortTag(is.readShort()); - case NBTConstants.TYPE_INT: - return new IntTag(is.readInt()); - case NBTConstants.TYPE_LONG: - return new LongTag(is.readLong()); - case NBTConstants.TYPE_FLOAT: - return new FloatTag(is.readFloat()); - case NBTConstants.TYPE_DOUBLE: - return new DoubleTag(is.readDouble()); - case NBTConstants.TYPE_BYTE_ARRAY: - int length = is.readInt(); - byte[] bytes = new byte[length]; - is.readFully(bytes); - return new ByteArrayTag(bytes); - case NBTConstants.TYPE_STRING: - length = is.readShort(); - bytes = new byte[length]; - is.readFully(bytes); - return new StringTag(new String(bytes, NBTConstants.CHARSET)); - case NBTConstants.TYPE_LIST: - int childType = is.readByte(); - length = is.readInt(); - - List tagList = new ArrayList<>(); - for (int i = 0; i < length; ++i) { - Tag tag = readTagPayload(childType, depth + 1); - if (tag instanceof EndTag) { - throw new IOException("TAG_End not permitted in a list."); - } - tagList.add(tag); - } - - return new ListTag(NBTUtils.getTypeClass(childType), tagList); - case NBTConstants.TYPE_COMPOUND: - Map tagMap = new HashMap<>(); - while (true) { - NamedTag namedTag = readNamedTag(depth + 1); - Tag tag = namedTag.getTag(); - if (tag instanceof EndTag) { - break; - } else { - tagMap.put(namedTag.getName(), tag); - } - } - - return new CompoundTag(tagMap); - case NBTConstants.TYPE_INT_ARRAY: - length = is.readInt(); - int[] data = new int[length]; - for (int i = 0; i < length; i++) { - data[i] = is.readInt(); - } - return new IntArrayTag(data); - case NBTConstants.TYPE_LONG_ARRAY: - length = is.readInt(); - long[] longData = new long[length]; - for (int i = 0; i < length; i++) { - longData[i] = is.readLong(); - } - return new LongArrayTag(longData); - default: - throw new IOException("Invalid tag type: " + type + "."); - } + Map.Entry named = BinaryTagIO.reader().readNamed( + (DataInput) this.is + ); + return new NamedTag(named.getKey(), new CompoundTag(named.getValue())); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTOutputStream.java b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTOutputStream.java index 98ccb72db0..59fc92bc31 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTOutputStream.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTOutputStream.java @@ -19,7 +19,12 @@ package com.sk89q.jnbt; +import com.google.common.collect.Maps; +import com.sk89q.worldedit.util.nbt.BinaryTagIO; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; + import java.io.Closeable; +import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -37,7 +42,10 @@ * found at * https://minecraft.gamepedia.com/NBT_format. *

+ * + * @deprecated JNBT is being removed for adventure-nbt in WorldEdit 8. */ +@Deprecated public final class NBTOutputStream implements Closeable { /** @@ -67,236 +75,10 @@ public NBTOutputStream(OutputStream os) throws IOException { * if an I/O error occurs. */ public void writeNamedTag(String name, Tag tag) throws IOException { - checkNotNull(name); - checkNotNull(tag); - - int type = NBTUtils.getTypeCode(tag.getClass()); - byte[] nameBytes = name.getBytes(NBTConstants.CHARSET); - - os.writeByte(type); - os.writeShort(nameBytes.length); - os.write(nameBytes); - - if (type == NBTConstants.TYPE_END) { - throw new IOException("Named TAG_End not permitted."); - } - - writeTagPayload(tag); - } - - /** - * Writes tag payload. - * - * @param tag - * The tag. - * @throws IOException - * if an I/O error occurs. - */ - private void writeTagPayload(Tag tag) throws IOException { - int type = NBTUtils.getTypeCode(tag.getClass()); - switch (type) { - case NBTConstants.TYPE_END: - writeEndTagPayload((EndTag) tag); - break; - case NBTConstants.TYPE_BYTE: - writeByteTagPayload((ByteTag) tag); - break; - case NBTConstants.TYPE_SHORT: - writeShortTagPayload((ShortTag) tag); - break; - case NBTConstants.TYPE_INT: - writeIntTagPayload((IntTag) tag); - break; - case NBTConstants.TYPE_LONG: - writeLongTagPayload((LongTag) tag); - break; - case NBTConstants.TYPE_FLOAT: - writeFloatTagPayload((FloatTag) tag); - break; - case NBTConstants.TYPE_DOUBLE: - writeDoubleTagPayload((DoubleTag) tag); - break; - case NBTConstants.TYPE_BYTE_ARRAY: - writeByteArrayTagPayload((ByteArrayTag) tag); - break; - case NBTConstants.TYPE_STRING: - writeStringTagPayload((StringTag) tag); - break; - case NBTConstants.TYPE_LIST: - writeListTagPayload((ListTag) tag); - break; - case NBTConstants.TYPE_COMPOUND: - writeCompoundTagPayload((CompoundTag) tag); - break; - case NBTConstants.TYPE_INT_ARRAY: - writeIntArrayTagPayload((IntArrayTag) tag); - break; - case NBTConstants.TYPE_LONG_ARRAY: - writeLongArrayTagPayload((LongArrayTag) tag); - break; - default: - throw new IOException("Invalid tag type: " + type + "."); - } - } - - /** - * Writes a {@code TAG_Byte} tag. - * - * @param tag - * The tag. - * @throws IOException - * if an I/O error occurs. - */ - private void writeByteTagPayload(ByteTag tag) throws IOException { - os.writeByte(tag.getValue()); - } - - /** - * Writes a {@code TAG_Byte_Array} tag. - * - * @param tag - * The tag. - * @throws IOException - * if an I/O error occurs. - */ - private void writeByteArrayTagPayload(ByteArrayTag tag) throws IOException { - byte[] bytes = tag.getValue(); - os.writeInt(bytes.length); - os.write(bytes); - } - - /** - * Writes a {@code TAG_Compound} tag. - * - * @param tag - * The tag. - * @throws IOException - * if an I/O error occurs. - */ - private void writeCompoundTagPayload(CompoundTag tag) throws IOException { - for (Map.Entry entry : tag.getValue().entrySet()) { - writeNamedTag(entry.getKey(), entry.getValue()); - } - os.writeByte((byte) 0); // end tag - better way? - } - - /** - * Writes a {@code TAG_List} tag. - * - * @param tag - * The tag. - * @throws IOException - * if an I/O error occurs. - */ - private void writeListTagPayload(ListTag tag) throws IOException { - Class clazz = tag.getType(); - List tags = tag.getValue(); - int size = tags.size(); - - os.writeByte(NBTUtils.getTypeCode(clazz)); - os.writeInt(size); - for (Tag tag1 : tags) { - writeTagPayload(tag1); - } - } - - /** - * Writes a {@code TAG_String} tag. - * - * @param tag - * The tag. - * @throws IOException - * if an I/O error occurs. - */ - private void writeStringTagPayload(StringTag tag) throws IOException { - byte[] bytes = tag.getValue().getBytes(NBTConstants.CHARSET); - os.writeShort(bytes.length); - os.write(bytes); - } - - /** - * Writes a {@code TAG_Double} tag. - * - * @param tag - * The tag. - * @throws IOException - * if an I/O error occurs. - */ - private void writeDoubleTagPayload(DoubleTag tag) throws IOException { - os.writeDouble(tag.getValue()); - } - - /** - * Writes a {@code TAG_Float} tag. - * - * @param tag - * The tag. - * @throws IOException - * if an I/O error occurs. - */ - private void writeFloatTagPayload(FloatTag tag) throws IOException { - os.writeFloat(tag.getValue()); - } - - /** - * Writes a {@code TAG_Long} tag. - * - * @param tag - * The tag. - * @throws IOException - * if an I/O error occurs. - */ - private void writeLongTagPayload(LongTag tag) throws IOException { - os.writeLong(tag.getValue()); - } - - /** - * Writes a {@code TAG_Int} tag. - * - * @param tag - * The tag. - * @throws IOException - * if an I/O error occurs. - */ - private void writeIntTagPayload(IntTag tag) throws IOException { - os.writeInt(tag.getValue()); - } - - /** - * Writes a {@code TAG_Short} tag. - * - * @param tag - * The tag. - * @throws IOException - * if an I/O error occurs. - */ - private void writeShortTagPayload(ShortTag tag) throws IOException { - os.writeShort(tag.getValue()); - } - - /** - * Writes a {@code TAG_Empty} tag. - * - * @param tag the tag - */ - private void writeEndTagPayload(EndTag tag) { - /* empty */ - } - - private void writeIntArrayTagPayload(IntArrayTag tag) throws IOException { - int[] data = tag.getValue(); - os.writeInt(data.length); - for (int aData : data) { - os.writeInt(aData); - } - } - - private void writeLongArrayTagPayload(LongArrayTag tag) throws IOException { - long[] data = tag.getValue(); - os.writeInt(data.length); - for (long aData : data) { - os.writeLong(aData); - } + BinaryTagIO.writer().writeNamed( + Maps.immutableEntry(name, (CompoundBinaryTag) tag.asBinaryTag()), + (DataOutput) this.os + ); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTUtils.java b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTUtils.java index c6e53e598c..46a11ee202 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTUtils.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTUtils.java @@ -29,7 +29,9 @@ /** * A class which contains NBT-related utility methods. * + * @deprecated JNBT is being removed for adventure-nbt in WorldEdit 8. */ +@Deprecated public final class NBTUtils { /** @@ -72,7 +74,7 @@ public static String getTypeName(Class clazz) { } else if (clazz.equals(LongArrayTag.class)) { return "TAG_Long_Array"; } else { - throw new IllegalArgumentException("Invalid tag classs (" + throw new IllegalArgumentException("Invalid tag class (" + clazz.getName() + ")."); } } @@ -85,36 +87,7 @@ public static String getTypeName(Class clazz) { * @throws IllegalArgumentException if the tag class is invalid. */ public static int getTypeCode(Class clazz) { - if (clazz.equals(ByteArrayTag.class)) { - return NBTConstants.TYPE_BYTE_ARRAY; - } else if (clazz.equals(ByteTag.class)) { - return NBTConstants.TYPE_BYTE; - } else if (clazz.equals(CompoundTag.class)) { - return NBTConstants.TYPE_COMPOUND; - } else if (clazz.equals(DoubleTag.class)) { - return NBTConstants.TYPE_DOUBLE; - } else if (clazz.equals(EndTag.class)) { - return NBTConstants.TYPE_END; - } else if (clazz.equals(FloatTag.class)) { - return NBTConstants.TYPE_FLOAT; - } else if (clazz.equals(IntTag.class)) { - return NBTConstants.TYPE_INT; - } else if (clazz.equals(ListTag.class)) { - return NBTConstants.TYPE_LIST; - } else if (clazz.equals(LongTag.class)) { - return NBTConstants.TYPE_LONG; - } else if (clazz.equals(ShortTag.class)) { - return NBTConstants.TYPE_SHORT; - } else if (clazz.equals(StringTag.class)) { - return NBTConstants.TYPE_STRING; - } else if (clazz.equals(IntArrayTag.class)) { - return NBTConstants.TYPE_INT_ARRAY; - } else if (clazz.equals(LongArrayTag.class)) { - return NBTConstants.TYPE_LONG_ARRAY; - } else { - throw new IllegalArgumentException("Invalid tag classs (" - + clazz.getName() + ")."); - } + return AdventureNBTConverter.getAdventureType(clazz).id(); } /** diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/NamedTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/NamedTag.java index c7089e3f48..80742783c8 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/NamedTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/NamedTag.java @@ -23,7 +23,10 @@ /** * A tag that has a name. + * + * @deprecated JNBT is being removed for adventure-nbt in WorldEdit 8. */ +@Deprecated public class NamedTag { private final String name; diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/ShortTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/ShortTag.java index f8224ab0ed..b045f231b0 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/ShortTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/ShortTag.java @@ -19,12 +19,17 @@ package com.sk89q.jnbt; +import com.sk89q.worldedit.util.nbt.ShortBinaryTag; + /** * The {@code TAG_Short} tag. + * + * @deprecated Use {@link ShortBinaryTag}. */ +@Deprecated public final class ShortTag extends Tag { - private final short value; + private final ShortBinaryTag innerTag; /** * Creates the tag with an empty name. @@ -33,17 +38,22 @@ public final class ShortTag extends Tag { */ public ShortTag(short value) { super(); - this.value = value; + this.innerTag = ShortBinaryTag.of(value); + } + + public ShortTag(ShortBinaryTag adventureTag) { + super(); + this.innerTag = adventureTag; } @Override - public Short getValue() { - return value; + public ShortBinaryTag asBinaryTag() { + return this.innerTag; } @Override - public String toString() { - return "TAG_Short(" + value + ")"; + public Short getValue() { + return innerTag.value(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/StringTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/StringTag.java index 3727f8d8e1..7c5bb3aa52 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/StringTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/StringTag.java @@ -19,14 +19,19 @@ package com.sk89q.jnbt; +import com.sk89q.worldedit.util.nbt.StringBinaryTag; + import static com.google.common.base.Preconditions.checkNotNull; /** * The {@code TAG_String} tag. + * + * @deprecated Use {@link StringBinaryTag}. */ +@Deprecated public final class StringTag extends Tag { - private final String value; + private final StringBinaryTag innerTag; /** * Creates the tag with an empty name. @@ -36,17 +41,22 @@ public final class StringTag extends Tag { public StringTag(String value) { super(); checkNotNull(value); - this.value = value; + this.innerTag = StringBinaryTag.of(value); + } + + public StringTag(StringBinaryTag adventureTag) { + super(); + this.innerTag = adventureTag; } @Override - public String getValue() { - return value; + public StringBinaryTag asBinaryTag() { + return this.innerTag; } @Override - public String toString() { - return "TAG_String(" + value + ")"; + public String getValue() { + return innerTag.value(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/Tag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/Tag.java index a94b3b3bb3..5a3bd1d484 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/Tag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/Tag.java @@ -19,10 +19,15 @@ package com.sk89q.jnbt; +import com.sk89q.worldedit.util.nbt.BinaryTagLike; + /** * Represents a NBT tag. + * + * @deprecated JNBT is being removed for adventure-nbt in WorldEdit 8. */ -public abstract class Tag { +@Deprecated +public abstract class Tag implements BinaryTagLike { /** * Gets the value of this tag. @@ -31,4 +36,8 @@ public abstract class Tag { */ public abstract Object getValue(); + @Override + public String toString() { + return asBinaryTag().toString(); + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index 837db9498c..aeda2d98d7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -23,8 +23,6 @@ import com.sk89q.jchronic.Options; import com.sk89q.jchronic.utils.Span; import com.sk89q.jchronic.utils.Time; -import com.sk89q.jnbt.IntTag; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.command.tool.BlockTool; import com.sk89q.worldedit.command.tool.BrushTool; import com.sk89q.worldedit.command.tool.InvalidToolBindException; @@ -50,7 +48,9 @@ import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.util.SideEffectSet; +import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; @@ -804,13 +804,15 @@ public void updateServerCUI(Actor actor) { BaseBlock block = ServerCUIHandler.createStructureBlock(player); if (block != null) { - // If it's null, we don't need to do anything. The old was already removed. - Map tags = block.getNbtData().getValue(); + CompoundBinaryTag tags = Objects.requireNonNull( + block.getNbt(), "createStructureBlock should return nbt" + ); BlockVector3 tempCuiTemporaryBlock = BlockVector3.at( - ((IntTag) tags.get("x")).getValue(), - ((IntTag) tags.get("y")).getValue(), - ((IntTag) tags.get("z")).getValue() + tags.getInt("x"), + tags.getInt("y"), + tags.getInt("z") ); + // If it's null, we don't need to do anything. The old was already removed. if (cuiTemporaryBlock != null && !tempCuiTemporaryBlock.equals(cuiTemporaryBlock)) { // Update the existing block if it's the same location player.sendFakeBlock(cuiTemporaryBlock, null); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseItem.java b/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseItem.java index a365bc4b14..16b979725b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseItem.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseItem.java @@ -20,9 +20,14 @@ package com.sk89q.worldedit.blocks; import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; +import com.sk89q.worldedit.util.nbt.TagStringIO; import com.sk89q.worldedit.world.NbtValued; import com.sk89q.worldedit.world.item.ItemType; +import java.io.IOException; import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkNotNull; @@ -37,7 +42,7 @@ public class BaseItem implements NbtValued { private ItemType itemType; @Nullable - private CompoundTag nbtData; + private LazyReference nbtData; /** * Construct the object. @@ -49,13 +54,24 @@ public BaseItem(ItemType itemType) { this.itemType = itemType; } + /** + * Construct the object. + * + * @param itemType Type of the item + * @param nbtData NBT Compound tag + */ + @Deprecated + public BaseItem(ItemType itemType, @Nullable CompoundTag nbtData) { + this(itemType, nbtData == null ? null : LazyReference.from(nbtData::asBinaryTag)); + } + /** * Construct the object. * * @param itemType Type of the item * @param tag NBT Compound tag */ - public BaseItem(ItemType itemType, @Nullable CompoundTag tag) { + public BaseItem(ItemType itemType, @Nullable LazyReference tag) { checkNotNull(itemType); this.itemType = itemType; this.nbtData = tag; @@ -79,19 +95,29 @@ public void setType(ItemType itemType) { this.itemType = itemType; } - @Override - public boolean hasNbtData() { - return this.nbtData != null; - } - @Nullable @Override - public CompoundTag getNbtData() { + public LazyReference getNbtReference() { return this.nbtData; } @Override - public void setNbtData(@Nullable CompoundTag nbtData) { + public void setNbtReference(@Nullable LazyReference nbtData) { this.nbtData = nbtData; } + + @Override + public String toString() { + String nbtString = ""; + LazyReference nbtData = this.nbtData; + if (nbtData != null) { + try { + nbtString = TagStringIO.get().asString(nbtData.getValue()); + } catch (IOException e) { + WorldEdit.logger.error("Failed to serialize NBT of Item", e); + } + } + + return getType().getId() + nbtString; + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseItemStack.java b/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseItemStack.java index 10655963a0..8d9e4ab07d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseItemStack.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseItemStack.java @@ -22,7 +22,9 @@ import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.platform.Capability; +import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.item.ItemType; /** @@ -60,12 +62,26 @@ public BaseItemStack(ItemType itemType, int amount) { * @param id The item type * @param tag Tag value * @param amount amount in the stack + * @deprecated Use {@link #BaseItemStack(ItemType, LazyReference, int)} */ + @Deprecated public BaseItemStack(ItemType id, CompoundTag tag, int amount) { super(id, tag); this.amount = amount; } + /** + * Construct the object. + * + * @param id The item type + * @param tag Tag value + * @param amount amount in the stack + */ + public BaseItemStack(ItemType id, LazyReference tag, int amount) { + super(id, tag); + this.amount = amount; + } + /** * Get the number of items in the stack. * diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/entity/BaseEntity.java b/worldedit-core/src/main/java/com/sk89q/worldedit/entity/BaseEntity.java index 393023df81..ae6d856686 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/entity/BaseEntity.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/entity/BaseEntity.java @@ -20,6 +20,8 @@ package com.sk89q.worldedit.entity; import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.NbtValued; import com.sk89q.worldedit.world.entity.EntityType; @@ -43,19 +45,33 @@ public class BaseEntity implements NbtValued { private final EntityType type; - private CompoundTag nbtData; + @Nullable + private LazyReference nbtData; /** * Create a new base entity. * * @param type the entity type * @param nbtData NBT data + * @deprecated Use {@link BaseEntity#BaseEntity(EntityType, LazyReference)} */ + @Deprecated public BaseEntity(EntityType type, CompoundTag nbtData) { this(type); setNbtData(nbtData); } + /** + * Create a new base entity. + * + * @param type the entity type + * @param nbtData NBT data + */ + public BaseEntity(EntityType type, LazyReference nbtData) { + this(type); + setNbtReference(nbtData); + } + /** * Create a new base entity with no NBT data. * @@ -73,22 +89,17 @@ public BaseEntity(EntityType type) { public BaseEntity(BaseEntity other) { checkNotNull(other); this.type = other.getType(); - setNbtData(other.getNbtData()); - } - - @Override - public boolean hasNbtData() { - return true; + setNbtReference(other.getNbtReference()); } @Nullable @Override - public CompoundTag getNbtData() { + public LazyReference getNbtReference() { return nbtData; } @Override - public void setNbtData(@Nullable CompoundTag nbtData) { + public void setNbtReference(@Nullable LazyReference nbtData) { this.nbtData = nbtData; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultItemParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultItemParser.java index 186fff5560..fb7616394f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultItemParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultItemParser.java @@ -30,12 +30,16 @@ import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.internal.registry.InputParser; import com.sk89q.worldedit.util.HandSide; +import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; +import com.sk89q.worldedit.util.nbt.TagStringIO; import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.registry.LegacyMapper; +import java.io.IOException; import java.util.Locale; import java.util.stream.Stream; @@ -52,44 +56,87 @@ public Stream getSuggestions(String input) { @Override public BaseItem parseFromInput(String input, ParserContext context) throws InputParseException { + ItemType itemType; + CompoundBinaryTag itemNbtData = null; + BaseItem item = null; + // Legacy matcher if (context.isTryingLegacy()) { try { String[] split = input.split(":"); - ItemType type; if (split.length == 0) { throw new InputParseException(TranslatableComponent.of("worldedit.error.parser.invalid-colon")); } else if (split.length == 1) { - type = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(split[0])); + itemType = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(split[0])); } else { - type = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(split[0]), Integer.parseInt(split[1])); + itemType = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(split[0]), Integer.parseInt(split[1])); } - if (type != null) { - item = new BaseItem(type); + if (itemType != null) { + item = new BaseItem(itemType); } } catch (NumberFormatException ignored) { } } - if ("hand".equalsIgnoreCase(input)) { - return getItemInHand(context.requireActor(), HandSide.MAIN_HAND); - } else if ("offhand".equalsIgnoreCase(input)) { - return getItemInHand(context.requireActor(), HandSide.OFF_HAND); - } - if (item == null) { - ItemType type = ItemTypes.get(input.toLowerCase(Locale.ROOT)); - if (type != null) { - item = new BaseItem(type); + String typeString; + String nbtString = null; + int nbtStart = input.indexOf('{'); + + if (nbtStart == -1) { + typeString = input; + } else { + typeString = input.substring(0, nbtStart); + if (nbtStart + 1 >= input.length()) { + throw new InputParseException(TranslatableComponent.of("worldedit.error.parser.hanging-lbracket", TextComponent.of(nbtStart))); + } + int stateEnd = input.lastIndexOf('}'); + if (stateEnd < 0) { + throw new InputParseException(TranslatableComponent.of("worldedit.error.parser.missing-rbracket")); + } + nbtString = input.substring(nbtStart); } - } - if (item == null) { - throw new NoMatchException(TranslatableComponent.of("worldedit.error.no-match", TextComponent.of(input))); - } else { - return item; + if ("hand".equalsIgnoreCase(typeString)) { + BaseItemStack heldItem = getItemInHand(context.requireActor(), HandSide.MAIN_HAND); + itemType = heldItem.getType(); + itemNbtData = heldItem.getNbt(); + } else if ("offhand".equalsIgnoreCase(typeString)) { + BaseItemStack heldItem = getItemInHand(context.requireActor(), HandSide.OFF_HAND); + itemType = heldItem.getType(); + itemNbtData = heldItem.getNbt(); + } else { + itemType = ItemTypes.get(typeString.toLowerCase(Locale.ROOT)); + } + + if (itemType == null) { + throw new NoMatchException(TranslatableComponent.of("worldedit.error.unknown-item", TextComponent.of(input))); + } + + if (nbtString != null) { + try { + CompoundBinaryTag otherTag = TagStringIO.get().asCompound(nbtString); + if (itemNbtData == null) { + itemNbtData = otherTag; + } else { + for (String key : otherTag.keySet()) { + itemNbtData.put(key, otherTag.get(key)); + } + } + } catch (IOException e) { + throw new NoMatchException(TranslatableComponent.of( + "worldedit.error.invalid-nbt", + TextComponent.of(input), + TextComponent.of(e.getMessage()) + )); + } + } + + item = new BaseItem(itemType, itemNbtData == null ? null : LazyReference.computed(itemNbtData)); } + + return item; } private BaseItemStack getItemInHand(Actor actor, HandSide handSide) throws InputParseException { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SurvivalModeExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SurvivalModeExtent.java index 2cb6b02c82..21c287cd79 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SurvivalModeExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SurvivalModeExtent.java @@ -23,6 +23,7 @@ import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockStateHolder; @@ -95,7 +96,7 @@ public > boolean setBlock(BlockVector3 location, B } else { // Can't be an inlined check due to inconsistent generic return type if (stripNbt) { - return super.setBlock(location, block.toBaseBlock(null)); + return super.setBlock(location, block.toBaseBlock((CompoundBinaryTag) null)); } else { return super.setBlock(location, block); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/ExtentBlockCopy.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/ExtentBlockCopy.java index 7f56aed565..cfa2445447 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/ExtentBlockCopy.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/ExtentBlockCopy.java @@ -19,8 +19,6 @@ package com.sk89q.worldedit.function.block; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.CompoundTagBuilder; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.RegionFunction; @@ -30,6 +28,9 @@ import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.Direction.Flag; +import com.sk89q.worldedit.util.nbt.BinaryTag; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; +import com.sk89q.worldedit.util.nbt.NumberBinaryTag; import com.sk89q.worldedit.world.block.BaseBlock; import static com.google.common.base.Preconditions.checkNotNull; @@ -87,12 +88,13 @@ public boolean apply(BlockVector3 position) throws WorldEditException { * @return a new state or the existing one */ private BaseBlock transformNbtData(BaseBlock state) { - CompoundTag tag = state.getNbtData(); + CompoundBinaryTag tag = state.getNbt(); if (tag != null) { // Handle blocks which store their rotation in NBT - if (tag.containsKey("Rot")) { - int rot = tag.asInt("Rot"); + BinaryTag rotTag = tag.get("Rot"); + if (rotTag instanceof NumberBinaryTag) { + int rot = ((NumberBinaryTag) rotTag).intValue(); Direction direction = MCDirections.fromRotation(rot); @@ -101,11 +103,9 @@ private BaseBlock transformNbtData(BaseBlock state) { Direction newDirection = Direction.findClosest(vector, Flag.CARDINAL | Flag.ORDINAL | Flag.SECONDARY_ORDINAL); if (newDirection != null) { - CompoundTagBuilder builder = tag.createBuilder(); - - builder.putByte("Rot", (byte) MCDirections.toRotation(newDirection)); - - return state.toBaseBlock(builder.build()); + return state.toBaseBlock( + tag.putByte("Rot", (byte) MCDirections.toRotation(newDirection)) + ); } } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/ServerCUIHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/ServerCUIHandler.java index 591dcca399..c979bf0dcc 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/ServerCUIHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/ServerCUIHandler.java @@ -19,11 +19,6 @@ package com.sk89q.worldedit.internal.cui; -import com.sk89q.jnbt.ByteTag; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.IntTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; @@ -33,11 +28,10 @@ import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockTypes; -import java.util.HashMap; -import java.util.Map; import javax.annotation.Nullable; /** @@ -126,7 +120,7 @@ public static BaseBlock createStructureBlock(Player player) { int z = (int) (location.getZ() - (xz * Math.cos(Math.toRadians(rotX))) * 12); int y = Math.max(0, Math.min(Math.min(255, posY + 32), posY + 3)); - Map structureTag = new HashMap<>(); + CompoundBinaryTag.Builder structureTag = CompoundBinaryTag.builder(); posX -= x; posY -= y; @@ -137,25 +131,25 @@ public static BaseBlock createStructureBlock(Player player) { return null; } - structureTag.put("name", new StringTag("worldedit:" + player.getName())); - structureTag.put("author", new StringTag(player.getName())); - structureTag.put("metadata", new StringTag("")); - structureTag.put("x", new IntTag(x)); - structureTag.put("y", new IntTag(y)); - structureTag.put("z", new IntTag(z)); - structureTag.put("posX", new IntTag(posX)); - structureTag.put("posY", new IntTag(posY)); - structureTag.put("posZ", new IntTag(posZ)); - structureTag.put("sizeX", new IntTag(width)); - structureTag.put("sizeY", new IntTag(height)); - structureTag.put("sizeZ", new IntTag(length)); - structureTag.put("rotation", new StringTag("NONE")); - structureTag.put("mirror", new StringTag("NONE")); - structureTag.put("mode", new StringTag("SAVE")); - structureTag.put("ignoreEntities", new ByteTag((byte) 1)); - structureTag.put("showboundingbox", new ByteTag((byte) 1)); - structureTag.put("id", new StringTag(BlockTypes.STRUCTURE_BLOCK.getId())); - - return BlockTypes.STRUCTURE_BLOCK.getDefaultState().toBaseBlock(new CompoundTag(structureTag)); + structureTag.putString("name", "worldedit:" + player.getName()); + structureTag.putString("author", player.getName()); + structureTag.putString("metadata", ""); + structureTag.putInt("x", x); + structureTag.putInt("y", y); + structureTag.putInt("z", z); + structureTag.putInt("posX", posX); + structureTag.putInt("posY", posY); + structureTag.putInt("posZ", posZ); + structureTag.putInt("sizeX", width); + structureTag.putInt("sizeY", height); + structureTag.putInt("sizeZ", length); + structureTag.putString("rotation", "NONE"); + structureTag.putString("mirror", "NONE"); + structureTag.putString("mode", "SAVE"); + structureTag.putByte("ignoreEntities", (byte) 1); + structureTag.putByte("showboundingbox", (byte) 1); + structureTag.putString("id", BlockTypes.STRUCTURE_BLOCK.getId()); + + return BlockTypes.STRUCTURE_BLOCK.getDefaultState().toBaseBlock(structureTag.build()); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/wna/WorldNativeAccess.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/wna/WorldNativeAccess.java index 042385c64b..ee91f9a644 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/wna/WorldNativeAccess.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/wna/WorldNativeAccess.java @@ -19,11 +19,14 @@ package com.sk89q.worldedit.internal.wna; -import com.sk89q.jnbt.CompoundTag; +import com.google.common.collect.ImmutableMap; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; +import com.sk89q.worldedit.util.nbt.IntBinaryTag; +import com.sk89q.worldedit.util.nbt.StringBinaryTag; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; @@ -66,14 +69,15 @@ default > boolean setBlock(BlockVector3 position, if (successful || old == newState) { if (block instanceof BaseBlock) { BaseBlock baseBlock = (BaseBlock) block; - CompoundTag tag = baseBlock.getNbtData(); + CompoundBinaryTag tag = baseBlock.getNbt(); if (tag != null) { - tag = tag.createBuilder() - .putString("id", baseBlock.getNbtId()) - .putInt("x", position.getX()) - .putInt("y", position.getY()) - .putInt("z", position.getZ()) - .build(); + tag = tag.put(ImmutableMap.of( + "id", StringBinaryTag.of(baseBlock.getNbtId()), + "x", IntBinaryTag.of(position.getX()), + "y", IntBinaryTag.of(position.getY()), + "z", IntBinaryTag.of(position.getZ()) + )); + // update if TE changed as well successful = updateTileEntity(pos, tag); } @@ -136,7 +140,7 @@ default void setCurrentSideEffectSet(SideEffectSet sideEffectSet) { void updateLightingForBlock(NP position); - boolean updateTileEntity(NP position, CompoundTag tag); + boolean updateTileEntity(NP position, CompoundBinaryTag tag); void notifyBlockUpdate(NP position, NBS oldState, NBS newState); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/collection/Int2BaseBlockMap.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/collection/Int2BaseBlockMap.java index ee571c6436..e3203d28cc 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/collection/Int2BaseBlockMap.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/collection/Int2BaseBlockMap.java @@ -50,7 +50,7 @@ class Int2BaseBlockMap extends AbstractInt2ObjectMap { * @return the internal ID, or {@link BlockStateIdAccess#invalidId()} if not useful */ private static int optimizedInternalId(BaseBlock block) { - if (block.hasNbtData()) { + if (block.getNbtReference() != null) { return BlockStateIdAccess.invalidId(); } return BlockStateIdAccess.getBlockStateId(block.toImmutableState()); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/concurrency/LazyReference.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/concurrency/LazyReference.java index f755b3fa02..8463cac91e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/concurrency/LazyReference.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/concurrency/LazyReference.java @@ -32,6 +32,17 @@ public static LazyReference from(Supplier valueComputation) { return new LazyReference<>(valueComputation); } + /** + * Pre-computed reference, for setting a lazy reference field with a known value. + * + * @param value the value of the reference + * @param the type of the value + * @return the new reference + */ + public static LazyReference computed(T value) { + return new LazyReference<>(value); + } + // Memory saving technique: hold the computation info in the same reference field that we'll // put the value into, so the memory possibly retained by those parts is GC'able as soon as // it's no longer needed. @@ -51,6 +62,10 @@ private LazyReference(Supplier valueComputation) { this.value = new RefInfo<>(valueComputation); } + private LazyReference(T value) { + this.value = value; + } + // casts are safe, value is either RefInfo or T @SuppressWarnings("unchecked") public T getValue() { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/nbt/NbtUtils.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/nbt/NbtUtils.java new file mode 100644 index 0000000000..2c032e8bce --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/nbt/NbtUtils.java @@ -0,0 +1,50 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.util.nbt; + +import com.sk89q.worldedit.world.storage.InvalidFormatException; + +public class NbtUtils { + + /** + * Get child tag of a NBT structure. + * + * @param tag the tag to read from + * @param key the key to look for + * @param expected the expected NBT class type + * @return child tag + * @throws InvalidFormatException if the format of the items is invalid + */ + public static T getChildTag(CompoundBinaryTag tag, String key, BinaryTagType expected) throws InvalidFormatException { + BinaryTag childTag = tag.get(key); + if (childTag == null) { + throw new InvalidFormatException("Missing a \"" + key + "\" tag"); + } + + if (childTag.type().id() != expected.id()) { + throw new InvalidFormatException(key + " tag is not of tag type " + expected.toString()); + } + // SAFETY: same binary tag type checked above + @SuppressWarnings("unchecked") + T childTagCast = (T) childTag; + return childTagCast; + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/NbtValued.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/NbtValued.java index 86ea9b454b..198a786308 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/NbtValued.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/NbtValued.java @@ -20,6 +20,10 @@ package com.sk89q.worldedit.world; import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.internal.util.DeprecationUtil; +import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import javax.annotation.Nullable; @@ -35,8 +39,12 @@ public interface NbtValued { * must not return null if this method returns true. * * @return true if there is NBT data + * @deprecated See {@link #getNbt()} */ - boolean hasNbtData(); + @Deprecated + default boolean hasNbtData() { + return getNbt() != null; + } /** * Get the object's NBT data (tile entity data). The returned tag, if @@ -49,15 +57,87 @@ public interface NbtValued { * not return null.

* * @return compound tag, or null + * @deprecated See {@link #getNbt()} */ + @Deprecated @Nullable - CompoundTag getNbtData(); + default CompoundTag getNbtData() { + CompoundBinaryTag tag = getNbt(); + return tag == null ? null : new CompoundTag(tag); + } /** * Set the object's NBT data (tile entity data). * * @param nbtData NBT data, or null if no data + * @deprecated See {@link #setNbtReference(LazyReference)} */ - void setNbtData(@Nullable CompoundTag nbtData); + @Deprecated + default void setNbtData(@Nullable CompoundTag nbtData) { + setNbtReference(nbtData == null ? null : LazyReference.from(nbtData::asBinaryTag)); + } + + /** + * Get the object's NBT data (tile entity data). + * + *

+ * This only needs to be used if you don't want to immediately resolve the data. + * Otherwise, you probably want {@link #getNbt()}. + *

+ * + * @return compound tag, or null + * @apiNote This must be overridden by new subclasses. See {@link NonAbstractForCompatibility} + * for details + */ + @NonAbstractForCompatibility( + delegateName = "getNbtData", + delegateParams = { } + ) + @Nullable + default LazyReference getNbtReference() { + DeprecationUtil.checkDelegatingOverride(getClass()); + + CompoundTag nbtData = getNbtData(); + return nbtData == null ? null : LazyReference.from(nbtData::asBinaryTag); + } + + /** + * Get the object's NBT data (tile entity data). + * + * @return compound tag, or null + * @apiNote This must be overridden by new subclasses. See {@link NonAbstractForCompatibility} + * for details + */ + @Nullable + default CompoundBinaryTag getNbt() { + LazyReference ref = getNbtReference(); + return ref == null ? null : ref.getValue(); + } + + /** + * Set the object's NBT data (tile entity data). + * + * @param nbtData NBT data, or null if no data + * @apiNote This must be overridden by new subclasses. See {@link NonAbstractForCompatibility} + * for details + */ + @NonAbstractForCompatibility( + delegateName = "setNbtData", + delegateParams = { CompoundTag.class } + ) + default void setNbtReference(@Nullable LazyReference nbtData) { + DeprecationUtil.checkDelegatingOverride(getClass()); + + setNbtData(nbtData == null ? null : new CompoundTag(nbtData.getValue())); + } + + /** + * Set the object's NBT data (tile entity data). + * + * @param nbtData NBT data, or null if no data + */ + default void setNbt(@Nullable CompoundBinaryTag nbtData) { + setNbtReference(nbtData == null ? null : LazyReference.computed(nbtData)); + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java index a7d50f6b1c..f7f79a66e5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java @@ -20,11 +20,14 @@ package com.sk89q.worldedit.world.block; import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.blocks.TileEntityBlock; import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; +import com.sk89q.worldedit.util.nbt.TagStringIO; +import java.io.IOException; import java.util.Map; import java.util.Objects; import javax.annotation.Nullable; @@ -44,7 +47,7 @@ public class BaseBlock implements BlockStateHolder, TileEntityBlock { private final BlockState blockState; @Nullable - private final CompoundTag nbtData; + private final LazyReference nbtData; /** * Construct a block with a state. @@ -62,7 +65,19 @@ protected BaseBlock(BlockState blockState) { * @param state The block state * @param nbtData NBT data, which must be provided */ + @Deprecated protected BaseBlock(BlockState state, CompoundTag nbtData) { + this(state, LazyReference.from(checkNotNull(nbtData)::asBinaryTag)); + } + + + /** + * Construct a block with the given ID, data value and NBT data structure. + * + * @param state The block state + * @param nbtData NBT data, which must be provided + */ + protected BaseBlock(BlockState state, LazyReference nbtData) { checkNotNull(nbtData); this.blockState = state; this.nbtData = nbtData; @@ -85,7 +100,7 @@ public BlockType getBlockType() { @Override public BaseBlock with(Property property, V value) { - return this.blockState.with(property, value).toBaseBlock(getNbtData()); + return this.blockState.with(property, value).toBaseBlock(getNbtReference()); } /** @@ -99,33 +114,23 @@ public V getState(Property property) { return this.blockState.getState(property); } - @Override - public boolean hasNbtData() { - return getNbtData() != null; - } - @Override public String getNbtId() { - CompoundTag nbtData = getNbtData(); + LazyReference nbtData = this.nbtData; if (nbtData == null) { return ""; } - Tag idTag = nbtData.getValue().get("id"); - if (idTag instanceof StringTag) { - return ((StringTag) idTag).getValue(); - } else { - return ""; - } + return nbtData.getValue().getString("id"); } @Nullable @Override - public CompoundTag getNbtData() { + public LazyReference getNbtReference() { return this.nbtData; } @Override - public void setNbtData(@Nullable CompoundTag nbtData) { + public void setNbtReference(@Nullable LazyReference nbtData) { throw new UnsupportedOperationException("This class is immutable."); } @@ -135,7 +140,7 @@ public void setNbtData(@Nullable CompoundTag nbtData) { @Override public boolean equals(Object o) { if (!(o instanceof BaseBlock)) { - if (!hasNbtData() && o instanceof BlockStateHolder) { + if (nbtData == null && o instanceof BlockStateHolder) { return Objects.equals(toImmutableState(), ((BlockStateHolder) o).toImmutableState()); } return false; @@ -143,7 +148,7 @@ public boolean equals(Object o) { final BaseBlock otherBlock = (BaseBlock) o; - return this.blockState.equalsFuzzy(otherBlock.blockState) && Objects.equals(getNbtData(), otherBlock.getNbtData()); + return this.blockState.equalsFuzzy(otherBlock.blockState) && Objects.equals(getNbt(), otherBlock.getNbt()); } /** @@ -168,7 +173,7 @@ public BaseBlock toBaseBlock() { } @Override - public BaseBlock toBaseBlock(CompoundTag compoundTag) { + public BaseBlock toBaseBlock(LazyReference compoundTag) { if (compoundTag == null) { return this.blockState.toBaseBlock(); } else if (compoundTag == this.nbtData) { @@ -181,16 +186,26 @@ public BaseBlock toBaseBlock(CompoundTag compoundTag) { @Override public int hashCode() { int ret = toImmutableState().hashCode() << 3; - if (hasNbtData()) { - ret += getNbtData().hashCode(); + CompoundBinaryTag nbtData = getNbt(); + if (nbtData != null) { + ret += nbtData.hashCode(); } return ret; } @Override public String toString() { - // TODO use a json serializer for the NBT data - return blockState.getAsString() + (hasNbtData() ? "{hasNbt}" : ""); + String nbtString = ""; + CompoundBinaryTag nbtData = getNbt(); + if (nbtData != null) { + try { + nbtString = TagStringIO.get().asString(nbtData); + } catch (IOException e) { + WorldEdit.logger.error("Failed to serialize NBT of Block", e); + } + } + + return blockState.getAsString() + nbtString; } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java index fdbdd92d42..61ece44397 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java @@ -24,10 +24,11 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Table; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import java.util.Collections; import java.util.Comparator; @@ -211,7 +212,7 @@ public BaseBlock toBaseBlock() { } @Override - public BaseBlock toBaseBlock(CompoundTag compoundTag) { + public BaseBlock toBaseBlock(LazyReference compoundTag) { if (compoundTag == null) { return toBaseBlock(); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateHolder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateHolder.java index 93aaa55ed4..e45544101f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateHolder.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateHolder.java @@ -21,8 +21,12 @@ import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.internal.util.DeprecationUtil; +import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import java.util.Locale; import java.util.Map; @@ -88,8 +92,42 @@ public interface BlockStateHolder> extends Pattern * * @param compoundTag The NBT Data to apply * @return The BaseBlock + * @deprecated Use {@link BlockStateHolder#toBaseBlock(LazyReference)}. */ - BaseBlock toBaseBlock(CompoundTag compoundTag); + @Deprecated + default BaseBlock toBaseBlock(CompoundTag compoundTag) { + return toBaseBlock(compoundTag == null ? null : LazyReference.from(compoundTag::asBinaryTag)); + } + + /** + * Gets a {@link BaseBlock} from this BlockStateHolder. + * + * @param compoundTag The NBT Data to apply + * @return The BaseBlock + * @apiNote This must be overridden by new subclasses. See {@link NonAbstractForCompatibility} + * for details + */ + @NonAbstractForCompatibility( + delegateName = "toBaseBlock", + delegateParams = { CompoundTag.class } + ) + default BaseBlock toBaseBlock(LazyReference compoundTag) { + DeprecationUtil.checkDelegatingOverride(getClass()); + + return toBaseBlock(compoundTag == null ? null : new CompoundTag(compoundTag.getValue())); + } + + /** + * Gets a {@link BaseBlock} from this BlockStateHolder. + * + * @param compoundTag The NBT Data to apply + * @return The BaseBlock + */ + default BaseBlock toBaseBlock(CompoundBinaryTag compoundTag) { + DeprecationUtil.checkDelegatingOverride(getClass()); + + return toBaseBlock(compoundTag == null ? null : LazyReference.computed(compoundTag)); + } @Override default BaseBlock applyBlock(BlockVector3 position) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk.java index dd8e407b94..f45f0eb91d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk.java @@ -19,15 +19,15 @@ package com.sk89q.worldedit.world.chunk; -import com.sk89q.jnbt.ByteArrayTag; -import com.sk89q.jnbt.ByteTag; import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.IntTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.NBTUtils; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.util.nbt.BinaryTag; +import com.sk89q.worldedit.util.nbt.BinaryTagTypes; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; +import com.sk89q.worldedit.util.nbt.IntBinaryTag; +import com.sk89q.worldedit.util.nbt.ListBinaryTag; +import com.sk89q.worldedit.util.nbt.NbtUtils; import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; @@ -36,63 +36,74 @@ import com.sk89q.worldedit.world.storage.InvalidFormatException; import java.util.HashMap; -import java.util.List; import java.util.Map; import javax.annotation.Nullable; public class AnvilChunk implements Chunk { - private final CompoundTag rootTag; + private final CompoundBinaryTag rootTag; private final byte[][] blocks; private final byte[][] blocksAdd; private final byte[][] data; private final int rootX; private final int rootZ; - private Map> tileEntities; + private Map tileEntities; + /** * Construct the chunk with a compound tag. * * @param tag the tag to read * @throws DataException on a data error + * @deprecated Use {@link #AnvilChunk(CompoundBinaryTag)} */ public AnvilChunk(CompoundTag tag) throws DataException { + this(tag.asBinaryTag()); + } + + /** + * Construct the chunk with a compound tag. + * + * @param tag the tag to read + * @throws DataException on a data error + */ + public AnvilChunk(CompoundBinaryTag tag) throws DataException { rootTag = tag; - rootX = NBTUtils.getChildTag(rootTag.getValue(), "xPos", IntTag.class).getValue(); - rootZ = NBTUtils.getChildTag(rootTag.getValue(), "zPos", IntTag.class).getValue(); + rootX = NbtUtils.getChildTag(rootTag, "xPos", BinaryTagTypes.INT).value(); + rootZ = NbtUtils.getChildTag(rootTag, "zPos", BinaryTagTypes.INT).value(); blocks = new byte[16][16 * 16 * 16]; blocksAdd = new byte[16][16 * 16 * 8]; data = new byte[16][16 * 16 * 8]; - List sections = NBTUtils.getChildTag(rootTag.getValue(), "Sections", ListTag.class).getValue(); + ListBinaryTag sections = NbtUtils.getChildTag(rootTag, "Sections", BinaryTagTypes.LIST); - for (Tag rawSectionTag : sections) { - if (!(rawSectionTag instanceof CompoundTag)) { + for (BinaryTag rawSectionTag : sections) { + if (!(rawSectionTag instanceof CompoundBinaryTag)) { continue; } - CompoundTag sectionTag = (CompoundTag) rawSectionTag; - if (!sectionTag.getValue().containsKey("Y")) { + CompoundBinaryTag sectionTag = (CompoundBinaryTag) rawSectionTag; + if (sectionTag.get("Y") == null) { continue; // Empty section. } - int y = NBTUtils.getChildTag(sectionTag.getValue(), "Y", ByteTag.class).getValue(); + int y = NbtUtils.getChildTag(sectionTag, "Y", BinaryTagTypes.BYTE).value(); if (y < 0 || y >= 16) { continue; } - blocks[y] = NBTUtils.getChildTag(sectionTag.getValue(), - "Blocks", ByteArrayTag.class).getValue(); - data[y] = NBTUtils.getChildTag(sectionTag.getValue(), "Data", - ByteArrayTag.class).getValue(); + blocks[y] = NbtUtils.getChildTag(sectionTag, + "Blocks", BinaryTagTypes.BYTE_ARRAY).value(); + data[y] = NbtUtils.getChildTag(sectionTag, "Data", + BinaryTagTypes.BYTE_ARRAY).value(); // 4096 ID block support - if (sectionTag.getValue().containsKey("Add")) { - blocksAdd[y] = NBTUtils.getChildTag(sectionTag.getValue(), - "Add", ByteArrayTag.class).getValue(); + if (sectionTag.get("Add") != null) { + blocksAdd[y] = NbtUtils.getChildTag(sectionTag, + "Add", BinaryTagTypes.BYTE_ARRAY).value(); } } @@ -179,50 +190,49 @@ private int getBlockData(BlockVector3 position) throws DataException { * Used to load the tile entities. */ private void populateTileEntities() throws DataException { - List tags = NBTUtils.getChildTag(rootTag.getValue(), - "TileEntities", ListTag.class).getValue(); + ListBinaryTag tags = NbtUtils.getChildTag(rootTag, "TileEntities", BinaryTagTypes.LIST); tileEntities = new HashMap<>(); - for (Tag tag : tags) { - if (!(tag instanceof CompoundTag)) { + for (BinaryTag tag : tags) { + if (!(tag instanceof CompoundBinaryTag)) { throw new InvalidFormatException("CompoundTag expected in TileEntities"); } - CompoundTag t = (CompoundTag) tag; + CompoundBinaryTag t = (CompoundBinaryTag) tag; int x = 0; int y = 0; int z = 0; - Map values = new HashMap<>(); + CompoundBinaryTag.Builder values = CompoundBinaryTag.builder(); - for (Map.Entry entry : t.getValue().entrySet()) { - switch (entry.getKey()) { + for (String key : t.keySet()) { + BinaryTag value = t.get(key); + switch (key) { case "x": - if (entry.getValue() instanceof IntTag) { - x = ((IntTag) entry.getValue()).getValue(); + if (value instanceof IntBinaryTag) { + x = ((IntBinaryTag) value).value(); } break; case "y": - if (entry.getValue() instanceof IntTag) { - y = ((IntTag) entry.getValue()).getValue(); + if (value instanceof IntBinaryTag) { + y = ((IntBinaryTag) value).value(); } break; case "z": - if (entry.getValue() instanceof IntTag) { - z = ((IntTag) entry.getValue()).getValue(); + if (value instanceof IntBinaryTag) { + z = ((IntBinaryTag) value).value(); } break; default: break; } - values.put(entry.getKey(), entry.getValue()); + values.put(key, value); } - BlockVector3 vec = BlockVector3.at(x, y, z); - tileEntities.put(vec, values); + tileEntities.put(vec, values.build()); } } @@ -236,17 +246,17 @@ private void populateTileEntities() throws DataException { * @throws DataException thrown if there is a data error */ @Nullable - private CompoundTag getBlockTileEntity(BlockVector3 position) throws DataException { + private CompoundBinaryTag getBlockTileEntity(BlockVector3 position) throws DataException { if (tileEntities == null) { populateTileEntities(); } - Map values = tileEntities.get(position); + CompoundBinaryTag values = tileEntities.get(position); if (values == null) { return null; } - return new CompoundTag(values); + return values; } @Override @@ -259,7 +269,7 @@ public BaseBlock getBlock(BlockVector3 position) throws DataException { WorldEdit.logger.warn("Unknown legacy block " + id + ":" + data + " found when loading legacy anvil chunk."); return BlockTypes.AIR.getDefaultState().toBaseBlock(); } - CompoundTag tileEntity = getBlockTileEntity(position); + CompoundBinaryTag tileEntity = getBlockTileEntity(position); if (tileEntity != null) { return state.toBaseBlock(tileEntity); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk13.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk13.java index 512649c45a..cb94791350 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk13.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk13.java @@ -19,15 +19,15 @@ package com.sk89q.worldedit.world.chunk; -import com.sk89q.jnbt.ByteTag; import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.IntTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.LongArrayTag; -import com.sk89q.jnbt.NBTUtils; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.util.nbt.BinaryTag; +import com.sk89q.worldedit.util.nbt.BinaryTagTypes; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; +import com.sk89q.worldedit.util.nbt.IntBinaryTag; +import com.sk89q.worldedit.util.nbt.ListBinaryTag; +import com.sk89q.worldedit.util.nbt.NbtUtils; import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; @@ -36,7 +36,6 @@ import com.sk89q.worldedit.world.storage.InvalidFormatException; import java.util.HashMap; -import java.util.List; import java.util.Map; import javax.annotation.Nullable; @@ -45,62 +44,75 @@ */ public class AnvilChunk13 implements Chunk { - private final CompoundTag rootTag; + private final CompoundBinaryTag rootTag; private final BlockState[][] blocks; private final int rootX; private final int rootZ; - private Map> tileEntities; + private Map tileEntities; + /** * Construct the chunk with a compound tag. * * @param tag the tag to read * @throws DataException on a data error + * @deprecated Use {@link #AnvilChunk13(CompoundBinaryTag)} */ + @Deprecated public AnvilChunk13(CompoundTag tag) throws DataException { + this(tag.asBinaryTag()); + } + + /** + * Construct the chunk with a compound tag. + * + * @param tag the tag to read + * @throws DataException on a data error + */ + public AnvilChunk13(CompoundBinaryTag tag) throws DataException { rootTag = tag; - rootX = NBTUtils.getChildTag(rootTag.getValue(), "xPos", IntTag.class).getValue(); - rootZ = NBTUtils.getChildTag(rootTag.getValue(), "zPos", IntTag.class).getValue(); + rootX = NbtUtils.getChildTag(rootTag, "xPos", BinaryTagTypes.INT).value(); + rootZ = NbtUtils.getChildTag(rootTag, "zPos", BinaryTagTypes.INT).value(); blocks = new BlockState[16][]; - List sections = NBTUtils.getChildTag(rootTag.getValue(), "Sections", ListTag.class).getValue(); + ListBinaryTag sections = NbtUtils.getChildTag(rootTag, "Sections", BinaryTagTypes.LIST); - for (Tag rawSectionTag : sections) { - if (!(rawSectionTag instanceof CompoundTag)) { + for (BinaryTag rawSectionTag : sections) { + if (!(rawSectionTag instanceof CompoundBinaryTag)) { continue; } - CompoundTag sectionTag = (CompoundTag) rawSectionTag; - if (!sectionTag.getValue().containsKey("Y")) { + CompoundBinaryTag sectionTag = (CompoundBinaryTag) rawSectionTag; + if (sectionTag.get("Y") == null) { continue; // Empty section. } - int y = NBTUtils.getChildTag(sectionTag.getValue(), "Y", ByteTag.class).getValue(); + int y = NbtUtils.getChildTag(sectionTag, "Y", BinaryTagTypes.BYTE).value(); if (y < 0 || y >= 16) { continue; } // parse palette - List paletteEntries = sectionTag.getList("Palette", CompoundTag.class); + ListBinaryTag paletteEntries = sectionTag.getList("Palette", BinaryTagTypes.COMPOUND); int paletteSize = paletteEntries.size(); if (paletteSize == 0) { continue; } BlockState[] palette = new BlockState[paletteSize]; for (int paletteEntryId = 0; paletteEntryId < paletteSize; paletteEntryId++) { - CompoundTag paletteEntry = paletteEntries.get(paletteEntryId); + CompoundBinaryTag paletteEntry = (CompoundBinaryTag) paletteEntries.get(paletteEntryId); BlockType type = BlockTypes.get(paletteEntry.getString("Name")); if (type == null) { throw new InvalidFormatException("Invalid block type: " + paletteEntry.getString("Name")); } BlockState blockState = type.getDefaultState(); - if (paletteEntry.containsKey("Properties")) { - CompoundTag properties = NBTUtils.getChildTag(paletteEntry.getValue(), "Properties", CompoundTag.class); + if (paletteEntry.get("Properties") != null) { + CompoundBinaryTag properties = NbtUtils.getChildTag(paletteEntry, "Properties", BinaryTagTypes.COMPOUND); for (Property property : blockState.getStates().keySet()) { - if (properties.containsKey(property.getName())) { + if (properties.get(property.getName()) != null) { String value = properties.getString(property.getName()); try { blockState = getBlockStateWith(blockState, property, value); @@ -114,7 +126,7 @@ public AnvilChunk13(CompoundTag tag) throws DataException { } // parse block states - long[] blockStatesSerialized = NBTUtils.getChildTag(sectionTag.getValue(), "BlockStates", LongArrayTag.class).getValue(); + long[] blockStatesSerialized = NbtUtils.getChildTag(sectionTag, "BlockStates", BinaryTagTypes.LONG_ARRAY).value(); BlockState[] chunkSectionBlocks = new BlockState[16 * 16 * 16]; blocks[y] = chunkSectionBlocks; @@ -166,26 +178,24 @@ private BlockState getBlockStateWith(BlockState source, Property property */ private void populateTileEntities() throws DataException { tileEntities = new HashMap<>(); - if (!rootTag.getValue().containsKey("TileEntities")) { + if (rootTag.get("TileEntities") == null) { return; } - List tags = NBTUtils.getChildTag(rootTag.getValue(), - "TileEntities", ListTag.class).getValue(); + ListBinaryTag tags = NbtUtils.getChildTag(rootTag, "TileEntities", BinaryTagTypes.LIST); - for (Tag tag : tags) { - if (!(tag instanceof CompoundTag)) { + for (BinaryTag tag : tags) { + if (!(tag instanceof CompoundBinaryTag)) { throw new InvalidFormatException("CompoundTag expected in TileEntities"); } - CompoundTag t = (CompoundTag) tag; + CompoundBinaryTag t = (CompoundBinaryTag) tag; - Map values = new HashMap<>(t.getValue()); - int x = ((IntTag) values.get("x")).getValue(); - int y = ((IntTag) values.get("y")).getValue(); - int z = ((IntTag) values.get("z")).getValue(); + int x = ((IntBinaryTag) t.get("x")).value(); + int y = ((IntBinaryTag) t.get("y")).value(); + int z = ((IntBinaryTag) t.get("z")).value(); BlockVector3 vec = BlockVector3.at(x, y, z); - tileEntities.put(vec, values); + tileEntities.put(vec, t); } } @@ -199,17 +209,17 @@ private void populateTileEntities() throws DataException { * @throws DataException thrown if there is a data error */ @Nullable - private CompoundTag getBlockTileEntity(BlockVector3 position) throws DataException { + private CompoundBinaryTag getBlockTileEntity(BlockVector3 position) throws DataException { if (tileEntities == null) { populateTileEntities(); } - Map values = tileEntities.get(position); + CompoundBinaryTag values = tileEntities.get(position); if (values == null) { return null; } - return new CompoundTag(values); + return values; } @Override @@ -228,7 +238,7 @@ public BaseBlock getBlock(BlockVector3 position) throws DataException { BlockState[] sectionBlocks = blocks[section]; BlockState state = sectionBlocks != null ? sectionBlocks[(yIndex << 8) | (z << 4) | x] : BlockTypes.AIR.getDefaultState(); - CompoundTag tileEntity = getBlockTileEntity(position); + CompoundBinaryTag tileEntity = getBlockTileEntity(position); if (tileEntity != null) { return state.toBaseBlock(tileEntity); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk16.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk16.java index bd9d5e08a5..13e69458ae 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk16.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk16.java @@ -20,6 +20,7 @@ package com.sk89q.worldedit.world.chunk; import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.storage.InvalidFormatException; @@ -34,11 +35,23 @@ public class AnvilChunk16 extends AnvilChunk13 { * * @param tag the tag to read * @throws DataException on a data error + * @deprecated Use {@link #AnvilChunk16(CompoundBinaryTag)} */ + @Deprecated public AnvilChunk16(CompoundTag tag) throws DataException { super(tag); } + /** + * Construct the chunk with a compound tag. + * + * @param tag the tag to read + * @throws DataException on a data error + */ + public AnvilChunk16(CompoundBinaryTag tag) throws DataException { + super(tag); + } + @Override protected void readBlockStates(BlockState[] palette, long[] blockStatesSerialized, BlockState[] chunkSectionBlocks) throws InvalidFormatException { PackedIntArrayReader reader = new PackedIntArrayReader(blockStatesSerialized); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/OldChunk.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/OldChunk.java index 8f5665c449..83f695ed15 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/OldChunk.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/OldChunk.java @@ -19,14 +19,15 @@ package com.sk89q.worldedit.world.chunk; -import com.sk89q.jnbt.ByteArrayTag; import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.IntTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.NBTUtils; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.util.nbt.BinaryTag; +import com.sk89q.worldedit.util.nbt.BinaryTagTypes; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; +import com.sk89q.worldedit.util.nbt.IntBinaryTag; +import com.sk89q.worldedit.util.nbt.ListBinaryTag; +import com.sk89q.worldedit.util.nbt.NbtUtils; import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; @@ -35,7 +36,6 @@ import com.sk89q.worldedit.world.storage.InvalidFormatException; import java.util.HashMap; -import java.util.List; import java.util.Map; /** @@ -43,27 +43,40 @@ */ public class OldChunk implements Chunk { - private final CompoundTag rootTag; + private final CompoundBinaryTag rootTag; private final byte[] blocks; private final byte[] data; private final int rootX; private final int rootZ; - private Map> tileEntities; + private Map tileEntities; + /** * Construct the chunk with a compound tag. * * @param tag the tag * @throws DataException if there is an error getting the chunk data + * @deprecated Use {@link #OldChunk(CompoundBinaryTag)} */ + @Deprecated public OldChunk(CompoundTag tag) throws DataException { + this(tag.asBinaryTag()); + } + + /** + * Construct the chunk with a compound tag. + * + * @param tag the tag + * @throws DataException if there is an error getting the chunk data + */ + public OldChunk(CompoundBinaryTag tag) throws DataException { rootTag = tag; - blocks = NBTUtils.getChildTag(rootTag.getValue(), "Blocks", ByteArrayTag.class).getValue(); - data = NBTUtils.getChildTag(rootTag.getValue(), "Data", ByteArrayTag.class).getValue(); - rootX = NBTUtils.getChildTag(rootTag.getValue(), "xPos", IntTag.class).getValue(); - rootZ = NBTUtils.getChildTag(rootTag.getValue(), "zPos", IntTag.class).getValue(); + blocks = NbtUtils.getChildTag(rootTag, "Blocks", BinaryTagTypes.BYTE_ARRAY).value(); + data = NbtUtils.getChildTag(rootTag, "Data", BinaryTagTypes.BYTE_ARRAY).value(); + rootX = NbtUtils.getChildTag(rootTag, "xPos", BinaryTagTypes.INT).value(); + rootZ = NbtUtils.getChildTag(rootTag, "zPos", BinaryTagTypes.INT).value(); int size = 16 * 16 * 128; if (blocks.length != size) { @@ -83,51 +96,50 @@ public OldChunk(CompoundTag tag) throws DataException { * @throws DataException if there is an error getting the chunk data */ private void populateTileEntities() throws DataException { - List tags = NBTUtils.getChildTag( - rootTag.getValue(), "TileEntities", ListTag.class) - .getValue(); + ListBinaryTag tags = NbtUtils.getChildTag(rootTag, "TileEntities", BinaryTagTypes.LIST); tileEntities = new HashMap<>(); - for (Tag tag : tags) { - if (!(tag instanceof CompoundTag)) { + for (BinaryTag tag : tags) { + if (!(tag instanceof CompoundBinaryTag)) { throw new InvalidFormatException("CompoundTag expected in TileEntities"); } - CompoundTag t = (CompoundTag) tag; + CompoundBinaryTag t = (CompoundBinaryTag) tag; int x = 0; int y = 0; int z = 0; - Map values = new HashMap<>(); + CompoundBinaryTag.Builder values = CompoundBinaryTag.builder(); - for (Map.Entry entry : t.getValue().entrySet()) { - switch (entry.getKey()) { + for (String key : t.keySet()) { + BinaryTag value = t.get(key); + switch (key) { case "x": - if (entry.getValue() instanceof IntTag) { - x = ((IntTag) entry.getValue()).getValue(); + if (value instanceof IntBinaryTag) { + x = ((IntBinaryTag) value).value(); } break; case "y": - if (entry.getValue() instanceof IntTag) { - y = ((IntTag) entry.getValue()).getValue(); + if (value instanceof IntBinaryTag) { + y = ((IntBinaryTag) value).value(); } break; case "z": - if (entry.getValue() instanceof IntTag) { - z = ((IntTag) entry.getValue()).getValue(); + if (value instanceof IntBinaryTag) { + z = ((IntBinaryTag) value).value(); } break; default: break; } - values.put(entry.getKey(), entry.getValue()); + values.put(key, value); } BlockVector3 vec = BlockVector3.at(x, y, z); - tileEntities.put(vec, values); + tileEntities.put(vec, values.build()); } } @@ -140,16 +152,16 @@ private void populateTileEntities() throws DataException { * @return a tag * @throws DataException if there is an error getting the chunk data */ - private CompoundTag getBlockTileEntity(BlockVector3 position) throws DataException { + private CompoundBinaryTag getBlockTileEntity(BlockVector3 position) throws DataException { if (tileEntities == null) { populateTileEntities(); } - Map values = tileEntities.get(position); + CompoundBinaryTag values = tileEntities.get(position); if (values == null) { return null; } - return new CompoundTag(values); + return values; } @Override @@ -189,7 +201,7 @@ public BaseBlock getBlock(BlockVector3 position) throws DataException { return BlockTypes.AIR.getDefaultState().toBaseBlock(); } - CompoundTag tileEntity = getBlockTileEntity(position); + CompoundBinaryTag tileEntity = getBlockTileEntity(position); if (tileEntity != null) { return state.toBaseBlock(tileEntity); diff --git a/worldedit-core/src/main/resources/lang/strings.json b/worldedit-core/src/main/resources/lang/strings.json index 2ed98270c1..a48412d5d7 100644 --- a/worldedit-core/src/main/resources/lang/strings.json +++ b/worldedit-core/src/main/resources/lang/strings.json @@ -331,6 +331,7 @@ "worldedit.error.invalid-number.matches": "Number expected; string \"{0}\" given.", "worldedit.error.incomplete-region": "Make a region selection first.", "worldedit.error.unknown-block": "Block name '{0}' was not recognized.", + "worldedit.error.unknown-item": "Item name '{0}' was not recognized.", "worldedit.error.unknown-entity": "Entity name '{0}' was not recognized.", "worldedit.error.unknown-mob": "Mob name '{0}' was not recognized.", "worldedit.error.unknown-biome": "Biome name '{0}' was not recognized.", @@ -372,6 +373,7 @@ "worldedit.error.parser.missing-random-type": "Missing the type after the % symbol for '{0}'", "worldedit.error.parser.clipboard.missing-coordinates": "Clipboard offset needs x,y,z coordinates.", "worldedit.error.parser.player-only": "Input '{0}' requires a player!", + "worldedit.error.parser.invalid-nbt": "Invalid NBT Data in input: '{0}'. Error: {1}", "worldedit.error.disabled": "This functionality is disabled (see WorldEdit configuration).", "worldedit.error.unknown": "Unknown error occurred: {0}", "worldedit.error.missing-extent": "No Extent is known", diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java index 53b74c3f73..4823eb8062 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java @@ -20,8 +20,6 @@ package com.sk89q.worldedit.fabric; import com.google.common.collect.ImmutableList; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.fabric.internal.NBTConverter; import com.sk89q.worldedit.math.BlockVector3; @@ -32,6 +30,9 @@ import com.sk89q.worldedit.registry.state.IntegerProperty; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import com.sk89q.worldedit.util.nbt.BinaryTag; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; @@ -43,6 +44,8 @@ import net.minecraft.block.Block; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.state.StateManager; @@ -228,8 +231,8 @@ public static ItemType adapt(Item item) { public static ItemStack adapt(BaseItemStack baseItemStack) { net.minecraft.nbt.CompoundTag fabricCompound = null; - if (baseItemStack.getNbtData() != null) { - fabricCompound = NBTConverter.toNative(baseItemStack.getNbtData()); + if (baseItemStack.getNbt() != null) { + fabricCompound = NBTConverter.toNative(baseItemStack.getNbt()); } final ItemStack itemStack = new ItemStack(adapt(baseItemStack.getType()), baseItemStack.getAmount()); itemStack.setTag(fabricCompound); @@ -237,18 +240,22 @@ public static ItemStack adapt(BaseItemStack baseItemStack) { } public static BaseItemStack adapt(ItemStack itemStack) { - CompoundTag tag = NBTConverter.fromNative(itemStack.toTag(new net.minecraft.nbt.CompoundTag())); - if (tag.getValue().isEmpty()) { + CompoundTag tag = itemStack.toTag(new CompoundTag()); + if (tag.isEmpty()) { tag = null; } else { - final Tag tagTag = tag.getValue().get("tag"); + final Tag tagTag = tag.get("tag"); if (tagTag instanceof CompoundTag) { tag = ((CompoundTag) tagTag); } else { tag = null; } } - return new BaseItemStack(adapt(itemStack.getItem()), tag, itemStack.getCount()); + CompoundTag finalTag = tag; + return new BaseItemStack( + adapt(itemStack.getItem()), + finalTag == null ? null : LazyReference.from(() -> NBTConverter.fromNative(finalTag)), + itemStack.getCount()); } /** diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricDataFixer.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricDataFixer.java index e59956df3a..f2aab20d51 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricDataFixer.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricDataFixer.java @@ -35,8 +35,8 @@ import com.mojang.datafixers.DataFixerBuilder; import com.mojang.datafixers.schemas.Schema; import com.mojang.serialization.Dynamic; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.fabric.internal.NBTConverter; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import net.minecraft.datafixer.Schemas; import net.minecraft.datafixer.TypeReferences; import net.minecraft.nbt.FloatTag; @@ -92,11 +92,11 @@ class FabricDataFixer extends DataFixerBuilder implements com.sk89q.worldedit.wo @Override public T fixUp(FixType type, T original, int srcVer) { if (type == FixTypes.CHUNK) { - return (T) fixChunk((CompoundTag) original, srcVer); + return (T) fixChunk((CompoundBinaryTag) original, srcVer); } else if (type == FixTypes.BLOCK_ENTITY) { - return (T) fixBlockEntity((CompoundTag) original, srcVer); + return (T) fixBlockEntity((CompoundBinaryTag) original, srcVer); } else if (type == FixTypes.ENTITY) { - return (T) fixEntity((CompoundTag) original, srcVer); + return (T) fixEntity((CompoundBinaryTag) original, srcVer); } else if (type == FixTypes.BLOCK_STATE) { return (T) fixBlockState((String) original, srcVer); } else if (type == FixTypes.ITEM_TYPE) { @@ -107,19 +107,19 @@ public T fixUp(FixType type, T original, int srcVer) { return original; } - private CompoundTag fixChunk(CompoundTag originalChunk, int srcVer) { + private CompoundBinaryTag fixChunk(CompoundBinaryTag originalChunk, int srcVer) { net.minecraft.nbt.CompoundTag tag = NBTConverter.toNative(originalChunk); net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer); return NBTConverter.fromNative(fixed); } - private CompoundTag fixBlockEntity(CompoundTag origTileEnt, int srcVer) { + private CompoundBinaryTag fixBlockEntity(CompoundBinaryTag origTileEnt, int srcVer) { net.minecraft.nbt.CompoundTag tag = NBTConverter.toNative(origTileEnt); net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer); return NBTConverter.fromNative(fixed); } - private CompoundTag fixEntity(CompoundTag origEnt, int srcVer) { + private CompoundBinaryTag fixEntity(CompoundBinaryTag origEnt, int srcVer) { net.minecraft.nbt.CompoundTag tag = NBTConverter.toNative(origEnt); net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer); return NBTConverter.fromNative(fixed); diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntity.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntity.java index 02ac3a4a8d..cd88c721dd 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntity.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntity.java @@ -26,6 +26,7 @@ import com.sk89q.worldedit.fabric.internal.NBTConverter; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.world.NullWorld; import com.sk89q.worldedit.world.entity.EntityTypes; import net.minecraft.nbt.CompoundTag; @@ -53,7 +54,7 @@ public BaseEntity getState() { Identifier id = Registry.ENTITY_TYPE.getId(entity.getType()); CompoundTag tag = new CompoundTag(); entity.toTag(tag); - return new BaseEntity(EntityTypes.get(id.toString()), NBTConverter.fromNative(tag)); + return new BaseEntity(EntityTypes.get(id.toString()), LazyReference.from(() -> NBTConverter.fromNative(tag))); } else { return null; } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java index 7240aa589d..cd34ca1646 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.fabric; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.util.StringUtil; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.entity.BaseEntity; @@ -38,6 +37,7 @@ import com.sk89q.worldedit.util.formatting.component.TextUtils; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.serializer.gson.GsonComponentSerializer; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockStateHolder; @@ -55,7 +55,6 @@ import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Hand; -import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import java.io.IOException; @@ -243,7 +242,7 @@ public > void sendFakeBlock(BlockVector3 pos, B bl player.networkHandler.sendPacket(packetOut); if (block instanceof BaseBlock && block.getBlockType().equals(BlockTypes.STRUCTURE_BLOCK)) { final BaseBlock baseBlock = (BaseBlock) block; - final CompoundTag nbtData = baseBlock.getNbtData(); + final CompoundBinaryTag nbtData = baseBlock.getNbt(); if (nbtData != null) { player.networkHandler.sendPacket(new BlockEntityUpdateS2CPacket( new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()), diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java index c4fb5cd6fd..07e1a3e1c0 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java @@ -28,7 +28,6 @@ import com.google.common.collect.Sets; import com.google.common.util.concurrent.Futures; import com.mojang.serialization.Dynamic; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; @@ -52,7 +51,9 @@ import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.util.TreeGenerator.TreeType; +import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.util.io.file.SafeFiles; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.AbstractWorld; import com.sk89q.worldedit.world.RegenOptions; import com.sk89q.worldedit.world.biome.BiomeType; @@ -248,7 +249,7 @@ public boolean setBiome(BlockVector3 position, BiomeType biome) { @Override public boolean useItem(BlockVector3 position, BaseItem item, Direction face) { - ItemStack stack = FabricAdapter.adapt(new BaseItemStack(item.getType(), item.getNbtData(), 1)); + ItemStack stack = FabricAdapter.adapt(new BaseItemStack(item.getType(), item.getNbtReference(), 1)); ServerWorld world = (ServerWorld) getWorld(); final WorldEditFakePlayer fakePlayer; try { @@ -426,7 +427,7 @@ private void regenForWorld(Region region, Extent extent, ServerWorld serverWorld if (blockEntity != null) { net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); blockEntity.toTag(tag); - state = state.toBaseBlock(NBTConverter.fromNative(tag)); + state = state.toBaseBlock(LazyReference.from(() -> NBTConverter.fromNative(tag))); } extent.setBlock(vec, state.toBaseBlock()); @@ -602,7 +603,7 @@ public BaseBlock getFullBlock(BlockVector3 position) { if (tile != null) { net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); tile.toTag(tag); - return getBlock(position).toBaseBlock(NBTConverter.fromNative(tag)); + return getBlock(position).toBaseBlock(LazyReference.from(() -> NBTConverter.fromNative(tag))); } else { return getBlock(position).toBaseBlock(); } @@ -667,9 +668,9 @@ public Entity createEntity(Location location, BaseEntity entity) { } net.minecraft.entity.Entity createdEntity = entityType.get().create(world); if (createdEntity != null) { - CompoundTag nativeTag = entity.getNbtData(); + CompoundBinaryTag nativeTag = entity.getNbt(); if (nativeTag != null) { - net.minecraft.nbt.CompoundTag tag = NBTConverter.toNative(entity.getNbtData()); + net.minecraft.nbt.CompoundTag tag = NBTConverter.toNative(nativeTag); for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { tag.remove(name); } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java index 62b3f92df9..5fbc89fb51 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java @@ -24,6 +24,7 @@ import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; @@ -103,7 +104,7 @@ public void updateLightingForBlock(BlockPos position) { } @Override - public boolean updateTileEntity(BlockPos position, com.sk89q.jnbt.CompoundTag tag) { + public boolean updateTileEntity(BlockPos position, CompoundBinaryTag tag) { CompoundTag nativeTag = NBTConverter.toNative(tag); BlockEntity tileEntity = getWorld().getWorldChunk(position).getBlockEntity(position); if (tileEntity == null) { diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/NBTConverter.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/NBTConverter.java index d915dce7bf..418b90b46a 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/NBTConverter.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/NBTConverter.java @@ -19,27 +19,22 @@ package com.sk89q.worldedit.fabric.internal; -import com.sk89q.jnbt.ByteArrayTag; -import com.sk89q.jnbt.ByteTag; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.DoubleTag; -import com.sk89q.jnbt.EndTag; -import com.sk89q.jnbt.FloatTag; -import com.sk89q.jnbt.IntArrayTag; -import com.sk89q.jnbt.IntTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.LongArrayTag; -import com.sk89q.jnbt.LongTag; -import com.sk89q.jnbt.ShortTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; - -import java.util.ArrayList; +import com.sk89q.worldedit.util.nbt.BinaryTag; +import com.sk89q.worldedit.util.nbt.ByteArrayBinaryTag; +import com.sk89q.worldedit.util.nbt.ByteBinaryTag; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; +import com.sk89q.worldedit.util.nbt.DoubleBinaryTag; +import com.sk89q.worldedit.util.nbt.EndBinaryTag; +import com.sk89q.worldedit.util.nbt.FloatBinaryTag; +import com.sk89q.worldedit.util.nbt.IntArrayBinaryTag; +import com.sk89q.worldedit.util.nbt.IntBinaryTag; +import com.sk89q.worldedit.util.nbt.ListBinaryTag; +import com.sk89q.worldedit.util.nbt.LongArrayBinaryTag; +import com.sk89q.worldedit.util.nbt.LongBinaryTag; +import com.sk89q.worldedit.util.nbt.ShortBinaryTag; +import com.sk89q.worldedit.util.nbt.StringBinaryTag; + import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import java.util.Set; /** @@ -50,56 +45,56 @@ public final class NBTConverter { private NBTConverter() { } - public static net.minecraft.nbt.Tag toNative(Tag tag) { - if (tag instanceof IntArrayTag) { - return toNative((IntArrayTag) tag); + public static net.minecraft.nbt.Tag toNative(BinaryTag tag) { + if (tag instanceof IntArrayBinaryTag) { + return toNative((IntArrayBinaryTag) tag); - } else if (tag instanceof ListTag) { - return toNative((ListTag) tag); + } else if (tag instanceof ListBinaryTag) { + return toNative((ListBinaryTag) tag); - } else if (tag instanceof LongTag) { - return toNative((LongTag) tag); + } else if (tag instanceof LongBinaryTag) { + return toNative((LongBinaryTag) tag); - } else if (tag instanceof LongArrayTag) { - return toNative((LongArrayTag) tag); + } else if (tag instanceof LongArrayBinaryTag) { + return toNative((LongArrayBinaryTag) tag); - } else if (tag instanceof StringTag) { - return toNative((StringTag) tag); + } else if (tag instanceof StringBinaryTag) { + return toNative((StringBinaryTag) tag); - } else if (tag instanceof IntTag) { - return toNative((IntTag) tag); + } else if (tag instanceof IntBinaryTag) { + return toNative((IntBinaryTag) tag); - } else if (tag instanceof ByteTag) { - return toNative((ByteTag) tag); + } else if (tag instanceof ByteBinaryTag) { + return toNative((ByteBinaryTag) tag); - } else if (tag instanceof ByteArrayTag) { - return toNative((ByteArrayTag) tag); + } else if (tag instanceof ByteArrayBinaryTag) { + return toNative((ByteArrayBinaryTag) tag); - } else if (tag instanceof CompoundTag) { - return toNative((CompoundTag) tag); + } else if (tag instanceof CompoundBinaryTag) { + return toNative((CompoundBinaryTag) tag); - } else if (tag instanceof FloatTag) { - return toNative((FloatTag) tag); + } else if (tag instanceof FloatBinaryTag) { + return toNative((FloatBinaryTag) tag); - } else if (tag instanceof ShortTag) { - return toNative((ShortTag) tag); + } else if (tag instanceof ShortBinaryTag) { + return toNative((ShortBinaryTag) tag); - } else if (tag instanceof DoubleTag) { - return toNative((DoubleTag) tag); + } else if (tag instanceof DoubleBinaryTag) { + return toNative((DoubleBinaryTag) tag); } else { throw new IllegalArgumentException("Can't convert tag of type " + tag.getClass().getCanonicalName()); } } - public static net.minecraft.nbt.IntArrayTag toNative(IntArrayTag tag) { - int[] value = tag.getValue(); + public static net.minecraft.nbt.IntArrayTag toNative(IntArrayBinaryTag tag) { + int[] value = tag.value(); return new net.minecraft.nbt.IntArrayTag(Arrays.copyOf(value, value.length)); } - public static net.minecraft.nbt.ListTag toNative(ListTag tag) { + public static net.minecraft.nbt.ListTag toNative(ListBinaryTag tag) { net.minecraft.nbt.ListTag list = new net.minecraft.nbt.ListTag(); - for (Tag child : tag.getValue()) { - if (child instanceof EndTag) { + for (BinaryTag child : tag) { + if (child instanceof EndBinaryTag) { continue; } list.add(toNative(child)); @@ -107,51 +102,51 @@ public static net.minecraft.nbt.ListTag toNative(ListTag tag) { return list; } - public static net.minecraft.nbt.LongTag toNative(LongTag tag) { - return net.minecraft.nbt.LongTag.of(tag.getValue()); + public static net.minecraft.nbt.LongTag toNative(LongBinaryTag tag) { + return net.minecraft.nbt.LongTag.of(tag.value()); } - public static net.minecraft.nbt.LongArrayTag toNative(LongArrayTag tag) { - return new net.minecraft.nbt.LongArrayTag(tag.getValue().clone()); + public static net.minecraft.nbt.LongArrayTag toNative(LongArrayBinaryTag tag) { + return new net.minecraft.nbt.LongArrayTag(tag.value().clone()); } - public static net.minecraft.nbt.StringTag toNative(StringTag tag) { - return net.minecraft.nbt.StringTag.of(tag.getValue()); + public static net.minecraft.nbt.StringTag toNative(StringBinaryTag tag) { + return net.minecraft.nbt.StringTag.of(tag.value()); } - public static net.minecraft.nbt.IntTag toNative(IntTag tag) { - return net.minecraft.nbt.IntTag.of(tag.getValue()); + public static net.minecraft.nbt.IntTag toNative(IntBinaryTag tag) { + return net.minecraft.nbt.IntTag.of(tag.value()); } - public static net.minecraft.nbt.ByteTag toNative(ByteTag tag) { - return net.minecraft.nbt.ByteTag.of(tag.getValue()); + public static net.minecraft.nbt.ByteTag toNative(ByteBinaryTag tag) { + return net.minecraft.nbt.ByteTag.of(tag.value()); } - public static net.minecraft.nbt.ByteArrayTag toNative(ByteArrayTag tag) { - return new net.minecraft.nbt.ByteArrayTag(tag.getValue().clone()); + public static net.minecraft.nbt.ByteArrayTag toNative(ByteArrayBinaryTag tag) { + return new net.minecraft.nbt.ByteArrayTag(tag.value().clone()); } - public static net.minecraft.nbt.CompoundTag toNative(CompoundTag tag) { + public static net.minecraft.nbt.CompoundTag toNative(CompoundBinaryTag tag) { net.minecraft.nbt.CompoundTag compound = new net.minecraft.nbt.CompoundTag(); - for (Entry child : tag.getValue().entrySet()) { - compound.put(child.getKey(), toNative(child.getValue())); + for (String key : tag.keySet()) { + compound.put(key, toNative(tag.get(key))); } return compound; } - public static net.minecraft.nbt.FloatTag toNative(FloatTag tag) { - return net.minecraft.nbt.FloatTag.of(tag.getValue()); + public static net.minecraft.nbt.FloatTag toNative(FloatBinaryTag tag) { + return net.minecraft.nbt.FloatTag.of(tag.value()); } - public static net.minecraft.nbt.ShortTag toNative(ShortTag tag) { - return net.minecraft.nbt.ShortTag.of(tag.getValue()); + public static net.minecraft.nbt.ShortTag toNative(ShortBinaryTag tag) { + return net.minecraft.nbt.ShortTag.of(tag.value()); } - public static net.minecraft.nbt.DoubleTag toNative(DoubleTag tag) { - return net.minecraft.nbt.DoubleTag.of(tag.getValue()); + public static net.minecraft.nbt.DoubleTag toNative(DoubleBinaryTag tag) { + return net.minecraft.nbt.DoubleTag.of(tag.value()); } - public static Tag fromNative(net.minecraft.nbt.Tag other) { + public static BinaryTag fromNative(net.minecraft.nbt.Tag other) { if (other instanceof net.minecraft.nbt.IntArrayTag) { return fromNative((net.minecraft.nbt.IntArrayTag) other); @@ -195,71 +190,69 @@ public static Tag fromNative(net.minecraft.nbt.Tag other) { } } - public static IntArrayTag fromNative(net.minecraft.nbt.IntArrayTag other) { + public static IntArrayBinaryTag fromNative(net.minecraft.nbt.IntArrayTag other) { int[] value = other.getIntArray(); - return new IntArrayTag(Arrays.copyOf(value, value.length)); + return IntArrayBinaryTag.of(Arrays.copyOf(value, value.length)); } - public static ListTag fromNative(net.minecraft.nbt.ListTag other) { + public static ListBinaryTag fromNative(net.minecraft.nbt.ListTag other) { other = other.copy(); - List list = new ArrayList<>(); - Class listClass = StringTag.class; + ListBinaryTag.Builder list = ListBinaryTag.builder(); int tags = other.size(); for (int i = 0; i < tags; i++) { - Tag child = fromNative(other.remove(0)); + BinaryTag child = fromNative(other.remove(0)); list.add(child); - listClass = child.getClass(); } - return new ListTag(listClass, list); + return list.build(); } - public static EndTag fromNative(net.minecraft.nbt.EndTag other) { - return new EndTag(); + public static EndBinaryTag fromNative(net.minecraft.nbt.EndTag other) { + return EndBinaryTag.get(); } - public static LongTag fromNative(net.minecraft.nbt.LongTag other) { - return new LongTag(other.getLong()); + public static LongBinaryTag fromNative(net.minecraft.nbt.LongTag other) { + return LongBinaryTag.of(other.getLong()); } - public static LongArrayTag fromNative(net.minecraft.nbt.LongArrayTag other) { - return new LongArrayTag(other.getLongArray().clone()); + public static LongArrayBinaryTag fromNative(net.minecraft.nbt.LongArrayTag other) { + return LongArrayBinaryTag.of(other.getLongArray().clone()); } - public static StringTag fromNative(net.minecraft.nbt.StringTag other) { - return new StringTag(other.asString()); + public static StringBinaryTag fromNative(net.minecraft.nbt.StringTag other) { + return StringBinaryTag.of(other.asString()); } - public static IntTag fromNative(net.minecraft.nbt.IntTag other) { - return new IntTag(other.getInt()); + public static IntBinaryTag fromNative(net.minecraft.nbt.IntTag other) { + return IntBinaryTag.of(other.getInt()); } - public static ByteTag fromNative(net.minecraft.nbt.ByteTag other) { - return new ByteTag(other.getByte()); + public static ByteBinaryTag fromNative(net.minecraft.nbt.ByteTag other) { + return ByteBinaryTag.of(other.getByte()); } - public static ByteArrayTag fromNative(net.minecraft.nbt.ByteArrayTag other) { - return new ByteArrayTag(other.getByteArray().clone()); + public static ByteArrayBinaryTag fromNative(net.minecraft.nbt.ByteArrayTag other) { + return ByteArrayBinaryTag.of(other.getByteArray().clone()); } - public static CompoundTag fromNative(net.minecraft.nbt.CompoundTag other) { + public static CompoundBinaryTag fromNative(net.minecraft.nbt.CompoundTag other) { Set tags = other.getKeys(); - Map map = new HashMap<>(); + CompoundBinaryTag.Builder builder = CompoundBinaryTag.builder(); for (String tagName : tags) { - map.put(tagName, fromNative(other.get(tagName))); + builder.put(tagName, fromNative(other.get(tagName))); } - return new CompoundTag(map); + return builder.build(); } - public static FloatTag fromNative(net.minecraft.nbt.FloatTag other) { - return new FloatTag(other.getFloat()); + public static FloatBinaryTag fromNative(net.minecraft.nbt.FloatTag other) { + return FloatBinaryTag.of(other.getFloat()); } - public static ShortTag fromNative(net.minecraft.nbt.ShortTag other) { - return new ShortTag(other.getShort()); + public static ShortBinaryTag fromNative(net.minecraft.nbt.ShortTag other) { + return ShortBinaryTag.of(other.getShort()); } - public static DoubleTag fromNative(net.minecraft.nbt.DoubleTag other) { - return new DoubleTag(other.getDouble()); + public static DoubleBinaryTag fromNative(net.minecraft.nbt.DoubleTag other) { + return DoubleBinaryTag.of(other.getDouble()); } } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeAdapter.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeAdapter.java index 840eb04547..c18a39202c 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeAdapter.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeAdapter.java @@ -20,8 +20,6 @@ package com.sk89q.worldedit.forge; import com.google.common.collect.ImmutableList; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.forge.internal.NBTConverter; import com.sk89q.worldedit.math.BlockVector3; @@ -32,6 +30,7 @@ import com.sk89q.worldedit.registry.state.IntegerProperty; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; @@ -45,6 +44,7 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.INBT; import net.minecraft.state.DirectionProperty; import net.minecraft.state.StateContainer; import net.minecraft.util.IStringSerializable; @@ -224,8 +224,8 @@ public static ItemType adapt(Item item) { public static ItemStack adapt(BaseItemStack baseItemStack) { CompoundNBT forgeCompound = null; - if (baseItemStack.getNbtData() != null) { - forgeCompound = NBTConverter.toNative(baseItemStack.getNbtData()); + if (baseItemStack.getNbt() != null) { + forgeCompound = NBTConverter.toNative(baseItemStack.getNbt()); } final ItemStack itemStack = new ItemStack(adapt(baseItemStack.getType()), baseItemStack.getAmount()); itemStack.setTag(forgeCompound); @@ -233,18 +233,23 @@ public static ItemStack adapt(BaseItemStack baseItemStack) { } public static BaseItemStack adapt(ItemStack itemStack) { - CompoundTag tag = NBTConverter.fromNative(itemStack.serializeNBT()); - if (tag.getValue().isEmpty()) { + CompoundNBT tag = itemStack.serializeNBT(); + if (tag.keySet().isEmpty()) { tag = null; } else { - final Tag tagTag = tag.getValue().get("tag"); - if (tagTag instanceof CompoundTag) { - tag = ((CompoundTag) tagTag); + final INBT tagTag = tag.get("tag"); + if (tagTag instanceof CompoundNBT) { + tag = ((CompoundNBT) tagTag); } else { tag = null; } } - return new BaseItemStack(adapt(itemStack.getItem()), tag, itemStack.getCount()); + CompoundNBT finalTag = tag; + return new BaseItemStack( + adapt(itemStack.getItem()), + finalTag == null ? null : LazyReference.from(() -> NBTConverter.fromNative(finalTag)), + itemStack.getCount() + ); } /** diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeDataFixer.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeDataFixer.java index 7eebd7dc5b..0c5edd609c 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeDataFixer.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeDataFixer.java @@ -34,8 +34,8 @@ import com.mojang.datafixers.DataFixerBuilder; import com.mojang.datafixers.schemas.Schema; import com.mojang.serialization.Dynamic; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.forge.internal.NBTConverter; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import net.minecraft.item.DyeColor; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.FloatNBT; @@ -94,11 +94,11 @@ class ForgeDataFixer extends DataFixerBuilder implements com.sk89q.worldedit.wor @Override public T fixUp(FixType type, T original, int srcVer) { if (type == FixTypes.CHUNK) { - return (T) fixChunk((CompoundTag) original, srcVer); + return (T) fixChunk((CompoundBinaryTag) original, srcVer); } else if (type == FixTypes.BLOCK_ENTITY) { - return (T) fixBlockEntity((CompoundTag) original, srcVer); + return (T) fixBlockEntity((CompoundBinaryTag) original, srcVer); } else if (type == FixTypes.ENTITY) { - return (T) fixEntity((CompoundTag) original, srcVer); + return (T) fixEntity((CompoundBinaryTag) original, srcVer); } else if (type == FixTypes.BLOCK_STATE) { return (T) fixBlockState((String) original, srcVer); } else if (type == FixTypes.ITEM_TYPE) { @@ -109,19 +109,19 @@ public T fixUp(FixType type, T original, int srcVer) { return original; } - private CompoundTag fixChunk(CompoundTag originalChunk, int srcVer) { + private CompoundBinaryTag fixChunk(CompoundBinaryTag originalChunk, int srcVer) { CompoundNBT tag = NBTConverter.toNative(originalChunk); CompoundNBT fixed = convert(LegacyType.CHUNK, tag, srcVer); return NBTConverter.fromNative(fixed); } - private CompoundTag fixBlockEntity(CompoundTag origTileEnt, int srcVer) { + private CompoundBinaryTag fixBlockEntity(CompoundBinaryTag origTileEnt, int srcVer) { CompoundNBT tag = NBTConverter.toNative(origTileEnt); CompoundNBT fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer); return NBTConverter.fromNative(fixed); } - private CompoundTag fixEntity(CompoundTag origEnt, int srcVer) { + private CompoundBinaryTag fixEntity(CompoundBinaryTag origEnt, int srcVer) { CompoundNBT tag = NBTConverter.toNative(origEnt); CompoundNBT fixed = convert(LegacyType.ENTITY, tag, srcVer); return NBTConverter.fromNative(fixed); diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntity.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntity.java index 521835dcc4..623e5a30d3 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntity.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntity.java @@ -26,6 +26,7 @@ import com.sk89q.worldedit.forge.internal.NBTConverter; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.world.NullWorld; import com.sk89q.worldedit.world.entity.EntityTypes; import net.minecraft.nbt.CompoundNBT; @@ -53,7 +54,10 @@ public BaseEntity getState() { if (id != null) { CompoundNBT tag = new CompoundNBT(); entity.writeWithoutTypeId(tag); - return new BaseEntity(EntityTypes.get(id.toString()), NBTConverter.fromNative(tag)); + return new BaseEntity( + EntityTypes.get(id.toString()), + LazyReference.from(() -> NBTConverter.fromNative(tag)) + ); } else { return null; } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java index 2151d98454..41e08e9559 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.forge; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.util.StringUtil; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.entity.BaseEntity; @@ -36,6 +35,7 @@ import com.sk89q.worldedit.util.formatting.component.TextUtils; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.serializer.gson.GsonComponentSerializer; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockStateHolder; @@ -244,7 +244,7 @@ public > void sendFakeBlock(BlockVector3 pos, B bl player.connection.sendPacket(packetOut); if (block instanceof BaseBlock && block.getBlockType().equals(BlockTypes.STRUCTURE_BLOCK)) { final BaseBlock baseBlock = (BaseBlock) block; - final CompoundTag nbtData = baseBlock.getNbtData(); + final CompoundBinaryTag nbtData = baseBlock.getNbt(); if (nbtData != null) { player.connection.sendPacket(new SUpdateTileEntityPacket( new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()), diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java index e54caa1a43..fdef1811da 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java @@ -29,7 +29,6 @@ import com.google.common.util.concurrent.Futures; import com.mojang.serialization.Codec; import com.mojang.serialization.Dynamic; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; @@ -52,7 +51,9 @@ import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.util.TreeGenerator.TreeType; +import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.util.io.file.SafeFiles; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.AbstractWorld; import com.sk89q.worldedit.world.RegenOptions; import com.sk89q.worldedit.world.biome.BiomeType; @@ -253,7 +254,7 @@ public boolean setBiome(BlockVector3 position, BiomeType biome) { @Override public boolean useItem(BlockVector3 position, BaseItem item, Direction face) { - ItemStack stack = ForgeAdapter.adapt(new BaseItemStack(item.getType(), item.getNbtData(), 1)); + ItemStack stack = ForgeAdapter.adapt(new BaseItemStack(item.getType(), item.getNbtReference(), 1)); ServerWorld world = (ServerWorld) getWorld(); final WorldEditFakePlayer fakePlayer; try { @@ -437,7 +438,7 @@ private void regenForWorld(Region region, Extent extent, ServerWorld serverWorld if (blockEntity != null) { CompoundNBT tag = new CompoundNBT(); blockEntity.write(tag); - state = state.toBaseBlock(NBTConverter.fromNative(tag)); + state = state.toBaseBlock(LazyReference.from(() -> NBTConverter.fromNative(tag))); } extent.setBlock(vec, state.toBaseBlock()); @@ -610,7 +611,10 @@ public BaseBlock getFullBlock(BlockVector3 position) { TileEntity tile = getWorld().getChunk(pos).getTileEntity(pos); if (tile != null) { - return getBlock(position).toBaseBlock(NBTConverter.fromNative(TileEntityUtils.copyNbtData(tile))); + CompoundNBT tag = TileEntityUtils.copyNbtData(tile); + return getBlock(position).toBaseBlock( + LazyReference.from(() -> NBTConverter.fromNative(tag)) + ); } else { return getBlock(position).toBaseBlock(); } @@ -677,9 +681,9 @@ public Entity createEntity(Location location, BaseEntity entity) { } net.minecraft.entity.Entity createdEntity = entityType.get().create(world); if (createdEntity != null) { - CompoundTag nativeTag = entity.getNbtData(); + CompoundBinaryTag nativeTag = entity.getNbt(); if (nativeTag != null) { - CompoundNBT tag = NBTConverter.toNative(entity.getNbtData()); + CompoundNBT tag = NBTConverter.toNative(nativeTag); for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { tag.remove(name); } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/ForgeWorldNativeAccess.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/ForgeWorldNativeAccess.java index 94f491b9f0..1080994a89 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/ForgeWorldNativeAccess.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/ForgeWorldNativeAccess.java @@ -19,12 +19,12 @@ package com.sk89q.worldedit.forge.internal; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.forge.ForgeAdapter; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.nbt.CompoundNBT; @@ -98,7 +98,7 @@ public void updateLightingForBlock(BlockPos position) { } @Override - public boolean updateTileEntity(BlockPos position, CompoundTag tag) { + public boolean updateTileEntity(BlockPos position, CompoundBinaryTag tag) { CompoundNBT nativeTag = NBTConverter.toNative(tag); return TileEntityUtils.setTileEntity(getWorld(), position, nativeTag); } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/NBTConverter.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/NBTConverter.java index 64532b6fb0..693369a71f 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/NBTConverter.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/NBTConverter.java @@ -19,20 +19,20 @@ package com.sk89q.worldedit.forge.internal; -import com.sk89q.jnbt.ByteArrayTag; -import com.sk89q.jnbt.ByteTag; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.DoubleTag; -import com.sk89q.jnbt.EndTag; -import com.sk89q.jnbt.FloatTag; -import com.sk89q.jnbt.IntArrayTag; -import com.sk89q.jnbt.IntTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.LongArrayTag; -import com.sk89q.jnbt.LongTag; -import com.sk89q.jnbt.ShortTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.util.nbt.BinaryTag; +import com.sk89q.worldedit.util.nbt.ByteArrayBinaryTag; +import com.sk89q.worldedit.util.nbt.ByteBinaryTag; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; +import com.sk89q.worldedit.util.nbt.DoubleBinaryTag; +import com.sk89q.worldedit.util.nbt.EndBinaryTag; +import com.sk89q.worldedit.util.nbt.FloatBinaryTag; +import com.sk89q.worldedit.util.nbt.IntArrayBinaryTag; +import com.sk89q.worldedit.util.nbt.IntBinaryTag; +import com.sk89q.worldedit.util.nbt.ListBinaryTag; +import com.sk89q.worldedit.util.nbt.LongArrayBinaryTag; +import com.sk89q.worldedit.util.nbt.LongBinaryTag; +import com.sk89q.worldedit.util.nbt.ShortBinaryTag; +import com.sk89q.worldedit.util.nbt.StringBinaryTag; import net.minecraft.nbt.ByteArrayNBT; import net.minecraft.nbt.ByteNBT; import net.minecraft.nbt.CompoundNBT; @@ -48,12 +48,7 @@ import net.minecraft.nbt.ShortNBT; import net.minecraft.nbt.StringNBT; -import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import java.util.Set; /** @@ -64,56 +59,56 @@ public final class NBTConverter { private NBTConverter() { } - public static INBT toNative(Tag tag) { - if (tag instanceof IntArrayTag) { - return toNative((IntArrayTag) tag); + public static INBT toNative(BinaryTag tag) { + if (tag instanceof IntArrayBinaryTag) { + return toNative((IntArrayBinaryTag) tag); - } else if (tag instanceof ListTag) { - return toNative((ListTag) tag); + } else if (tag instanceof ListBinaryTag) { + return toNative((ListBinaryTag) tag); - } else if (tag instanceof LongTag) { - return toNative((LongTag) tag); + } else if (tag instanceof LongBinaryTag) { + return toNative((LongBinaryTag) tag); - } else if (tag instanceof LongArrayTag) { - return toNative((LongArrayTag) tag); + } else if (tag instanceof LongArrayBinaryTag) { + return toNative((LongArrayBinaryTag) tag); - } else if (tag instanceof StringTag) { - return toNative((StringTag) tag); + } else if (tag instanceof StringBinaryTag) { + return toNative((StringBinaryTag) tag); - } else if (tag instanceof IntTag) { - return toNative((IntTag) tag); + } else if (tag instanceof IntBinaryTag) { + return toNative((IntBinaryTag) tag); - } else if (tag instanceof ByteTag) { - return toNative((ByteTag) tag); + } else if (tag instanceof ByteBinaryTag) { + return toNative((ByteBinaryTag) tag); - } else if (tag instanceof ByteArrayTag) { - return toNative((ByteArrayTag) tag); + } else if (tag instanceof ByteArrayBinaryTag) { + return toNative((ByteArrayBinaryTag) tag); - } else if (tag instanceof CompoundTag) { - return toNative((CompoundTag) tag); + } else if (tag instanceof CompoundBinaryTag) { + return toNative((CompoundBinaryTag) tag); - } else if (tag instanceof FloatTag) { - return toNative((FloatTag) tag); + } else if (tag instanceof FloatBinaryTag) { + return toNative((FloatBinaryTag) tag); - } else if (tag instanceof ShortTag) { - return toNative((ShortTag) tag); + } else if (tag instanceof ShortBinaryTag) { + return toNative((ShortBinaryTag) tag); - } else if (tag instanceof DoubleTag) { - return toNative((DoubleTag) tag); + } else if (tag instanceof DoubleBinaryTag) { + return toNative((DoubleBinaryTag) tag); } else { throw new IllegalArgumentException("Can't convert tag of type " + tag.getClass().getCanonicalName()); } } - public static IntArrayNBT toNative(IntArrayTag tag) { - int[] value = tag.getValue(); + public static IntArrayNBT toNative(IntArrayBinaryTag tag) { + int[] value = tag.value(); return new IntArrayNBT(Arrays.copyOf(value, value.length)); } - public static ListNBT toNative(ListTag tag) { + public static ListNBT toNative(ListBinaryTag tag) { ListNBT list = new ListNBT(); - for (Tag child : tag.getValue()) { - if (child instanceof EndTag) { + for (BinaryTag child : tag) { + if (child instanceof EndBinaryTag) { continue; } list.add(toNative(child)); @@ -121,51 +116,51 @@ public static ListNBT toNative(ListTag tag) { return list; } - public static LongNBT toNative(LongTag tag) { - return LongNBT.valueOf(tag.getValue()); + public static LongNBT toNative(LongBinaryTag tag) { + return LongNBT.valueOf(tag.value()); } - public static LongArrayNBT toNative(LongArrayTag tag) { - return new LongArrayNBT(tag.getValue().clone()); + public static LongArrayNBT toNative(LongArrayBinaryTag tag) { + return new LongArrayNBT(tag.value().clone()); } - public static StringNBT toNative(StringTag tag) { - return StringNBT.valueOf(tag.getValue()); + public static StringNBT toNative(StringBinaryTag tag) { + return StringNBT.valueOf(tag.value()); } - public static IntNBT toNative(IntTag tag) { - return IntNBT.valueOf(tag.getValue()); + public static IntNBT toNative(IntBinaryTag tag) { + return IntNBT.valueOf(tag.value()); } - public static ByteNBT toNative(ByteTag tag) { - return ByteNBT.valueOf(tag.getValue()); + public static ByteNBT toNative(ByteBinaryTag tag) { + return ByteNBT.valueOf(tag.value()); } - public static ByteArrayNBT toNative(ByteArrayTag tag) { - return new ByteArrayNBT(tag.getValue().clone()); + public static ByteArrayNBT toNative(ByteArrayBinaryTag tag) { + return new ByteArrayNBT(tag.value().clone()); } - public static CompoundNBT toNative(CompoundTag tag) { + public static CompoundNBT toNative(CompoundBinaryTag tag) { CompoundNBT compound = new CompoundNBT(); - for (Entry child : tag.getValue().entrySet()) { - compound.put(child.getKey(), toNative(child.getValue())); + for (String key : tag.keySet()) { + compound.put(key, toNative(tag.get(key))); } return compound; } - public static FloatNBT toNative(FloatTag tag) { - return FloatNBT.valueOf(tag.getValue()); + public static FloatNBT toNative(FloatBinaryTag tag) { + return FloatNBT.valueOf(tag.value()); } - public static ShortNBT toNative(ShortTag tag) { - return ShortNBT.valueOf(tag.getValue()); + public static ShortNBT toNative(ShortBinaryTag tag) { + return ShortNBT.valueOf(tag.value()); } - public static DoubleNBT toNative(DoubleTag tag) { - return DoubleNBT.valueOf(tag.getValue()); + public static DoubleNBT toNative(DoubleBinaryTag tag) { + return DoubleNBT.valueOf(tag.value()); } - public static Tag fromNative(INBT other) { + public static BinaryTag fromNative(INBT other) { if (other instanceof IntArrayNBT) { return fromNative((IntArrayNBT) other); @@ -209,71 +204,69 @@ public static Tag fromNative(INBT other) { } } - public static IntArrayTag fromNative(IntArrayNBT other) { + public static IntArrayBinaryTag fromNative(IntArrayNBT other) { int[] value = other.getIntArray(); - return new IntArrayTag(Arrays.copyOf(value, value.length)); + return IntArrayBinaryTag.of(Arrays.copyOf(value, value.length)); } - public static ListTag fromNative(ListNBT other) { + public static ListBinaryTag fromNative(ListNBT other) { other = other.copy(); - List list = new ArrayList<>(); - Class listClass = StringTag.class; + ListBinaryTag.Builder list = ListBinaryTag.builder(); int tags = other.size(); for (int i = 0; i < tags; i++) { - Tag child = fromNative(other.remove(0)); + BinaryTag child = fromNative(other.remove(0)); list.add(child); - listClass = child.getClass(); } - return new ListTag(listClass, list); + return list.build(); } - public static EndTag fromNative(EndNBT other) { - return new EndTag(); + public static EndBinaryTag fromNative(EndNBT other) { + return EndBinaryTag.get(); } - public static LongTag fromNative(LongNBT other) { - return new LongTag(other.getLong()); + public static LongBinaryTag fromNative(LongNBT other) { + return LongBinaryTag.of(other.getLong()); } - public static LongArrayTag fromNative(LongArrayNBT other) { - return new LongArrayTag(other.getAsLongArray().clone()); + public static LongArrayBinaryTag fromNative(LongArrayNBT other) { + return LongArrayBinaryTag.of(other.getAsLongArray().clone()); } - public static StringTag fromNative(StringNBT other) { - return new StringTag(other.getString()); + public static StringBinaryTag fromNative(StringNBT other) { + return StringBinaryTag.of(other.getString()); } - public static IntTag fromNative(IntNBT other) { - return new IntTag(other.getInt()); + public static IntBinaryTag fromNative(IntNBT other) { + return IntBinaryTag.of(other.getInt()); } - public static ByteTag fromNative(ByteNBT other) { - return new ByteTag(other.getByte()); + public static ByteBinaryTag fromNative(ByteNBT other) { + return ByteBinaryTag.of(other.getByte()); } - public static ByteArrayTag fromNative(ByteArrayNBT other) { - return new ByteArrayTag(other.getByteArray().clone()); + public static ByteArrayBinaryTag fromNative(ByteArrayNBT other) { + return ByteArrayBinaryTag.of(other.getByteArray().clone()); } - public static CompoundTag fromNative(CompoundNBT other) { + public static CompoundBinaryTag fromNative(CompoundNBT other) { Set tags = other.keySet(); - Map map = new HashMap<>(); + CompoundBinaryTag.Builder map = CompoundBinaryTag.builder(); for (String tagName : tags) { map.put(tagName, fromNative(other.get(tagName))); } - return new CompoundTag(map); + return map.build(); } - public static FloatTag fromNative(FloatNBT other) { - return new FloatTag(other.getFloat()); + public static FloatBinaryTag fromNative(FloatNBT other) { + return FloatBinaryTag.of(other.getFloat()); } - public static ShortTag fromNative(ShortNBT other) { - return new ShortTag(other.getShort()); + public static ShortBinaryTag fromNative(ShortNBT other) { + return ShortBinaryTag.of(other.getShort()); } - public static DoubleTag fromNative(DoubleNBT other) { - return new DoubleTag(other.getDouble()); + public static DoubleBinaryTag fromNative(DoubleNBT other) { + return DoubleBinaryTag.of(other.getDouble()); } } diff --git a/worldedit-libs/core/build.gradle.kts b/worldedit-libs/core/build.gradle.kts index d669216d6d..84714e5eb7 100644 --- a/worldedit-libs/core/build.gradle.kts +++ b/worldedit-libs/core/build.gradle.kts @@ -13,4 +13,5 @@ dependencies { "shade"("org.enginehub.piston:core:${Versions.PISTON}") "shade"("org.enginehub.piston.core-ap:runtime:${Versions.PISTON}") "shade"("org.enginehub.piston:default-impl:${Versions.PISTON}") + "shade"("net.kyori:adventure-nbt:4.5.0") } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorld.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorld.java index c37535160c..8aead8e81e 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorld.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorld.java @@ -21,7 +21,6 @@ import com.flowpowered.math.vector.Vector3d; import com.flowpowered.math.vector.Vector3i; -import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.entity.BaseEntity; @@ -168,9 +167,12 @@ public > boolean setBlock(BlockVector3 position, B snapshot.restore(true, notifyAndLight ? BlockChangeFlags.ALL : BlockChangeFlags.NONE); // Create the TileEntity - if (block instanceof BaseBlock && ((BaseBlock) block).hasNbtData()) { - // Kill the old TileEntity - world.getTileEntity(pos).ifPresent(tileEntity -> applyTileEntityData(tileEntity, (BaseBlock) block)); + if (block instanceof BaseBlock) { + BaseBlock baseBlock = (BaseBlock) block; + if (baseBlock.getNbtReference() != null) { + // Kill the old TileEntity + world.getTileEntity(pos).ifPresent(tileEntity -> applyTileEntityData(tileEntity, baseBlock)); + } } return true; @@ -301,7 +303,7 @@ public Entity createEntity(Location location, BaseEntity entity) { Vector3d pos = new Vector3d(location.getX(), location.getY(), location.getZ()); org.spongepowered.api.entity.Entity newEnt = world.createEntity(entityType, pos); - if (entity.hasNbtData()) { + if (entity.getNbtReference() != null) { applyEntityData(newEnt, entity); }