From 0000000000000000000000000000000000000000 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/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java index ae2f5664c3022b452b6cba8f9ce36b493fa9fec8..a6f0cde7bdc930abced5063da237bcd27ddcd20f 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -157,6 +157,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne } } }; + public List entitySlice = null; // Paper end public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java index f56ff8e727c74870229d4d146b13534863f620d6..e4accac8f2e8daa58f9b0c279ffcad9347448bb0 100644 --- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java @@ -26,6 +26,8 @@ import net.minecraft.ReportedException; import net.minecraft.core.BlockPosition; import net.minecraft.core.IRegistry; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ChunkProviderServer; import net.minecraft.server.level.PlayerChunk; import net.minecraft.server.level.WorldServer; import net.minecraft.util.EntitySlice; @@ -551,6 +553,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; @@ -560,6 +581,7 @@ public class Chunk implements IChunkAccess { entity.chunkZ = this.loc.z; this.entities.add(entity); // Paper - per chunk entity list this.entitySlices[k].add(entity); + entity.entitySlice = this.entitySlices[k]; // Paper this.markDirty(); // Paper } @@ -585,6 +607,10 @@ 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; + entity.inChunk = false; + } if (!this.entitySlices[i].remove(entity)) { return; }