From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 6 Nov 2017 21:08:22 -0500 Subject: [PATCH] API to get a BlockState without a snapshot This allows you to get a BlockState without creating a snapshot, operating on the real tile entity. This is useful for where performance is needed also Avoid NPE during CraftBlockEntityState load if could not get TE If Tile Entity was null, correct Sign to return empty lines instead of null diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java index 63acd109a79ed752a05df3d4f1b99309297c2055..d156f7cc71050f13b2feca00c52ca6b64572b60e 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java @@ -44,6 +44,7 @@ public abstract class BlockEntity { this.type = type; this.worldPosition = pos.immutable(); this.blockState = state; + this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); // Paper - always init } public static BlockPos getPosFromTag(CompoundTag nbt) { @@ -65,7 +66,7 @@ public abstract class BlockEntity { // CraftBukkit start - read container public void load(CompoundTag nbt) { - this.persistentDataContainer = new CraftPersistentDataContainer(BlockEntity.DATA_TYPE_REGISTRY); + this.persistentDataContainer.clear(); // Paper - clear instead of init net.minecraft.nbt.Tag persistentDataTag = nbt.get("PublicBukkitValues"); if (persistentDataTag instanceof CompoundTag) { @@ -239,8 +240,15 @@ public abstract class BlockEntity { // CraftBukkit start - add method public InventoryHolder getOwner() { + // Paper start + return getOwner(true); + } + public InventoryHolder getOwner(boolean useSnapshot) { + // Paper end if (this.level == null) return null; - org.bukkit.block.BlockState state = this.level.getWorld().getBlockAt(this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ()).getState(); + org.bukkit.block.Block block = this.level.getWorld().getBlockAt(this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ()); + if (block.getType() == org.bukkit.Material.AIR) return null; + org.bukkit.block.BlockState state = block.getState(useSnapshot); // Paper if (state instanceof InventoryHolder) return (InventoryHolder) state; return null; } diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java index e5750b2459e5a7513b34d644f672f3e06181172d..3205d86a63f8fcf3ccd13c6be0e0eefc27beb62a 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java @@ -332,6 +332,13 @@ public class CraftBlock implements Block { return CraftBlockStates.getBlockState(this); } + // Paper start + @Override + public BlockState getState(boolean useSnapshot) { + return CraftBlockStates.getBlockState(this, useSnapshot); + } + // Paper end + @Override public Biome getBiome() { return this.getWorld().getBiome(this.getX(), this.getY(), this.getZ()); diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java index f698424feb30a8579e2ca581c48be08edf5bbf59..84550b6e4eaf62806a8ad83656d4051b09c9c97d 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java @@ -17,15 +17,26 @@ public class CraftBlockEntityState extends CraftBlockStat private final T tileEntity; private final T snapshot; + public final boolean snapshotDisabled; // Paper + public static boolean DISABLE_SNAPSHOT = false; // Paper public CraftBlockEntityState(World world, T tileEntity) { super(world, tileEntity.getBlockPos(), tileEntity.getBlockState()); this.tileEntity = tileEntity; + // Paper start + this.snapshotDisabled = DISABLE_SNAPSHOT; + if (DISABLE_SNAPSHOT) { + this.snapshot = this.tileEntity; + } else { + this.snapshot = this.createSnapshot(tileEntity); + } // copy tile entity data: - this.snapshot = this.createSnapshot(tileEntity); - this.load(snapshot); + if (this.snapshot != null) { + this.load(this.snapshot); + } + // Paper end } public void refreshSnapshot() { @@ -118,4 +129,11 @@ public class CraftBlockEntityState extends CraftBlockStat T vanillaTileEntitiy = (T) BlockEntity.loadStatic(CraftLocation.toBlockPosition(location), getHandle(), this.getSnapshotNBT()); return ClientboundBlockEntityDataPacket.create(vanillaTileEntitiy); } + + // Paper start + @Override + public boolean isSnapshot() { + return !this.snapshotDisabled; + } + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java index a69a03a7954b03a0aeca7a74d89756dd38ca6faf..17e1131c79ad140c0803a914621ce7924f0f2a6d 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java @@ -379,15 +379,30 @@ public final class CraftBlockStates { } public static BlockState getBlockState(Block block) { + // Paper start + return CraftBlockStates.getBlockState(block, true); + } + public static BlockState getBlockState(Block block, boolean useSnapshot) { + // Paper end Preconditions.checkNotNull(block, "block is null"); CraftBlock craftBlock = (CraftBlock) block; CraftWorld world = (CraftWorld) block.getWorld(); BlockPos blockPosition = craftBlock.getPosition(); net.minecraft.world.level.block.state.BlockState blockData = craftBlock.getNMS(); BlockEntity tileEntity = craftBlock.getHandle().getBlockEntity(blockPosition); + // Paper start - block state snapshots + boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT; + CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot; + try { + // Paper end CraftBlockState blockState = CraftBlockStates.getBlockState(world, blockPosition, blockData, tileEntity); blockState.setWorldHandle(craftBlock.getHandle()); // Inject the block's generator access return blockState; + // Paper start + } finally { + CraftBlockEntityState.DISABLE_SNAPSHOT = prev; + } + // Paper end } public static BlockState getBlockState(Material material, @Nullable CompoundTag blockEntityTag) { diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java index 6c559b0d7b3d8b95276d16a6af4975fd44de3334..a94389eebe51bb368f759b3f99f0b9ed08ae2bdd 100644 --- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java +++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java @@ -156,4 +156,10 @@ public class CraftPersistentDataContainer implements PersistentDataContainer { public Map serialize() { return (Map) CraftNBTTagConfigSerializer.serialize(this.toTagCompound()); } + + // Paper start + public void clear() { + this.customDataTags.clear(); + } + // Paper end }