From 6b67d1f666bc517ea49fd5822edc2f5cfb08f36c Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Sat, 21 Jul 2018 08:25:40 -0400
Subject: [PATCH] Add Debug Entities option to debug dupe uuid issues

Add -Ddebug.entities=true to your JVM flags to gain more information

diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index 835d329f9..ff22feee4 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -72,6 +72,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
     protected CraftEntity bukkitEntity;
 
     EntityTrackerEntry tracker; // Paper
+    Throwable addedToWorldStack; // Paper - entity debug
     public CraftEntity getBukkitEntity() {
         if (bukkitEntity == null) {
             bukkitEntity = CraftEntity.getEntity(world.getServer(), this);
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index b048343b7..747d99dbe 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -53,6 +53,10 @@ public class WorldServer extends World implements IAsyncTaskHandler {
     private boolean Q;
 
     // CraftBukkit start
+    private static final boolean DEBUG_ENTITIES = Boolean.getBoolean("debug.entities"); // Paper
+    private static Throwable getAddToWorldStackTrace(Entity entity) {
+        return new Throwable(entity + " Added to world at " + new java.util.Date());
+    }
     public final int dimension;
 
     // Add env and gen to constructor
@@ -980,6 +984,7 @@ public class WorldServer extends World implements IAsyncTaskHandler {
     private boolean j(Entity entity) {
         if (entity.dead) {
             WorldServer.a.warn("Tried to add entity {} but it was marked as removed already: " + entity); // CraftBukkit // Paper
+            if (DEBUG_ENTITIES) getAddToWorldStackTrace(entity).printStackTrace();
             return false;
         } else {
             UUID uuid = entity.getUniqueID();
@@ -991,8 +996,14 @@ public class WorldServer extends World implements IAsyncTaskHandler {
                     this.g.remove(entity1);
                 } else {
                     if (!(entity instanceof EntityHuman)) {
-                        WorldServer.a.error("Keeping entity {} that already exists with UUID {} - " + entity1, EntityTypes.getName(entity1.P()), uuid.toString()); // CraftBukkit // Paper
+                        WorldServer.a.error("Keeping entity {} that already exists with UUID {}", entity1, uuid.toString()); // CraftBukkit // Paper
                         WorldServer.a.error("Deleting duplicate entity {}", entity); // Paper
+                        if (DEBUG_ENTITIES) {
+                            if (entity1.addedToWorldStack != null) {
+                                entity1.addedToWorldStack.printStackTrace();
+                            }
+                            getAddToWorldStackTrace(entity).printStackTrace();
+                        }
                         return false;
                     }
 
@@ -1009,7 +1020,25 @@ public class WorldServer extends World implements IAsyncTaskHandler {
     protected void b(Entity entity) {
         super.b(entity);
         this.entitiesById.a(entity.getId(), entity);
-        this.entitiesByUUID.put(entity.getUniqueID(), entity);
+        // Paper start
+        if (DEBUG_ENTITIES) {
+            entity.addedToWorldStack = getAddToWorldStackTrace(entity);
+        }
+
+        Entity old = this.entitiesByUUID.put(entity.getUniqueID(), entity);
+        if (old != null && old.getId() != entity.getId() && old.valid) {
+            Logger logger = LogManager.getLogger();
+            logger.error("Overwrote an existing entity " + old + " with " + entity);
+            if (DEBUG_ENTITIES) {
+                if (old.addedToWorldStack != null) {
+                    old.addedToWorldStack.printStackTrace();
+                } else {
+                    logger.error("Oddly, the old entity was not added to the world in the normal way. Plugins?");
+                }
+                entity.addedToWorldStack.printStackTrace();
+            }
+        }
+        // Paper end
         Entity[] aentity = entity.bi();
 
         if (aentity != null) {
-- 
2.17.1