From 88075086ab0ce189abe18270d7b670f8d57e6074 Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 23 Jul 2018 22:44:23 -0400 Subject: [PATCH] Add some Debug to Chunk Entity slices If we detect unexpected state, log and try to recover This should hopefully avoid duplicate entities ever being created if the entity was to end up in 2 different chunk slices diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java index c23891f73a..d787a4ab30 100644 --- a/src/main/java/net/minecraft/server/Chunk.java +++ b/src/main/java/net/minecraft/server/Chunk.java @@ -402,6 +402,25 @@ public class Chunk implements IChunkAccess { if (k >= this.entitySlices.length) { k = this.entitySlices.length - 1; } + // Paper - remove from any old list if its in one + List nextSlice = this.entitySlices[k]; // the next list to be added to + List currentSlice = entity.entitySlice; + if (nextSlice == currentSlice) { + if (World.DEBUG_ENTITIES) MinecraftServer.LOGGER.warn("Entity was already in this chunk!" + entity, new Throwable()); + return; // ??? silly plugins + } + if (currentSlice != null && currentSlice.contains(entity)) { + // Still in an old chunk... + if (World.DEBUG_ENTITIES) MinecraftServer.LOGGER.warn("Entity is still in another chunk!" + entity, new Throwable()); + Chunk chunk = entity.getCurrentChunk(); + if (chunk != null) { + chunk.removeEntity(entity); + } else { + removeEntity(entity); + } + currentSlice.remove(entity); // Just incase the above did not remove from the previous slice + } + // Paper end if (!entity.inChunk || entity.getCurrentChunk() != this) entityCounts.increment(entity.getMinecraftKeyString()); // Paper entity.inChunk = true; @@ -410,6 +429,7 @@ public class Chunk implements IChunkAccess { entity.chunkY = k; entity.chunkZ = this.loc.z; this.entitySlices[k].add(entity); + entity.entitySlice = this.entitySlices[k]; // Paper this.markDirty(); // Paper } @@ -433,6 +453,9 @@ public class Chunk implements IChunkAccess { } // Paper start if (entity.currentChunk != null && entity.currentChunk.get() == this) entity.setCurrentChunk(null); + if (entitySlices[i] == entity.entitySlice) { + entity.entitySlice = null; + } if (!this.entitySlices[i].remove(entity)) { return; } diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java index 3397604a8a..cbd7793c53 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java @@ -67,6 +67,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke } } }; + List entitySlice = null; // Paper end static boolean isLevelAtLeast(NBTTagCompound tag, int level) { return tag.hasKey("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; -- 2.21.0