Paper/patches/server/0168-API-to-get-a-BlockState-without-a-snapshot.patch

154 lines
7.4 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
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 1e416b23a38458f16add472cea09b0ac5ac91869..6f61fd8224fb4094f38a851300ab55f94523c252 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 implements io.papermc.paper.util.KeyedObject {
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) {
@@ -86,7 +87,7 @@ public abstract class BlockEntity implements io.papermc.paper.util.KeyedObject {
// 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) {
@@ -260,8 +261,15 @@ public abstract class BlockEntity implements io.papermc.paper.util.KeyedObject {
// 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 c0af4b05b5d77aad99487fa7f8d840e797b6554c..40fc3268e7b662cdd45b569224ccd2abfad0a595 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
@@ -320,6 +320,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..c2c0b4bfab64394e55f2832e37e49bccb7e955ab 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<T extends BlockEntity> 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() {
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<String, Object> serialize() {
return (Map<String, Object>) CraftNBTTagConfigSerializer.serialize(this.toTagCompound());
}
+
+ // Paper start
+ public void clear() {
+ this.customDataTags.clear();
+ }
+ // Paper end
}