From 0000000000000000000000000000000000000000 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 bee2fa2bfbb61209381f24ed6508d3d1c73a344a..1fa190e098079522e0fe3593fa261c1b7ad4e24b 100644
--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java
+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java
@@ -207,7 +207,7 @@ public class PaperCommand extends Command {
                 ServerChunkCache chunkProviderServer = world.getChunkSource();
 
                 world.getAllEntities().forEach(e -> {
-                    ResourceLocation key = new ResourceLocation(""); // TODO: update in next patch
+                    ResourceLocation key = e.getMinecraftKey();
 
                     MutablePair<Integer, Map<ChunkPos, Integer>> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap()));
                     ChunkPos chunk = e.chunkPosition();
diff --git a/src/main/java/io/papermc/paper/util/KeyedObject.java b/src/main/java/io/papermc/paper/util/KeyedObject.java
new file mode 100644
index 0000000000000000000000000000000000000000..9f0c7fd903f085e70db1785fb8bcdb5456e6ca51
--- /dev/null
+++ b/src/main/java/io/papermc/paper/util/KeyedObject.java
@@ -0,0 +1,11 @@
+package io.papermc.paper.util;
+
+import net.minecraft.resources.ResourceLocation;
+
+public interface KeyedObject {
+    ResourceLocation getMinecraftKey();
+    default String getMinecraftKeyString() {
+        ResourceLocation key = getMinecraftKey();
+        return key != null ? key.toString() : null;
+    }
+}
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 52eb344feee9c3bc34a6d22a32de174c52736fb5..0736454dea12d8ffe8ef6873c5d25d17a96504b0 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -145,7 +145,7 @@ import org.bukkit.event.player.PlayerTeleportEvent;
 import org.bukkit.plugin.PluginManager;
 // CraftBukkit end
 
-public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+public abstract class Entity implements Nameable, EntityAccess, CommandSource, io.papermc.paper.util.KeyedObject { // Paper
 
     // CraftBukkit start
     private static final int CURRENT_LEVEL = 2;
@@ -1963,12 +1963,32 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
         return true;
     }
 
+    // Paper start
+    private ResourceLocation entityKey;
+    private String entityKeyString;
+
+    @Override
+    public ResourceLocation getMinecraftKey() {
+        if (entityKey == null) {
+            this.entityKey = EntityType.getKey(this.getType());
+            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 getEncodeId() {
         EntityType<?> entitytypes = this.getType();
         ResourceLocation minecraftkey = EntityType.getKey(entitytypes);
 
-        return entitytypes.canSerialize() && minecraftkey != null ? minecraftkey.toString() : null;
+        return entitytypes != null && entitytypes.canSerialize() ? getMinecraftKeyString() : null;
+        // Paper end
     }
 
     protected abstract void readAdditionalSaveData(CompoundTag nbt);
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 30adcc82bc4e2e7145d29b64fde952d694cdf1e1..d33c2d2ec285179614d21a255cea394682e4cc2c 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
@@ -23,7 +23,7 @@ import org.bukkit.inventory.InventoryHolder;
 
 import org.spigotmc.CustomTimingsHandler; // Spigot
 
-public abstract class BlockEntity {
+public abstract class BlockEntity implements io.papermc.paper.util.KeyedObject { // Paper
 
     public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot
     // CraftBukkit start - data containers
@@ -48,6 +48,26 @@ public abstract class BlockEntity {
         return new BlockPos(nbt.getInt("x"), nbt.getInt("y"), nbt.getInt("z"));
     }
 
+    // Paper start
+    private String tileEntityKeyString = null;
+    private ResourceLocation tileEntityKey = null;
+
+    @Override
+    public ResourceLocation getMinecraftKey() {
+        if (tileEntityKey == null) {
+            tileEntityKey = BlockEntityType.getKey(this.type);
+            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 Level getLevel() {
         return this.level;