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 77645019c88d61dde28b7598d8a29b7d0c23c209..560ee4eaa286197a0f8fc0a119ff5e06baca792a 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
@@ -42,6 +42,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject {
         this.type = type;
         this.worldPosition = pos.immutable();
         this.blockState = state;
+        this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); // Paper - always init
     }
 
     // Paper start
@@ -79,7 +80,7 @@ public abstract class BlockEntity implements net.minecraft.server.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) {
@@ -222,6 +223,11 @@ public abstract class BlockEntity implements net.minecraft.server.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;
         // Spigot start
         org.bukkit.block.Block block = this.level.getWorld().getBlockAt(this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ());
@@ -230,7 +236,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject {
             return null;
         }
         // Spigot end
-        org.bukkit.block.BlockState state = block.getState();
+        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 e6b8dd52cd503f45ca9bb868891ae4c8b29b3fcb..f1c4c3a3392c2d4d836fa10d7a38558d08084d9d 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
@@ -314,7 +314,20 @@ public class CraftBlock implements Block {
 
     @Override
     public BlockState getState() {
+        // Paper start
+        return this.getState(true);
+    }
+
+    @Override
+    public BlockState getState(boolean useSnapshot) {
+        boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT;
+        CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot;
+        try {
         return CraftBlockStates.getBlockState(this);
+        } finally {
+            CraftBlockEntityState.DISABLE_SNAPSHOT = prev;
+        }
+        // Paper end
     }
 
     @Override
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
index fbd52387299c90b85afd79897139cdb879fce74a..aaddbaecc25af87c863fe51098eb322fd5702104 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 abstract class CraftBlockEntityState<T extends BlockEntity> extends Craft
 
     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/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
index ddd7b63f0452042baa3fca04bb9fbdb42fcecbfd..b638351581fa09c488425a2318b782a5812140ce 100644
--- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
+++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
@@ -155,4 +155,10 @@ public final class CraftPersistentDataContainer implements PersistentDataContain
     public Map<String, Object> serialize() {
         return (Map<String, Object>) CraftNBTTagConfigSerializer.serialize(this.toTagCompound());
     }
+
+    // Paper start
+    public void clear() {
+        this.customDataTags.clear();
+    }
+    // Paper end
 }