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 0883e1755eae316faaeae8bf95763a0f80313c5a..90b218ebc947a1d8a8c7dfc677fe145b6386654a 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 @@ -57,6 +57,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) { @@ -78,7 +79,7 @@ public abstract class BlockEntity { // CraftBukkit start - read container protected void loadAdditional(CompoundTag nbt, HolderLookup.Provider registryLookup) { - 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) { @@ -342,8 +343,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 a1c1a101aa424e74309f6f4c0a53a6a8db5df441..013298c424025cd88f15d61e50d196f70fa4c58b 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java @@ -328,6 +328,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 be9c5d928b8dccd0adde9df42ac7306153d1cc5c..fdd6f9e8164efedb3e8f29857ad35ed69e7b299d 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java @@ -22,15 +22,26 @@ public class CraftBlockEntityState extends CraftBlockStat private final T tileEntity; private final T snapshot; + public 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(this.snapshot); + if (this.snapshot != null) { + this.load(this.snapshot); + } + // Paper end } protected CraftBlockEntityState(CraftBlockEntityState state, Location location) { @@ -165,4 +176,11 @@ public class CraftBlockEntityState extends CraftBlockStat public CraftBlockEntityState copy(Location location) { return new CraftBlockEntityState<>(this, location); } + + // 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 9d22f389dfce7b800e29efab767fac842651490a..4c30af81697db25d9913b436c45d9a926cbb5cca 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java @@ -387,15 +387,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 } @Deprecated diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java index dbb9a5b2f8d3bc0b13e0f56f6e8a0d9a7b761327..3001bb0e3d4af9b16645a0136093db594b89ab01 100644 --- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java +++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java @@ -177,4 +177,10 @@ public class CraftPersistentDataContainer implements PersistentDataContainer { public String serialize() { return CraftNBTTagConfigSerializer.serialize(this.toTagCompound()); } + + // Paper start + public void clear() { + this.customDataTags.clear(); + } + // Paper end }