From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Sat, 28 Jul 2018 12:18:27 -0400
Subject: [PATCH] Ignore Dead Entities in entityList iteration

A spigot change delays removal of entities from the entity list.
This causes a change in behavior from Vanilla where getEntities type
methods will return dead entities that they shouldn't otherwise be doing.

This will ensure that dead entities are skipped from iteration since
they shouldn't of been in the list in the first place.

diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java
index b839769ceae8932bb121a0b96fde1e7d129a1f63..5acad8e44f024d3ddf5ef4fd320460ac516e0fb8 100644
--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java
+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java
@@ -179,6 +179,7 @@ public class PaperCommand extends Command {
                 Collection<Entity> entities = world.entitiesById.values();
                 entities.forEach(e -> {
                     MinecraftKey key = e.getMinecraftKey();
+                    if (e.shouldBeRemoved) return; // Paper
 
                     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/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index 0afa8a7ebd8dbdfaac362d66b687e787bc040dee..8e9ddca049f837ed1c5fc4aa9fd6a6858dbc36be 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -810,6 +810,7 @@ public class Chunk implements IChunkAccess {
 
                 while (iterator.hasNext()) {
                     Entity entity1 = (Entity) iterator.next();
+                    if (entity1.shouldBeRemoved) continue; // Paper
 
                     if (entity1.getBoundingBox().c(axisalignedbb) && entity1 != entity) {
                         if (predicate == null || predicate.test(entity1)) {
@@ -847,6 +848,7 @@ public class Chunk implements IChunkAccess {
 
             while (iterator.hasNext()) {
                 T entity = (T) iterator.next(); // CraftBukkit - decompile error
+                if (entity.shouldBeRemoved) continue; // Paper
 
                 if ((entitytypes == null || entity.getEntityType() == entitytypes) && entity.getBoundingBox().c(axisalignedbb) && predicate.test(entity)) {
                     list.add(entity);
@@ -868,6 +870,7 @@ public class Chunk implements IChunkAccess {
 
             while (iterator.hasNext()) {
                 T t0 = (T) iterator.next(); // CraftBukkit - decompile error
+                if (t0.shouldBeRemoved) continue; // Paper
 
                 if (oclass.isInstance(t0) && t0.getBoundingBox().c(axisalignedbb) && (predicate == null || predicate.test(t0))) { // Spigot - instance check
                     list.add(t0);
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index 84d36ea84e25a701af22900af6cd3099adf6cd54..6e87ff52df30f4de8cfb11d1dbfb71211d656831 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -195,6 +195,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
     protected int numCollisions = 0; // Paper
     public void inactiveTick() { }
     // Spigot end
+    public boolean shouldBeRemoved; // Paper
 
     public float getBukkitYaw() {
         return this.yaw;
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 426ca12970e0c75ba75eee6c3e3cdbf833730737..3067ab76d94c58fbfd52fac6754bf6d6d7f01d09 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -908,7 +908,7 @@ public class WorldServer extends World {
 
         while (objectiterator.hasNext()) {
             Entity entity = (Entity) objectiterator.next();
-
+            if (entity.shouldBeRemoved) continue; // Paper
             if (entity instanceof EntityInsentient) {
                 EntityInsentient entityinsentient = (EntityInsentient) entity;
 
@@ -1230,6 +1230,7 @@ public class WorldServer extends World {
                 entity.origin = entity.getBukkitEntity().getLocation();
             }
             // Paper end
+            entity.shouldBeRemoved = false; // Paper - shouldn't be removed after being re-added
             new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid
         }
 
@@ -1242,6 +1243,7 @@ public class WorldServer extends World {
             this.removeEntityFromChunk(entity);
             this.entitiesById.remove(entity.getId());
             this.unregisterEntity(entity);
+            entity.shouldBeRemoved = true; // Paper
         }
     }
 
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index cde999c97f5a1ccab0d13f02708992fac3876e67..960e29cb16f1b08f522832700c60d25416585cce 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1029,6 +1029,7 @@ public class CraftWorld implements World {
         for (Object o : world.entitiesById.values()) {
             if (o instanceof net.minecraft.server.Entity) {
                 net.minecraft.server.Entity mcEnt = (net.minecraft.server.Entity) o;
+                if (mcEnt.shouldBeRemoved) continue; // Paper
                 Entity bukkitEntity = mcEnt.getBukkitEntity();
 
                 // Assuming that bukkitEntity isn't null
@@ -1048,6 +1049,7 @@ public class CraftWorld implements World {
         for (Object o : world.entitiesById.values()) {
             if (o instanceof net.minecraft.server.Entity) {
                 net.minecraft.server.Entity mcEnt = (net.minecraft.server.Entity) o;
+                if (mcEnt.shouldBeRemoved) continue; // Paper
                 Entity bukkitEntity = mcEnt.getBukkitEntity();
 
                 // Assuming that bukkitEntity isn't null
@@ -1074,6 +1076,7 @@ public class CraftWorld implements World {
 
         for (Object entity: world.entitiesById.values()) {
             if (entity instanceof net.minecraft.server.Entity) {
+                if (((net.minecraft.server.Entity) entity).shouldBeRemoved) continue; // Paper
                 Entity bukkitEntity = ((net.minecraft.server.Entity) entity).getBukkitEntity();
 
                 if (bukkitEntity == null) {
@@ -1097,6 +1100,7 @@ public class CraftWorld implements World {
 
         for (Object entity: world.entitiesById.values()) {
             if (entity instanceof net.minecraft.server.Entity) {
+                if (((net.minecraft.server.Entity) entity).shouldBeRemoved) continue; // Paper
                 Entity bukkitEntity = ((net.minecraft.server.Entity) entity).getBukkitEntity();
 
                 if (bukkitEntity == null) {
