From eb20b0b160d0b3b2c15297b27b666be93013371a 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 --- .../level/block/entity/BlockEntity.java.patch | 31 ++++++++++++++----- .../bukkit/craftbukkit/block/CraftBlock.java | 7 +++++ .../block/CraftBlockEntityState.java | 22 +++++++++++-- .../craftbukkit/block/CraftBlockStates.java | 15 +++++++++ .../CraftPersistentDataContainer.java | 6 ++++ 5 files changed, 71 insertions(+), 10 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/world/level/block/entity/BlockEntity.java.patch b/paper-server/patches/sources/net/minecraft/world/level/block/entity/BlockEntity.java.patch index 615c1970ee..b2ac6c60fe 100644 --- a/paper-server/patches/sources/net/minecraft/world/level/block/entity/BlockEntity.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/block/entity/BlockEntity.java.patch @@ -19,14 +19,22 @@ private static final Logger LOGGER = LogUtils.getLogger(); private final BlockEntityType type; @Nullable -@@ -74,8 +84,17 @@ +@@ -43,6 +53,7 @@ + this.worldPosition = pos.immutable(); + this.validateBlockState(state); + this.blockState = state; ++ this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); // Paper - always init + } + + private void validateBlockState(BlockState state) { +@@ -74,8 +85,17 @@ return this.level != null; } - protected void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) {} + // CraftBukkit start - read container + protected void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) { -+ 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) { @@ -38,7 +46,7 @@ public final void loadWithComponents(CompoundTag nbt, HolderLookup.Provider registries) { this.loadAdditional(nbt, registries); BlockEntity.ComponentHelper.COMPONENTS_CODEC.parse(registries.createSerializationContext(NbtOps.INSTANCE), nbt).resultOrPartial((s) -> { -@@ -114,6 +133,11 @@ +@@ -114,6 +134,11 @@ }).ifPresent((nbtbase) -> { nbttagcompound.merge((CompoundTag) nbtbase); }); @@ -50,7 +58,7 @@ return nbttagcompound; } -@@ -234,7 +258,12 @@ +@@ -234,7 +259,12 @@ public void fillCrashReportCategory(CrashReportCategory crashReportSection) { crashReportSection.setDetail("Name", this::getNameForReporting); if (this.level != null) { @@ -64,7 +72,7 @@ CrashReportCategory.populateBlockDetails(crashReportSection, this.level, this.worldPosition, this.level.getBlockState(this.worldPosition)); } } -@@ -263,13 +292,19 @@ +@@ -263,13 +293,19 @@ } public final void applyComponents(DataComponentMap defaultComponents, DataComponentPatch components) { @@ -86,7 +94,7 @@ @Nullable @Override public T get(DataComponentType type) { -@@ -284,9 +319,13 @@ +@@ -284,9 +320,13 @@ } }); Objects.requireNonNull(set); @@ -101,14 +109,21 @@ } protected void collectImplicitComponents(DataComponentMap.Builder builder) {} -@@ -321,6 +360,15 @@ +@@ -321,6 +361,22 @@ } } + // 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/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java index c9b1167b15..e163ff416f 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/paper-server/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/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java index 483a89ba47..80418a05d5 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java @@ -24,15 +24,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) { @@ -184,4 +195,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/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java index b849ed6eef..1a8dcde39a 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java @@ -393,15 +393,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/paper-server/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java index dbb9a5b2f8..3001bb0e3d 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java +++ b/paper-server/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 }