Lazily compute NBT

This commit is contained in:
Octavia Togami 2021-02-15 01:49:49 -08:00
parent e1cc6bc948
commit 23a4e2d6fd
No known key found for this signature in database
GPG Key ID: CC364524D1983C99
25 changed files with 192 additions and 174 deletions

View File

@ -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 <B extends BlockStateHolder<B>> 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);
}
}

View File

@ -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);

View File

@ -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<CompoundBinaryTag> 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<CompoundBinaryTag> 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<CompoundBinaryTag> getNbtReference() {
return this.nbtData;
}
@Override
public void setNbt(@Nullable CompoundBinaryTag nbtData) {
public void setNbtReference(@Nullable LazyReference<CompoundBinaryTag> nbtData) {
this.nbtData = nbtData;
}
@Override
public String toString() {
String nbtString = "";
if (hasNbt()) {
LazyReference<CompoundBinaryTag> 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);
}
}

View File

@ -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<CompoundBinaryTag> tag, int amount) {
super(id, tag);
this.amount = amount;
}

View File

@ -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<CompoundBinaryTag> 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<CompoundBinaryTag> 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<CompoundBinaryTag> getNbtReference() {
return nbtData;
}
@Override
public void setNbt(@Nullable CompoundBinaryTag nbtData) {
public void setNbtReference(@Nullable LazyReference<CompoundBinaryTag> nbtData) {
this.nbtData = nbtData;
}

View File

@ -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;

View File

@ -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;

View File

@ -50,7 +50,7 @@ class Int2BaseBlockMap extends AbstractInt2ObjectMap<BaseBlock> {
* @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());

View File

@ -32,6 +32,17 @@ public static <T> LazyReference<T> from(Supplier<T> 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 <T> the type of the value
* @return the new reference
*/
public static <T> LazyReference<T> 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<T> 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() {

View File

@ -17,11 +17,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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 {

View File

@ -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.
*
* <p>{@link #hasNbt()} must return true if and only if method does
* not return null.</p>
* <p>
* This only needs to be used if you don't want to immediately resolve the data.
* Otherwise, you probably want {@link #getNbt()}.
* </p>
*
* @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<CompoundBinaryTag> 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<CompoundBinaryTag> 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<CompoundBinaryTag> 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));
}
}

View File

@ -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<BaseBlock>, TileEntityBlock {
private final BlockState blockState;
@Nullable
private final CompoundBinaryTag nbtData;
private final LazyReference<CompoundBinaryTag> 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<CompoundBinaryTag> nbtData) {
checkNotNull(nbtData);
this.blockState = state;
this.nbtData = nbtData;
@ -115,26 +116,21 @@ public <V> V getState(Property<V> property) {
@Override
public String getNbtId() {
CompoundBinaryTag nbtData = this.nbtData;
LazyReference<CompoundBinaryTag> 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<CompoundBinaryTag> getNbtReference() {
return this.nbtData;
}
@Override
public void setNbt(@Nullable CompoundBinaryTag nbtData) {
public void setNbtReference(@Nullable LazyReference<CompoundBinaryTag> 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<CompoundBinaryTag> 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);
}
}

View File

@ -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<CompoundBinaryTag> compoundTag) {
if (compoundTag == null) {
return toBaseBlock();
}

View File

@ -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<B extends BlockStateHolder<B>> 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<CompoundBinaryTag> 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

View File

@ -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<>();

View File

@ -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)) {

View File

@ -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<>();

View File

@ -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());
}
/**

View File

@ -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;
}

View File

@ -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 {

View File

@ -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()
);
}
/**

View File

@ -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;
}

View File

@ -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 {

View File

@ -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<BinaryTag> list = ListBinaryTag.builder();
int tags = other.size();
for (int i = 0; i < tags; i++) {
BinaryTag child = fromNative(other.remove(0));

View File

@ -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 <B extends BlockStateHolder<B>> 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);
}