From 23a4e2d6fd8936aeeb3fa4e6ec3f8549f2402e27 Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Mon, 15 Feb 2021 01:49:49 -0800 Subject: [PATCH] Lazily compute NBT --- .../sk89q/worldedit/bukkit/BukkitPlayer.java | 12 ++-- .../com/sk89q/worldedit/LocalSession.java | 9 ++- .../com/sk89q/worldedit/blocks/BaseItem.java | 23 +++--- .../sk89q/worldedit/blocks/BaseItemStack.java | 5 +- .../sk89q/worldedit/entity/BaseEntity.java | 20 +++--- .../factory/parser/DefaultItemParser.java | 3 +- .../internal/cui/ServerCUIHandler.java | 1 + .../util/collection/Int2BaseBlockMap.java | 2 +- .../util/concurrency/LazyReference.java | 15 ++++ .../worldedit/util/{ => nbt}/NbtUtils.java | 5 +- .../com/sk89q/worldedit/world/NbtValued.java | 70 ++++++++++--------- .../worldedit/world/block/BaseBlock.java | 50 +++++-------- .../worldedit/world/block/BlockState.java | 13 +--- .../world/block/BlockStateHolder.java | 20 ++++-- .../worldedit/world/chunk/AnvilChunk.java | 21 +++--- .../worldedit/world/chunk/AnvilChunk13.java | 18 +++-- .../sk89q/worldedit/world/chunk/OldChunk.java | 14 ++-- .../sk89q/worldedit/fabric/FabricAdapter.java | 19 +++-- .../sk89q/worldedit/fabric/FabricEntity.java | 3 +- .../sk89q/worldedit/fabric/FabricWorld.java | 2 +- .../sk89q/worldedit/forge/ForgeAdapter.java | 19 +++-- .../sk89q/worldedit/forge/ForgeEntity.java | 6 +- .../com/sk89q/worldedit/forge/ForgeWorld.java | 2 +- .../forge/internal/NBTConverter.java | 2 +- .../sk89q/worldedit/sponge/SpongeWorld.java | 12 ++-- 25 files changed, 192 insertions(+), 174 deletions(-) rename worldedit-core/src/main/java/com/sk89q/worldedit/util/{ => nbt}/NbtUtils.java (90%) 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 487dfb804..95dd3216f 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).hasNbt()) { - BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); - if (adapter != null) { - if (block.getBlockType() == BlockTypes.STRUCTURE_BLOCK) { - adapter.sendFakeNBT(player, pos, ((BaseBlock) block).getNbt()); + 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-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index 3b865ad80..aeda2d98d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -48,6 +48,7 @@ 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; @@ -802,14 +803,16 @@ public void updateServerCUI(Actor actor) { } BaseBlock block = ServerCUIHandler.createStructureBlock(player); - if (block != null && block.hasNbt()) { - // If it's null, we don't need to do anything. The old was already removed. - CompoundBinaryTag tags = block.getNbt(); + if (block != null) { + CompoundBinaryTag tags = Objects.requireNonNull( + block.getNbt(), "createStructureBlock should return nbt" + ); BlockVector3 tempCuiTemporaryBlock = BlockVector3.at( 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 180e80c90..16b979725 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 @@ -21,6 +21,7 @@ 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; @@ -41,7 +42,7 @@ public class BaseItem implements NbtValued { private ItemType itemType; @Nullable - private CompoundBinaryTag nbtData; + private LazyReference nbtData; /** * Construct the object. @@ -61,7 +62,7 @@ public BaseItem(ItemType itemType) { */ @Deprecated public BaseItem(ItemType itemType, @Nullable CompoundTag nbtData) { - this(itemType, nbtData == null ? null : nbtData.asBinaryTag()); + this(itemType, nbtData == null ? null : LazyReference.from(nbtData::asBinaryTag)); } /** @@ -70,7 +71,7 @@ public BaseItem(ItemType itemType, @Nullable CompoundTag nbtData) { * @param itemType Type of the item * @param tag NBT Compound tag */ - public BaseItem(ItemType itemType, @Nullable CompoundBinaryTag tag) { + public BaseItem(ItemType itemType, @Nullable LazyReference tag) { checkNotNull(itemType); this.itemType = itemType; this.nbtData = tag; @@ -94,30 +95,26 @@ public void setType(ItemType itemType) { this.itemType = itemType; } - @Override - public boolean hasNbt() { - return this.nbtData != null; - } - @Nullable @Override - public CompoundBinaryTag getNbt() { + public LazyReference getNbtReference() { return this.nbtData; } @Override - public void setNbt(@Nullable CompoundBinaryTag nbtData) { + public void setNbtReference(@Nullable LazyReference nbtData) { this.nbtData = nbtData; } @Override public String toString() { String nbtString = ""; - if (hasNbt()) { + LazyReference nbtData = this.nbtData; + if (nbtData != null) { try { - nbtString = TagStringIO.get().asString(nbtData); + nbtString = TagStringIO.get().asString(nbtData.getValue()); } catch (IOException e) { - WorldEdit.logger.error("Failed to parse NBT of Item", e); + WorldEdit.logger.error("Failed to serialize NBT of Item", e); } } 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 461dc31df..8d9e4ab07 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,6 +22,7 @@ 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; @@ -61,7 +62,7 @@ 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, CompoundBinaryTag, int)} + * @deprecated Use {@link #BaseItemStack(ItemType, LazyReference, int)} */ @Deprecated public BaseItemStack(ItemType id, CompoundTag tag, int amount) { @@ -76,7 +77,7 @@ public BaseItemStack(ItemType id, CompoundTag tag, int amount) { * @param tag Tag value * @param amount amount in the stack */ - public BaseItemStack(ItemType id, CompoundBinaryTag tag, int amount) { + public BaseItemStack(ItemType id, LazyReference tag, int amount) { super(id, tag); this.amount = amount; } 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 ef26da7b8..ae6d85668 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,7 @@ 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; @@ -45,14 +46,14 @@ public class BaseEntity implements NbtValued { private final EntityType type; @Nullable - private CompoundBinaryTag nbtData; + private LazyReference nbtData; /** * Create a new base entity. * * @param type the entity type * @param nbtData NBT data - * @deprecated Use {@link BaseEntity#BaseEntity(EntityType, CompoundBinaryTag)} + * @deprecated Use {@link BaseEntity#BaseEntity(EntityType, LazyReference)} */ @Deprecated public BaseEntity(EntityType type, CompoundTag nbtData) { @@ -66,9 +67,9 @@ public BaseEntity(EntityType type, CompoundTag nbtData) { * @param type the entity type * @param nbtData NBT data */ - public BaseEntity(EntityType type, CompoundBinaryTag nbtData) { + public BaseEntity(EntityType type, LazyReference nbtData) { this(type); - setNbt(nbtData); + setNbtReference(nbtData); } /** @@ -88,22 +89,17 @@ public BaseEntity(EntityType type) { public BaseEntity(BaseEntity other) { checkNotNull(other); this.type = other.getType(); - setNbt(other.getNbt()); - } - - @Override - public boolean hasNbt() { - return true; + setNbtReference(other.getNbtReference()); } @Nullable @Override - public CompoundBinaryTag getNbt() { + public LazyReference getNbtReference() { return nbtData; } @Override - public void setNbt(@Nullable CompoundBinaryTag 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 2a9d3bf8f..fb7616394 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,6 +30,7 @@ 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; @@ -132,7 +133,7 @@ public BaseItem parseFromInput(String input, ParserContext context) throws Input } } - item = new BaseItem(itemType, itemNbtData); + item = new BaseItem(itemType, itemNbtData == null ? null : LazyReference.computed(itemNbtData)); } return item; 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 162425421..20d52e013 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 @@ -28,6 +28,7 @@ import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.util.nbt.ByteBinaryTag; import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.util.nbt.IntBinaryTag; 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 21d480d69..e3203d28c 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.hasNbt()) { + 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 f755b3fa0..8463cac91 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/NbtUtils.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/nbt/NbtUtils.java similarity index 90% rename from worldedit-core/src/main/java/com/sk89q/worldedit/util/NbtUtils.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/util/nbt/NbtUtils.java index 190526bed..2c032e8bc 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/NbtUtils.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/nbt/NbtUtils.java @@ -17,11 +17,8 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.util; +package com.sk89q.worldedit.util.nbt; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.BinaryTagType; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.storage.InvalidFormatException; public class NbtUtils { 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 c07d23e1b..198a78630 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 @@ -19,10 +19,10 @@ package com.sk89q.worldedit.world; -import com.sk89q.jnbt.AdventureNBTConverter; 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; @@ -39,11 +39,11 @@ public interface NbtValued { * must not return null if this method returns true. * * @return true if there is NBT data - * @deprecated See {@link #hasNbt()} + * @deprecated See {@link #getNbt()} */ @Deprecated default boolean hasNbtData() { - return hasNbt(); + return getNbt() != null; } /** @@ -70,40 +70,20 @@ default CompoundTag getNbtData() { * Set the object's NBT data (tile entity data). * * @param nbtData NBT data, or null if no data - * @deprecated See {@link #setNbt(CompoundBinaryTag)} + * @deprecated See {@link #setNbtReference(LazyReference)} */ @Deprecated default void setNbtData(@Nullable CompoundTag nbtData) { - setNbt(nbtData == null ? null : nbtData.asBinaryTag()); + setNbtReference(nbtData == null ? null : LazyReference.from(nbtData::asBinaryTag)); } /** - * Returns whether the block contains NBT data. {@link #getNbt()} - * must not return null if this method returns true. + * Get the object's NBT data (tile entity data). * - * @return true if there is NBT data - * @apiNote This must be overridden by new subclasses. See {@link NonAbstractForCompatibility} - * for details - */ - @NonAbstractForCompatibility( - delegateName = "hasNbtData", - delegateParams = { } - ) - default boolean hasNbt() { - DeprecationUtil.checkDelegatingOverride(getClass()); - - return hasNbtData(); - } - - /** - * Get the object's NBT data (tile entity data). The returned tag, if - * modified in any way, should be sent to {@link #setNbt(CompoundBinaryTag)} - * so that the instance knows of the changes. Making changes without - * calling {@link #setNbt(CompoundBinaryTag)} could have unintended - * consequences. - * - *

{@link #hasNbt()} must return true if and only if method does - * not return null.

+ *

+ * 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} @@ -114,11 +94,24 @@ default boolean hasNbt() { delegateParams = { } ) @Nullable - default CompoundBinaryTag getNbt() { + default LazyReference getNbtReference() { DeprecationUtil.checkDelegatingOverride(getClass()); CompoundTag nbtData = getNbtData(); - return nbtData == null ? null : nbtData.asBinaryTag(); + 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(); } /** @@ -132,10 +125,19 @@ default CompoundBinaryTag getNbt() { delegateName = "setNbtData", delegateParams = { CompoundTag.class } ) - default void setNbt(@Nullable CompoundBinaryTag nbtData) { + default void setNbtReference(@Nullable LazyReference nbtData) { DeprecationUtil.checkDelegatingOverride(getClass()); - setNbtData(nbtData == null ? null : new CompoundTag(nbtData)); + 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 a488f5905..f0d2adee6 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 @@ -23,6 +23,7 @@ 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; @@ -46,7 +47,7 @@ public class BaseBlock implements BlockStateHolder, TileEntityBlock { private final BlockState blockState; @Nullable - private final CompoundBinaryTag nbtData; + private final LazyReference nbtData; /** * Construct a block with a state. @@ -66,7 +67,7 @@ protected BaseBlock(BlockState blockState) { */ @Deprecated protected BaseBlock(BlockState state, CompoundTag nbtData) { - this(state, checkNotNull(nbtData).asBinaryTag()); + this(state, LazyReference.from(checkNotNull(nbtData)::asBinaryTag)); } @@ -76,7 +77,7 @@ protected BaseBlock(BlockState state, CompoundTag nbtData) { * @param state The block state * @param nbtData NBT data, which must be provided */ - protected BaseBlock(BlockState state, CompoundBinaryTag nbtData) { + protected BaseBlock(BlockState state, LazyReference nbtData) { checkNotNull(nbtData); this.blockState = state; this.nbtData = nbtData; @@ -115,26 +116,21 @@ public V getState(Property property) { @Override public String getNbtId() { - CompoundBinaryTag nbtData = this.nbtData; + LazyReference nbtData = this.nbtData; if (nbtData == null) { return ""; } - return nbtData.getString("id"); - } - - @Override - public boolean hasNbt() { - return this.nbtData != null; + return nbtData.getValue().getString("id"); } @Nullable @Override - public CompoundBinaryTag getNbt() { + public LazyReference getNbtReference() { return this.nbtData; } @Override - public void setNbt(@Nullable CompoundBinaryTag nbtData) { + public void setNbtReference(@Nullable LazyReference nbtData) { throw new UnsupportedOperationException("This class is immutable."); } @@ -144,7 +140,7 @@ public void setNbt(@Nullable CompoundBinaryTag nbtData) { @Override public boolean equals(Object o) { if (!(o instanceof BaseBlock)) { - if (!hasNbt() && o instanceof BlockStateHolder) { + if (nbtData == null && o instanceof BlockStateHolder) { return Objects.equals(toImmutableState(), ((BlockStateHolder) o).toImmutableState()); } return false; @@ -176,22 +172,8 @@ public BaseBlock toBaseBlock() { return this; } - @Deprecated @Override - public BaseBlock toBaseBlock(CompoundTag compoundTag) { - if (compoundTag == null) { - return this.blockState.toBaseBlock(); - } else if (compoundTag.asBinaryTag() == this.nbtData) { - // The above reference equality check is fine, as JNBT classes contain an internal - // Adventure reference. - return this; - } else { - return new BaseBlock(this.blockState, compoundTag); - } - } - - @Override - public BaseBlock toBaseBlock(CompoundBinaryTag compoundTag) { + public BaseBlock toBaseBlock(LazyReference compoundTag) { if (compoundTag == null) { return this.blockState.toBaseBlock(); } else if (compoundTag == this.nbtData) { @@ -204,8 +186,9 @@ public BaseBlock toBaseBlock(CompoundBinaryTag compoundTag) { @Override public int hashCode() { int ret = toImmutableState().hashCode() << 3; - if (hasNbt()) { - ret += getNbt().hashCode(); + CompoundBinaryTag nbtData = getNbt(); + if (nbtData != null) { + ret += nbtData.hashCode(); } return ret; } @@ -213,11 +196,12 @@ public int hashCode() { @Override public String toString() { String nbtString = ""; - if (hasNbt()) { + CompoundBinaryTag nbtData = getNbt(); + if (nbtData != null) { try { - nbtString = TagStringIO.get().asString(getNbt()); + nbtString = TagStringIO.get().asString(nbtData); } catch (IOException e) { - WorldEdit.logger.error("Failed to parse NBT of Block", e); + WorldEdit.logger.error("Failed to serialize NBT of Block", e); } } 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 be4584b03..61ece4439 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,10 @@ 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; @@ -211,17 +211,8 @@ public BaseBlock toBaseBlock() { return this.emptyBaseBlock; } - @Deprecated @Override - public BaseBlock toBaseBlock(CompoundTag compoundTag) { - if (compoundTag == null) { - return toBaseBlock(); - } - return new BaseBlock(this, compoundTag); - } - - @Override - public BaseBlock toBaseBlock(CompoundBinaryTag 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 0c11bb833..e45544101 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 @@ -19,13 +19,13 @@ package com.sk89q.worldedit.world.block; -import com.sk89q.jnbt.AdventureNBTConverter; 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; @@ -92,11 +92,11 @@ public interface BlockStateHolder> extends Pattern * * @param compoundTag The NBT Data to apply * @return The BaseBlock - * @deprecated Use {@link BlockStateHolder#toBaseBlock(CompoundBinaryTag)}. + * @deprecated Use {@link BlockStateHolder#toBaseBlock(LazyReference)}. */ @Deprecated default BaseBlock toBaseBlock(CompoundTag compoundTag) { - return toBaseBlock(compoundTag == null ? null : compoundTag.asBinaryTag()); + return toBaseBlock(compoundTag == null ? null : LazyReference.from(compoundTag::asBinaryTag)); } /** @@ -111,10 +111,22 @@ default BaseBlock toBaseBlock(CompoundTag compoundTag) { 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 : new CompoundTag(compoundTag)); + return toBaseBlock(compoundTag == null ? null : LazyReference.computed(compoundTag)); } @Override 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 8ecd71034..f45f0eb91 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 @@ -22,13 +22,12 @@ import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.util.NbtUtils; 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.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; @@ -72,14 +71,14 @@ public AnvilChunk(CompoundTag tag) throws DataException { public AnvilChunk(CompoundBinaryTag tag) throws DataException { rootTag = tag; - rootX = NbtUtils.getChildTag(rootTag, "xPos", IntBinaryTag.class).value(); - rootZ = NbtUtils.getChildTag(rootTag, "zPos", IntBinaryTag.class).value(); + 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]; - ListBinaryTag sections = NbtUtils.getChildTag(rootTag, "Sections", ListBinaryTag.class); + ListBinaryTag sections = NbtUtils.getChildTag(rootTag, "Sections", BinaryTagTypes.LIST); for (BinaryTag rawSectionTag : sections) { if (!(rawSectionTag instanceof CompoundBinaryTag)) { @@ -91,20 +90,20 @@ public AnvilChunk(CompoundBinaryTag tag) throws DataException { continue; // Empty section. } - int y = NbtUtils.getChildTag(sectionTag, "Y", ByteBinaryTag.class).value(); + int y = NbtUtils.getChildTag(sectionTag, "Y", BinaryTagTypes.BYTE).value(); if (y < 0 || y >= 16) { continue; } blocks[y] = NbtUtils.getChildTag(sectionTag, - "Blocks", ByteArrayBinaryTag.class).value(); + "Blocks", BinaryTagTypes.BYTE_ARRAY).value(); data[y] = NbtUtils.getChildTag(sectionTag, "Data", - ByteArrayBinaryTag.class).value(); + BinaryTagTypes.BYTE_ARRAY).value(); // 4096 ID block support if (sectionTag.get("Add") != null) { blocksAdd[y] = NbtUtils.getChildTag(sectionTag, - "Add", ByteArrayBinaryTag.class).value(); + "Add", BinaryTagTypes.BYTE_ARRAY).value(); } } @@ -191,7 +190,7 @@ private int getBlockData(BlockVector3 position) throws DataException { * Used to load the tile entities. */ private void populateTileEntities() throws DataException { - ListBinaryTag tags = NbtUtils.getChildTag(rootTag, "TileEntities", ListBinaryTag.class); + ListBinaryTag tags = NbtUtils.getChildTag(rootTag, "TileEntities", BinaryTagTypes.LIST); tileEntities = new HashMap<>(); 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 dd3bfdbe6..cb9479135 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 @@ -22,14 +22,12 @@ import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.registry.state.Property; -import com.sk89q.worldedit.util.NbtUtils; import com.sk89q.worldedit.util.nbt.BinaryTag; import com.sk89q.worldedit.util.nbt.BinaryTagTypes; -import com.sk89q.worldedit.util.nbt.ByteBinaryTag; 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.LongArrayBinaryTag; +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; @@ -75,12 +73,12 @@ public AnvilChunk13(CompoundTag tag) throws DataException { public AnvilChunk13(CompoundBinaryTag tag) throws DataException { rootTag = tag; - rootX = NbtUtils.getChildTag(rootTag, "xPos", IntBinaryTag.class).value(); - rootZ = NbtUtils.getChildTag(rootTag, "zPos", IntBinaryTag.class).value(); + rootX = NbtUtils.getChildTag(rootTag, "xPos", BinaryTagTypes.INT).value(); + rootZ = NbtUtils.getChildTag(rootTag, "zPos", BinaryTagTypes.INT).value(); blocks = new BlockState[16][]; - ListBinaryTag sections = NbtUtils.getChildTag(rootTag, "Sections", ListBinaryTag.class); + ListBinaryTag sections = NbtUtils.getChildTag(rootTag, "Sections", BinaryTagTypes.LIST); for (BinaryTag rawSectionTag : sections) { if (!(rawSectionTag instanceof CompoundBinaryTag)) { @@ -92,7 +90,7 @@ public AnvilChunk13(CompoundBinaryTag tag) throws DataException { continue; // Empty section. } - int y = NbtUtils.getChildTag(sectionTag, "Y", ByteBinaryTag.class).value(); + int y = NbtUtils.getChildTag(sectionTag, "Y", BinaryTagTypes.BYTE).value(); if (y < 0 || y >= 16) { continue; } @@ -112,7 +110,7 @@ public AnvilChunk13(CompoundBinaryTag tag) throws DataException { } BlockState blockState = type.getDefaultState(); if (paletteEntry.get("Properties") != null) { - CompoundBinaryTag properties = NbtUtils.getChildTag(paletteEntry, "Properties", CompoundBinaryTag.class); + CompoundBinaryTag properties = NbtUtils.getChildTag(paletteEntry, "Properties", BinaryTagTypes.COMPOUND); for (Property property : blockState.getStates().keySet()) { if (properties.get(property.getName()) != null) { String value = properties.getString(property.getName()); @@ -128,7 +126,7 @@ public AnvilChunk13(CompoundBinaryTag tag) throws DataException { } // parse block states - long[] blockStatesSerialized = NbtUtils.getChildTag(sectionTag, "BlockStates", LongArrayBinaryTag.class).value(); + long[] blockStatesSerialized = NbtUtils.getChildTag(sectionTag, "BlockStates", BinaryTagTypes.LONG_ARRAY).value(); BlockState[] chunkSectionBlocks = new BlockState[16 * 16 * 16]; blocks[y] = chunkSectionBlocks; @@ -183,7 +181,7 @@ private void populateTileEntities() throws DataException { if (rootTag.get("TileEntities") == null) { return; } - ListBinaryTag tags = NbtUtils.getChildTag(rootTag, "TileEntities", ListBinaryTag.class); + ListBinaryTag tags = NbtUtils.getChildTag(rootTag, "TileEntities", BinaryTagTypes.LIST); for (BinaryTag tag : tags) { if (!(tag instanceof CompoundBinaryTag)) { 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 fa4288885..83f695ed1 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 @@ -22,12 +22,12 @@ import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.util.NbtUtils; import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.ByteArrayBinaryTag; +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; @@ -73,10 +73,10 @@ public OldChunk(CompoundTag tag) throws DataException { public OldChunk(CompoundBinaryTag tag) throws DataException { rootTag = tag; - blocks = NbtUtils.getChildTag(rootTag, "Blocks", ByteArrayBinaryTag.class).value(); - data = NbtUtils.getChildTag(rootTag, "Data", ByteArrayBinaryTag.class).value(); - rootX = NbtUtils.getChildTag(rootTag, "xPos", IntBinaryTag.class).value(); - rootZ = NbtUtils.getChildTag(rootTag, "zPos", IntBinaryTag.class).value(); + 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) { @@ -96,7 +96,7 @@ public OldChunk(CompoundBinaryTag tag) throws DataException { * @throws DataException if there is an error getting the chunk data */ private void populateTileEntities() throws DataException { - ListBinaryTag tags = NbtUtils.getChildTag(rootTag, "TileEntities", ListBinaryTag.class); + ListBinaryTag tags = NbtUtils.getChildTag(rootTag, "TileEntities", BinaryTagTypes.LIST); tileEntities = new HashMap<>(); 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 21d050b26..4823eb806 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 @@ -30,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.util.nbt.BinaryTag; import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.World; @@ -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; @@ -237,18 +240,22 @@ public static ItemStack adapt(BaseItemStack baseItemStack) { } public static BaseItemStack adapt(ItemStack itemStack) { - CompoundBinaryTag tag = NBTConverter.fromNative(itemStack.toTag(new net.minecraft.nbt.CompoundTag())); - if (tag.keySet().isEmpty()) { + CompoundTag tag = itemStack.toTag(new CompoundTag()); + if (tag.isEmpty()) { tag = null; } else { - final BinaryTag tagTag = tag.get("tag"); - if (tagTag instanceof CompoundBinaryTag) { - tag = ((CompoundBinaryTag) tagTag); + 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/FabricEntity.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntity.java index 02ac3a4a8..cd88c721d 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/FabricWorld.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java index 5bf412edc..f2958f325 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 @@ -248,7 +248,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.getNbt(), 1)); + ItemStack stack = FabricAdapter.adapt(new BaseItemStack(item.getType(), item.getNbtReference(), 1)); ServerWorld world = (ServerWorld) getWorld(); final WorldEditFakePlayer fakePlayer; try { 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 ba02cfa1a..c18a39202 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 @@ -30,8 +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.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; +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; @@ -233,18 +233,23 @@ public static ItemStack adapt(BaseItemStack baseItemStack) { } public static BaseItemStack adapt(ItemStack itemStack) { - CompoundBinaryTag tag = NBTConverter.fromNative(itemStack.serializeNBT()); + CompoundNBT tag = itemStack.serializeNBT(); if (tag.keySet().isEmpty()) { tag = null; } else { - final BinaryTag tagTag = tag.get("tag"); - if (tagTag instanceof CompoundBinaryTag) { - tag = ((CompoundBinaryTag) 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/ForgeEntity.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntity.java index 521835dcc..623e5a30d 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/ForgeWorld.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java index 2eb64dede..ccdc813a3 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 @@ -253,7 +253,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.getNbt(), 1)); + ItemStack stack = ForgeAdapter.adapt(new BaseItemStack(item.getType(), item.getNbtReference(), 1)); ServerWorld world = (ServerWorld) getWorld(); final WorldEditFakePlayer fakePlayer; try { 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 4f76306bc..693369a71 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 @@ -211,7 +211,7 @@ public static IntArrayBinaryTag fromNative(IntArrayNBT other) { public static ListBinaryTag fromNative(ListNBT other) { other = other.copy(); - ListBinaryTag.Builder list = ListBinaryTag.builder(); + ListBinaryTag.Builder list = ListBinaryTag.builder(); int tags = other.size(); for (int i = 0; i < tags; i++) { BinaryTag child = fromNative(other.remove(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 540808475..8aead8e81 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).hasNbt()) { - // 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.hasNbt()) { + if (entity.getNbtReference() != null) { applyEntityData(newEnt, entity); }