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 148e79ae4e24fe16dbbb17550c3f258d4362c266..06beb18e5e1950aeb6cb427876fcc4c5ea95adb2 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 @@ -45,6 +45,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) { @@ -66,7 +67,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) { @@ -240,8 +241,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 52fc42050d5df0882586c8f4bb4890ef1dbf979e..ba8f9ffed49bf377be8b37532d4f2bdcb8c44d82 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java @@ -329,6 +329,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 7629a51ec284cab0db7e9238027d6acfa4f3083c..a76cce199acdcecfdd8b998ec08974c2ed0751cf 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java @@ -10,15 +10,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() { @@ -105,4 +116,11 @@ public class CraftBlockEntityState extends CraftBlockStat public PersistentDataContainer getPersistentDataContainer() { return this.getSnapshot().persistentDataContainer; } + + // 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 51ea68c433c4d530f8404d3174c5a121ce808a96..93a8aeb5545c794ac425c35f8af52a443cd060ca 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java @@ -324,15 +324,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 3fc3907172f12ee24ea70bd6a1ffbbc6084ed971..2c59f09a9261a1690951161fd856a5848d9885b7 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 }