diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java index fa2444a2a..581905974 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java @@ -109,12 +109,20 @@ public class CraftBlockEntityState extends CraftBlockState return snapshot.saveWithFullMetadata(getRegistryAccess()); } - public NBTTagCompound getSnapshotNBTWithoutComponents() { - NBTTagCompound nbt = getSnapshotNBT(); + public NBTTagCompound getItemNBT() { + // update snapshot + applyTo(snapshot); + + // See TileEntity#saveToItem + NBTTagCompound nbt = snapshot.saveCustomOnly(getRegistryAccess()); snapshot.removeComponentsFromTag(nbt); return nbt; } + public void addEntityType(NBTTagCompound nbt) { + TileEntity.addEntityType(nbt, snapshot.getType()); + } + // gets the packet data of the TileEntity represented by this block state public NBTTagCompound getUpdateNBT() { // update snapshot diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java index 42b812b03..487d07b83 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java @@ -26,6 +26,7 @@ import org.bukkit.craftbukkit.block.CraftBlockEntityState; import org.bukkit.craftbukkit.block.CraftBlockStates; import org.bukkit.craftbukkit.util.CraftMagicNumbers; import org.bukkit.inventory.meta.BlockStateMeta; +import org.bukkit.util.BlockVector; @DelegateDeserialization(SerializableMeta.class) public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta { @@ -55,6 +56,7 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta final Material material; private CraftBlockEntityState blockEntityTag; + private BlockVector position; private NBTTagCompound internalTag; CraftMetaBlockState(CraftMetaItem meta, Material material) { @@ -69,14 +71,20 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta CraftMetaBlockState te = (CraftMetaBlockState) meta; this.blockEntityTag = te.blockEntityTag; + this.position = te.position; } CraftMetaBlockState(DataComponentPatch tag, Material material) { super(tag); this.material = material; - getOrEmpty(tag, BLOCK_ENTITY_TAG).ifPresent((nbt) -> { - blockEntityTag = getBlockState(material, nbt.copyTag()); + getOrEmpty(tag, BLOCK_ENTITY_TAG).ifPresent((blockTag) -> { + NBTTagCompound nbt = blockTag.copyTag(); + + blockEntityTag = getBlockState(material, nbt); + if (nbt.contains("x", CraftMagicNumbers.NBT.TAG_ANY_NUMBER) && nbt.contains("y", CraftMagicNumbers.NBT.TAG_ANY_NUMBER) && nbt.contains("z", CraftMagicNumbers.NBT.TAG_ANY_NUMBER)) { + position = new BlockVector(nbt.getInt("x"), nbt.getInt("y"), nbt.getInt("z")); + } }); if (!tag.isEmpty()) { @@ -114,19 +122,39 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta blockEntityTag = getBlockState(material, internalTag); internalTag = null; } + position = SerializableMeta.getObject(BlockVector.class, map, "blockPosition", true); } @Override void applyToItem(CraftMetaItem.Applicator tag) { super.applyToItem(tag); + NBTTagCompound nbt = null; if (blockEntityTag != null) { - tag.put(BLOCK_ENTITY_TAG, CustomData.of(blockEntityTag.getSnapshotNBTWithoutComponents())); + nbt = blockEntityTag.getItemNBT(); for (TypedDataComponent component : blockEntityTag.collectComponents()) { tag.putIfAbsent(component); } } + + if (position != null) { + if (nbt == null) { + nbt = new NBTTagCompound(); + } + + nbt.putInt("x", position.getBlockX()); + nbt.putInt("y", position.getBlockY()); + nbt.putInt("z", position.getBlockZ()); + } + + if (nbt != null && !nbt.isEmpty()) { + CraftBlockEntityState tile = (blockEntityTag != null) ? blockEntityTag : getBlockState(material, null); + // See ItemBlock#setBlockEntityData + tile.addEntityType(nbt); + + tag.put(BLOCK_ENTITY_TAG, CustomData.of(nbt)); + } } @Override @@ -149,6 +177,9 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { super.serialize(builder); builder.put("blockMaterial", material.name()); + if (position != null) { + builder.put("blockPosition", position); + } return builder; } @@ -159,6 +190,9 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta if (blockEntityTag != null) { hash = 61 * hash + this.blockEntityTag.hashCode(); } + if (position != null) { + hash = 61 * hash + this.position.hashCode(); + } return original != hash ? CraftMetaBlockState.class.hashCode() ^ hash : hash; } @@ -170,19 +204,23 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta if (meta instanceof CraftMetaBlockState) { CraftMetaBlockState that = (CraftMetaBlockState) meta; - return Objects.equal(this.blockEntityTag, that.blockEntityTag); + return Objects.equal(this.blockEntityTag, that.blockEntityTag) && Objects.equal(this.position, that.position); } return true; } + boolean isBlockStateEmpty() { + return !(blockEntityTag != null || position != null); + } + @Override boolean notUncommon(CraftMetaItem meta) { - return super.notUncommon(meta) && (meta instanceof CraftMetaBlockState || blockEntityTag == null); + return super.notUncommon(meta) && (meta instanceof CraftMetaBlockState || isBlockStateEmpty()); } @Override boolean isEmpty() { - return super.isEmpty() && blockEntityTag == null; + return super.isEmpty() && isBlockStateEmpty(); } @Override @@ -191,6 +229,9 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta if (blockEntityTag != null) { meta.blockEntityTag = blockEntityTag.copy(); } + if (position != null) { + meta.position = position.clone(); + } return meta; }