Reorder BuildInClipboardFormat and document changed JNBT classes (#807)

* Get rid of FastSchematicReader/Writer and document changed JNBT classes

This commit includes changes from upstream to the schematic classes
(`com.sk89q.worldedit.extent.clipboard.io`). It also documents the JNBT
classes, specifying what has been changed in FAWE. This was done in preparation
for the upcoming move to adventure-nbt.

The PlotSquared schematic handler classes will now use SpongeSchematicReader/Writer rather than FastSchematicReader/Writer.

This is yet untested and the entire branch is a W.I.P.

* Fix JNBT mutability misuse in FAWE

FAWE previously had mutable compound and list tags. The previous commit changed that, and this commit will fix misuse of the tag API.

I've tried to identify the places where mutability was assumed, but I might have missed something. This needs quite extensive testing.

This is yet another change which increases upstream compatibility in FAWE.

* Fix FAWE_Spigot_<..>#getEntity

* Fix JNBT usage in the AsyncBlockState code

* Readd FastSchematicReader/Writer and add a new schematic format (`FAST`)

* Update dead repository

* Implement missing AsyncChunk#getTileEntities

* handle entities properly and add "brokenentity" format

* Fix fast schematic reader
lazily reading means it's read in order of appearance in the inputstream so we need to read schematic version first (skip past everything) and then reset the stream

* Fix p2 FAWE

* Go back to fast schematics in P2/CompressedSchematicTag (#819)

* Fix compile

Co-authored-by: N0tMyFaultOG <mc.cache@web.de>
Co-authored-by: Alexander Söderberg <Sauilitired@users.noreply.github.com>
Co-authored-by: dordsor21 <dordsor21@gmail.com>
Co-authored-by: Aurora <aurora@relanet.eu>
This commit is contained in:
Alexander Söderberg
2021-01-04 19:18:23 +01:00
committed by GitHub
parent efcca5b66f
commit 3f0b9a2a92
56 changed files with 559 additions and 995 deletions

View File

@ -12,15 +12,18 @@ import net.minecraft.server.v1_15_R1.NBTTagList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public class LazyCompoundTag_1_15_2 extends CompoundTag {
private final Supplier<NBTTagCompound> nmsTag;
private CompoundTag cachedValue;
public LazyCompoundTag_1_15_2(Supplier<NBTTagCompound> tag) {
super(null);
super(new HashMap<>());
this.nmsTag = tag;
}
@ -34,12 +37,10 @@ public class LazyCompoundTag_1_15_2 extends CompoundTag {
@Override
public Map<String, Tag> getValue() {
Map<String, Tag> value = super.getValue();
if (value == null) {
Tag tag = WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(nmsTag.get());
setValue(((CompoundTag) tag).getValue());
if (cachedValue == null) {
cachedValue = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(nmsTag.get());
}
return super.getValue();
return cachedValue.getValue();
}
public boolean containsKey(String key) {
@ -149,4 +150,4 @@ public class LazyCompoundTag_1_15_2 extends CompoundTag {
public String toString() {
return nmsTag.get().toString();
}
}
}

View File

@ -12,15 +12,18 @@ import net.minecraft.server.v1_16_R1.NBTTagList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public class LazyCompoundTag_1_16_1 extends CompoundTag {
private final Supplier<NBTTagCompound> nmsTag;
private CompoundTag cachedValue;
public LazyCompoundTag_1_16_1(Supplier<NBTTagCompound> tag) {
super(null);
super(new HashMap<>());
this.nmsTag = tag;
}
@ -34,12 +37,10 @@ public class LazyCompoundTag_1_16_1 extends CompoundTag {
@Override
public Map<String, Tag> getValue() {
Map<String, Tag> value = super.getValue();
if (value == null) {
Tag tag = WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(nmsTag.get());
setValue(((CompoundTag) tag).getValue());
if (cachedValue == null) {
cachedValue = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(nmsTag.get());
}
return super.getValue();
return cachedValue.getValue();
}
public boolean containsKey(String key) {

View File

@ -12,15 +12,18 @@ import net.minecraft.server.v1_16_R2.NBTTagList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public class LazyCompoundTag_1_16_2 extends CompoundTag {
private final Supplier<NBTTagCompound> nmsTag;
private CompoundTag cachedValue;
public LazyCompoundTag_1_16_2(Supplier<NBTTagCompound> tag) {
super(null);
super(new HashMap<>());
this.nmsTag = tag;
}
@ -34,12 +37,10 @@ public class LazyCompoundTag_1_16_2 extends CompoundTag {
@Override
public Map<String, Tag> getValue() {
Map<String, Tag> value = super.getValue();
if (value == null) {
Tag tag = WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(nmsTag.get());
setValue(((CompoundTag) tag).getValue());
if (cachedValue == null) {
cachedValue = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(nmsTag.get());
}
return super.getValue();
return cachedValue.getValue();
}
public boolean containsKey(String key) {

View File

@ -12,15 +12,18 @@ import net.minecraft.server.v1_16_R3.NBTTagList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public class LazyCompoundTag_1_16_4 extends CompoundTag {
private final Supplier<NBTTagCompound> nmsTag;
private CompoundTag cachedValue;
public LazyCompoundTag_1_16_4(Supplier<NBTTagCompound> tag) {
super(null);
super(new HashMap<>());
this.nmsTag = tag;
}
@ -34,12 +37,10 @@ public class LazyCompoundTag_1_16_4 extends CompoundTag {
@Override
public Map<String, Tag> getValue() {
Map<String, Tag> value = super.getValue();
if (value == null) {
Tag tag = WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(nmsTag.get());
setValue(((CompoundTag) tag).getValue());
if (cachedValue == null) {
cachedValue = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(nmsTag.get());
}
return super.getValue();
return cachedValue.getValue();
}
public boolean containsKey(String key) {

View File

@ -1,6 +1,5 @@
package com.boydti.fawe.bukkit.regions.plotsquared;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.clipboard.ReadOnlyClipboard;
import com.boydti.fawe.object.io.PGZIPOutputStream;
@ -16,10 +15,10 @@ import com.plotsquared.core.util.SchematicHandler;
import com.plotsquared.core.util.task.RunnableVal;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.CompressedCompoundTag;
import com.sk89q.jnbt.CompressedSchematicTag;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.Tag;
import com.sk89q.jnbt.fawe.CompressedSchematicTag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;

View File

@ -15,7 +15,7 @@ import com.github.intellectualsites.plotsquared.plot.util.SchematicHandler;
import com.github.intellectualsites.plotsquared.plot.util.block.LocalBlockQueue;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.CompressedCompoundTag;
import com.sk89q.jnbt.CompressedSchematicTag;
import com.sk89q.jnbt.fawe.CompressedSchematicTag;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.EditSession;
@ -65,6 +65,7 @@ public class FaweSchematicHandler extends SchematicHandler {
ReadOnlyClipboard clipboard = ReadOnlyClipboard.of(editSession, region, false, true);
Clipboard holder = new BlockArrayClipboard(region, clipboard);
CompressedSchematicTag tag = new CompressedSchematicTag(holder);
whenDone.run(tag);
});

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.bukkit.wrapper;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.world.block.BaseBlock;
@ -16,8 +17,12 @@ import org.bukkit.material.MaterialData;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class AsyncBlockState implements BlockState {
@ -25,10 +30,6 @@ public class AsyncBlockState implements BlockState {
private BlockData blockData;
private final AsyncBlock block;
public AsyncBlockState(AsyncBlock block) {
this(block, block.world.getFullBlock(block.x, block.y, block.z));
}
public AsyncBlockState(AsyncBlock block, BaseBlock state) {
this.state = state;
this.block = block;
@ -112,11 +113,11 @@ public class AsyncBlockState implements BlockState {
@Override
public void setBlockData(BlockData blockData) {
this.blockData = blockData;
CompoundTag nbt = state.getNbtData();
CompoundTag nbt = this.getNbtData();
BlockType oldType = state.getBlockType();
com.sk89q.worldedit.world.block.BlockState newState = BukkitAdapter.adapt(blockData);
if (nbt != null && newState.getBlockType() == oldType) {
state = newState.toBaseBlock(nbt);
this.setNbtData(nbt);
} else {
state = newState.toBaseBlock();
}
@ -146,14 +147,47 @@ public class AsyncBlockState implements BlockState {
}
}
public CompoundTag getNbtData() {
/**
* Returns the (unmodifiable) tag compound that belongs to this block state.
* If the block state is null, this will return null.
*
* @return NBT data
*/
public synchronized @Nullable CompoundTag getNbtData() {
if (this.state == null) {
return null;
}
return state.getNbtData();
}
public void setNbtData(CompoundTag nbt) {
/**
* Clone the NBT {@link CompoundTag} into a new {@link Map}.
*
* @return Modifiable clone of NBT data
*/
public @NotNull Map<String, Tag> cloneNbtMap() {
return Optional.ofNullable(this.getNbtData()).map(CompoundTag::getValue)
.map(HashMap::new).orElse(new HashMap<>());
}
/**
* Set the NBT data of the block.
*
* @param nbt New NBT data
*/
public synchronized void setNbtData(@Nullable final CompoundTag nbt) {
state = this.state.toBaseBlock(nbt);
}
/**
* Set the NBT data of the block.
*
* @param map New NBT data
*/
public void setNbtData(@NotNull final Map<String, Tag> map) {
this.setNbtData(new CompoundTag(map));
}
@Override
public byte getRawData() {
return (byte) (state.getInternalId() >> BlockTypesCache.BIT_OFFSET);
@ -163,7 +197,7 @@ public class AsyncBlockState implements BlockState {
public void setRawData(byte data) {
int combinedId = getTypeId() + (data << BlockTypesCache.BIT_OFFSET);
state = com.sk89q.worldedit.world.block.BlockState.getFromInternalId(combinedId)
.toBaseBlock(state.getNbtData());
.toBaseBlock(this.getNbtData());
this.blockData = BukkitAdapter.adapt(state);
}

View File

@ -16,17 +16,24 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
public final class AsyncDataContainer implements PersistentDataContainer {
private final CompoundTag root;
public AsyncDataContainer(CompoundTag root) {
this.root = root;
private final Supplier<CompoundTag> supplier;
private final Consumer<CompoundTag> consumer;
public AsyncDataContainer(
final @NotNull Supplier<CompoundTag> supplier,
final @NotNull Consumer<CompoundTag> consumer
) {
this.supplier = supplier;
this.consumer = consumer;
}
private CompoundTag root() {
CompoundTag value = (CompoundTag) root.getValue().get("PublicBukkitValues");
return value;
return (CompoundTag) supplier.get().getValue().get("PublicBukkitValues");
}
private Map<String, Tag> get() {
@ -40,8 +47,9 @@ public final class AsyncDataContainer implements PersistentDataContainer {
if (!create) {
return Collections.emptyMap();
}
Map<String, Tag> map = root.getValue();
final Map<String, Tag> map = new HashMap<>(root().getValue());
map.put("PublicBukkitValues", new CompoundTag(raw = new HashMap<>()));
this.consumer.accept(new CompoundTag(map));
} else {
raw = tag.getValue();
}
@ -52,7 +60,14 @@ public final class AsyncDataContainer implements PersistentDataContainer {
Validate.notNull(key, "The provided key for the custom value was null");
Validate.notNull(type, "The provided type for the custom value was null");
Validate.notNull(value, "The provided value for the custom value was null");
get().put(key.toString(), FaweCache.IMP.asTag(type.toPrimitive(value, null)));
// Modify public values
final Map<String, Tag> publicValues = new HashMap<>(this.get());
publicValues.put(key.toString(), FaweCache.IMP.asTag(type.toPrimitive(value, null)));
// Modify the root tag
final Map<String, Tag> map = new HashMap<>(root().getValue());
map.put("PublicBukkitValues", new CompoundTag(publicValues));
// Update the owning object
this.consumer.accept(new CompoundTag(map));
}
public <T, Z> boolean has(NamespacedKey key, PersistentDataType<T, Z> type) {
@ -60,7 +75,7 @@ public final class AsyncDataContainer implements PersistentDataContainer {
Validate.notNull(type, "The provided type for the custom value was null");
Tag value = get(false).get(key.toString());
if (value == null) {
return type == null;
return false;
}
return type.getPrimitiveType() == value.getValue().getClass();
}
@ -93,7 +108,14 @@ public final class AsyncDataContainer implements PersistentDataContainer {
public void remove(NamespacedKey key) {
Validate.notNull(key, "The provided key for the custom value was null");
get(false).remove(key.toString());
// Modify public values
final Map<String, Tag> publicValues = new HashMap<>(this.get(false));
publicValues.remove(key.toString());
// Modify the root tag
final Map<String, Tag> map = new HashMap<>(root().getValue());
map.put("PublicBukkitValues", new CompoundTag(publicValues));
// Update the owning object
this.consumer.accept(new CompoundTag(map));
}
public boolean isEmpty() {

View File

@ -19,6 +19,7 @@ import java.util.Locale;
import java.util.Map;
public class AsyncSign extends AsyncBlockState implements Sign {
public AsyncSign(AsyncBlock block, BaseBlock state) {
super(block, state);
}
@ -59,11 +60,12 @@ public class AsyncSign extends AsyncBlockState implements Sign {
@Override
public void setLine(int index, String line) throws IndexOutOfBoundsException {
CompoundTag nbt = getNbtData();
if (nbt != null) {
Map<String, Tag> map = nbt.getValue();
map.put("Text" + (index + 1), new StringTag(toJson(line)));
final Map<String, Tag> map = this.cloneNbtMap();
if (map.isEmpty()) {
return;
}
map.put("Text" + (index + 1), new StringTag(toJson(line)));
this.setNbtData(map);
}
@Override
@ -79,13 +81,13 @@ public class AsyncSign extends AsyncBlockState implements Sign {
@Override
@NotNull
public PersistentDataContainer getPersistentDataContainer() {
return new AsyncDataContainer(getNbtData());
return new AsyncDataContainer(this::getNbtData, this::setNbtData);
}
@Override
@Nullable
public DyeColor getColor() {
CompoundTag nbt = getNbtData();
CompoundTag nbt = this.getNbtData();
if (nbt != null) {
String color = nbt.getString("Color").toUpperCase(Locale.ROOT);
if (!color.isEmpty()) {
@ -97,10 +99,11 @@ public class AsyncSign extends AsyncBlockState implements Sign {
@Override
public void setColor(DyeColor color) {
CompoundTag nbt = getNbtData();
if (nbt != null) {
Map<String, Tag> map = nbt.getValue();
map.put("Color", new StringTag(color.name().toLowerCase(Locale.ROOT)));
final Map<String, Tag> map = this.cloneNbtMap();
if (map.isEmpty()) {
return;
}
map.put("Color", new StringTag(color.name().toLowerCase(Locale.ROOT)));
this.setNbtData(map);
}
}

View File

@ -19,7 +19,6 @@
package com.sk89q.worldedit.bukkit.adapter.impl;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.implementation.packet.ChunkPacket;
@ -93,15 +92,15 @@ import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.util.OptionalInt;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
public final class FAWE_Spigot_v1_15_R2 extends CachedBukkitAdapter implements IDelegateBukkitImplAdapter<NBTBase> {
@ -271,13 +270,13 @@ public final class FAWE_Spigot_v1_15_R2 extends CachedBukkitAdapter implements I
if (id != null) {
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundTag> saveTag = () -> {
NBTTagCompound tag = new NBTTagCompound();
readEntityIntoTag(mcEntity, tag);
final NBTTagCompound minecraftTag = new NBTTagCompound();
readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work
CompoundTag natve = (CompoundTag) toNative(tag);
natve.getValue().put("Id", new StringTag(id));
return natve;
final CompoundTag tag = (CompoundTag) toNative(minecraftTag);
final Map<String, Tag> tags = new HashMap<>(tag.getValue());
tags.put("Id", new StringTag(id));
return new CompoundTag(tags);
};
return new LazyBaseEntity(type, saveTag);
} else {
@ -351,7 +350,6 @@ public final class FAWE_Spigot_v1_15_R2 extends CachedBukkitAdapter implements I
}
}
}
public int ordinalToIbdID(char ordinal) {
synchronized (this) {
try {

View File

@ -92,15 +92,15 @@ import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.util.OptionalInt;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
public final class FAWE_Spigot_v1_16_R1 extends CachedBukkitAdapter implements IDelegateBukkitImplAdapter<NBTBase> {
@ -270,13 +270,13 @@ public final class FAWE_Spigot_v1_16_R1 extends CachedBukkitAdapter implements I
if (id != null) {
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundTag> saveTag = () -> {
NBTTagCompound tag = new NBTTagCompound();
readEntityIntoTag(mcEntity, tag);
final NBTTagCompound minecraftTag = new NBTTagCompound();
readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work
CompoundTag natve = (CompoundTag) toNative(tag);
natve.getValue().put("Id", new StringTag(id));
return natve;
final CompoundTag tag = (CompoundTag) toNative(minecraftTag);
final Map<String, Tag> tags = new HashMap<>(tag.getValue());
tags.put("Id", new StringTag(id));
return new CompoundTag(tags);
};
return new LazyBaseEntity(type, saveTag);
} else {

View File

@ -92,15 +92,16 @@ import org.bukkit.craftbukkit.v1_16_R2.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.util.OptionalInt;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
public final class FAWE_Spigot_v1_16_R2 extends CachedBukkitAdapter implements IDelegateBukkitImplAdapter<NBTBase> {
@ -271,13 +272,13 @@ public final class FAWE_Spigot_v1_16_R2 extends CachedBukkitAdapter implements I
if (id != null) {
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundTag> saveTag = () -> {
NBTTagCompound tag = new NBTTagCompound();
readEntityIntoTag(mcEntity, tag);
final NBTTagCompound minecraftTag = new NBTTagCompound();
readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work
CompoundTag natve = (CompoundTag) toNative(tag);
natve.getValue().put("Id", new StringTag(id));
return natve;
final CompoundTag tag = (CompoundTag) toNative(minecraftTag);
final Map<String, Tag> tags = new HashMap<>(tag.getValue());
tags.put("Id", new StringTag(id));
return new CompoundTag(tags);
};
return new LazyBaseEntity(type, saveTag);
} else {
@ -351,7 +352,6 @@ public final class FAWE_Spigot_v1_16_R2 extends CachedBukkitAdapter implements I
}
}
}
public int ordinalToIbdID(char ordinal) {
synchronized (this) {
try {

View File

@ -19,7 +19,6 @@
package com.sk89q.worldedit.bukkit.adapter.impl;
import com.bekvon.bukkit.residence.commands.material;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.implementation.packet.ChunkPacket;
@ -96,6 +95,7 @@ import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.util.OptionalInt;
import java.util.Set;
@ -272,13 +272,13 @@ public final class FAWE_Spigot_v1_16_R3 extends CachedBukkitAdapter implements I
if (id != null) {
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundTag> saveTag = () -> {
NBTTagCompound tag = new NBTTagCompound();
readEntityIntoTag(mcEntity, tag);
final NBTTagCompound minecraftTag = new NBTTagCompound();
readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work
CompoundTag natve = (CompoundTag) toNative(tag);
natve.getValue().put("Id", new StringTag(id));
return natve;
final CompoundTag tag = (CompoundTag) toNative(minecraftTag);
final Map<String, Tag> tags = new HashMap<>(tag.getValue());
tags.put("Id", new StringTag(id));
return new CompoundTag(tags);
};
return new LazyBaseEntity(type, saveTag);
} else {