From 3654a5a2fdfc4d68c9055b22d9913a1d250f6130 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/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java
index 9ad14417e3..3e9b357c87 100644
--- a/src/main/java/net/minecraft/server/TileEntity.java
+++ b/src/main/java/net/minecraft/server/TileEntity.java
@@ -203,7 +203,12 @@ public abstract class TileEntity implements KeyedObject {
     }
 
     // CraftBukkit start - add method
+    // Paper start
     public InventoryHolder getOwner() {
+        return getOwner(true);
+    }
+    public InventoryHolder getOwner(boolean useSnapshot) {
+        // Paper end
         if (world == null) return null;
         // Spigot start
         org.bukkit.block.Block block = world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ());
@@ -212,7 +217,7 @@ public abstract class TileEntity implements 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 698d044a8d..9514968b07 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
@@ -263,6 +263,20 @@ public class CraftBlock implements Block {
     }
 
     public BlockState getState() {
+        // Paper start - allow disabling the use of snapshots
+        return getState(true);
+    }
+    public BlockState getState(boolean useSnapshot) {
+        boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT;
+        CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot;
+        try {
+            return getState0();
+        } finally {
+            CraftBlockEntityState.DISABLE_SNAPSHOT = prev;
+        }
+    }
+    public BlockState getState0() {
+        // Paper end
         Material material = getType();
 
         switch (material) {
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
index 0558cafe31..d4d9c5fc50 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
@@ -23,20 +23,40 @@ public class CraftBlockEntityState<T extends TileEntity> extends CraftBlockState
         CraftWorld world = (CraftWorld) this.getWorld();
         this.tileEntity = tileEntityClass.cast(world.getTileEntityAt(this.getX(), this.getY(), this.getZ()));
 
+        // Paper start
+        this.snapshotDisabled = DISABLE_SNAPSHOT;
+        if (DISABLE_SNAPSHOT) {
+            this.snapshot = this.tileEntity;
+        } else {
+            this.snapshot = this.createSnapshot(this.tileEntity, world.getHandle());
+        }
         // copy tile entity data:
-        this.snapshot = this.createSnapshot(tileEntity, world.getHandle());
-        this.load(snapshot);
+        if(this.snapshot != null) {
+            this.load(this.snapshot);
+        }
+        // Paper end
     }
 
+    public final boolean snapshotDisabled; // Paper
+    public static boolean DISABLE_SNAPSHOT = false; // Paper
+
     public CraftBlockEntityState(Material material, T tileEntity) {
         super(material);
 
         this.tileEntityClass = (Class<T>) tileEntity.getClass();
         this.tileEntity = tileEntity;
-
+        // Paper start
+        this.snapshotDisabled = DISABLE_SNAPSHOT;
+        if (DISABLE_SNAPSHOT) {
+            this.snapshot = this.tileEntity;
+        } else {
+            this.snapshot = this.createSnapshot(this.tileEntity, null);
+        }
         // copy tile entity data:
-        this.snapshot = this.createSnapshot(tileEntity, null);
-        this.load(snapshot);
+        if(this.snapshot != null) {
+            this.load(this.snapshot);
+        }
+        // Paper end
     }
 
     private T createSnapshot(T tileEntity, World world) {
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
index 7a8d445299..97b4e6910d 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
@@ -14,10 +14,12 @@ public class CraftSign extends CraftBlockEntityState<TileEntitySign> implements
 
     public CraftSign(final Block block) {
         super(block, TileEntitySign.class);
+        if (lines == null) { lines = new String[]{"", "", "", ""}; } // Paper
     }
 
     public CraftSign(final Material material, final TileEntitySign te) {
         super(material, te);
+        if (lines == null) { lines = new String[]{"", "", "", ""}; } // Paper
     }
 
     @Override
-- 
2.18.0