From 5ff4ed009bdf9fa16a49ad57060a1aba090ed1ae Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Wed, 4 Jul 2018 01:40:13 -0400
Subject: [PATCH] Add MinecraftKey Information to Objects

Stores the reference to the objects respective MinecraftKey

diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java
index 841edd010f..3354fdd60d 100644
--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java
+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java
@@ -175,7 +175,7 @@ public class PaperCommand extends Command {
 
                 List<Entity> entities = world.globalEntityList;
                 entities.forEach(e -> {
-                    MinecraftKey key = new MinecraftKey(""); // TODO: update in next patch
+                    MinecraftKey key = e.getMinecraftKey();
 
                     MutablePair<Integer, Map<ChunkCoordIntPair, Integer>> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap()));
                     ChunkCoordIntPair chunk = new ChunkCoordIntPair(e.getChunkX(), e.getChunkZ());
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index 77015bc06e..01e4863899 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -49,7 +49,7 @@ import org.bukkit.event.player.PlayerTeleportEvent;
 import org.bukkit.plugin.PluginManager;
 // CraftBukkit end
 
-public abstract class Entity implements INamableTileEntity, ICommandListener {
+public abstract class Entity implements INamableTileEntity, ICommandListener, KeyedObject { // Paper
 
     // CraftBukkit start
     private static final int CURRENT_LEVEL = 2;
@@ -1677,12 +1677,31 @@ public abstract class Entity implements INamableTileEntity, ICommandListener {
         return true;
     }
 
+    // Paper start
+    private MinecraftKey entityKey;
+    private String entityKeyString;
+
+    @Override
+    public MinecraftKey getMinecraftKey() {
+        if (entityKey == null) {
+            this.entityKey = EntityTypes.getName(this.getEntityType());
+            this.entityKeyString = this.entityKey != null ? this.entityKey.toString() : null;
+        }
+        return entityKey;
+    }
+
+    @Override
+    public String getMinecraftKeyString() {
+        getMinecraftKey(); // Try to load if it doesn't exists. see: https://github.com/PaperMC/Paper/issues/1280
+        return entityKeyString;
+    }
     @Nullable
     public final String getSaveID() {
         EntityTypes<?> entitytypes = this.getEntityType();
         MinecraftKey minecraftkey = EntityTypes.getName(entitytypes);
 
-        return entitytypes.a() && minecraftkey != null ? minecraftkey.toString() : null;
+        return entitytypes != null && entitytypes.isPersistable() ? getMinecraftKeyString() : null;
+        // Paper end
     }
 
     protected abstract void a(NBTTagCompound nbttagcompound);
diff --git a/src/main/java/net/minecraft/server/EntityTypes.java b/src/main/java/net/minecraft/server/EntityTypes.java
index 3217a8ed18..c7fb8f513b 100644
--- a/src/main/java/net/minecraft/server/EntityTypes.java
+++ b/src/main/java/net/minecraft/server/EntityTypes.java
@@ -238,6 +238,7 @@ public class EntityTypes<T extends Entity> {
         }
     }
 
+    public boolean isPersistable() { return a(); } // Paper - OBFHELPER
     public boolean a() {
         return this.bb;
     }
diff --git a/src/main/java/net/minecraft/server/KeyedObject.java b/src/main/java/net/minecraft/server/KeyedObject.java
new file mode 100644
index 0000000000..743142d030
--- /dev/null
+++ b/src/main/java/net/minecraft/server/KeyedObject.java
@@ -0,0 +1,9 @@
+package net.minecraft.server;
+
+public interface KeyedObject {
+    MinecraftKey getMinecraftKey();
+    default String getMinecraftKeyString() {
+        MinecraftKey key = getMinecraftKey();
+        return key != null ? key.toString() : null;
+    }
+}
diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java
index 080fd819b6..77d77fcb8b 100644
--- a/src/main/java/net/minecraft/server/TileEntity.java
+++ b/src/main/java/net/minecraft/server/TileEntity.java
@@ -10,7 +10,7 @@ import org.bukkit.inventory.InventoryHolder;
 // CraftBukkit end
 import org.spigotmc.CustomTimingsHandler; // Spigot
 
-public abstract class TileEntity {
+public abstract class TileEntity implements KeyedObject { // Paper
 
     public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot
     // CraftBukkit start - data containers
@@ -18,7 +18,7 @@ public abstract class TileEntity {
     public final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY);
     // CraftBukkit end
     private static final Logger LOGGER = LogManager.getLogger();
-    private final TileEntityTypes<?> b;
+    private final TileEntityTypes<?> b; public TileEntityTypes getTileEntityType() { return b; } // Paper - OBFHELPER
     @Nullable
     protected World world;
     protected BlockPosition position;
@@ -31,6 +31,26 @@ public abstract class TileEntity {
         this.b = tileentitytypes;
     }
 
+    // Paper start
+    private String tileEntityKeyString = null;
+    private MinecraftKey tileEntityKey = null;
+
+    @Override
+    public MinecraftKey getMinecraftKey() {
+        if (tileEntityKey == null) {
+            tileEntityKey = TileEntityTypes.a(this.getTileEntityType());
+            tileEntityKeyString = tileEntityKey != null ? tileEntityKey.toString() : null;
+        }
+        return tileEntityKey;
+    }
+
+    @Override
+    public String getMinecraftKeyString() {
+        getMinecraftKey(); // Try to load if it doesn't exists.
+        return tileEntityKeyString;
+    }
+    // Paper end
+
     @Nullable
     public World getWorld() {
         return this.world;
-- 
2.21.0