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.

Not relevant in 1.17

diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java
index e95b91cefb0374bd5bb57cc090f5ecd566d7a618..8fd716bf2e1402694798b8be03fd85821153be44 100644
--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java
+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java
@@ -209,6 +209,7 @@ public class PaperCommand extends Command {
                 Collection<Entity> entities = world.entitiesById.values();
                 entities.forEach(e -> {
                     ResourceLocation key = e.getMinecraftKey();
+                    if (e.shouldBeRemoved) return; // Paper
 
                     MutablePair<Integer, Map<ChunkPos, Integer>> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap()));
                     ChunkPos chunk = new ChunkPos(e.xChunk, e.zChunk);
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 8e8e5f30c512ed7d8ee987550c22d3e9df845043..84b2cd661697545186677ab7966556d9288c650b 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1303,6 +1303,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
                 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
         }
 
@@ -1315,6 +1316,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
             this.removeFromChunk(entity);
             this.entitiesById.remove(entity.getId());
             this.onEntityRemoved(entity);
+            entity.shouldBeRemoved = true; // Paper
         }
     }
 
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 7847078c54154e28ab066ea8a329f929df1e1a37..5bf6bc6a01ccde8a4d67b49293bb326cb09248d8 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -275,6 +275,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
     protected int numCollisions = 0; // Paper
     public void inactiveTick() { }
     // Spigot end
+    public boolean shouldBeRemoved; // Paper
 
     public float getBukkitYaw() {
         return this.yRot;
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
index 09aa608bd303b618ae2c0ebd237bcbdba60a37a8..db28bfe95c885cdefa855c7aaa3bcf92bc52df26 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -862,6 +862,7 @@ public class LevelChunk implements ChunkAccess {
 
             for (int i1 = 0; i1 < l; ++i1) {
                 Entity entity1 = (Entity) list1.get(i1);
+                if (entity1.shouldBeRemoved) continue; // Paper
 
                 if (entity1.getBoundingBox().intersects(box) && entity1 != except) {
                     if (predicate == null || predicate.test(entity1)) {
@@ -899,6 +900,7 @@ public class LevelChunk implements ChunkAccess {
 
             while (iterator.hasNext()) {
                 T entity = (T) iterator.next(); // CraftBukkit - decompile error
+                if (entity.shouldBeRemoved) continue; // Paper
 
                 if ((type == null || entity.getType() == type) && entity.getBoundingBox().intersects(box) && predicate.test(entity)) {
                     result.add(entity);
@@ -921,6 +923,7 @@ public class LevelChunk implements ChunkAccess {
 
             while (iterator.hasNext()) {
                 T t0 = (T) iterator.next(); // CraftBukkit - decompile error
+                if (t0.shouldBeRemoved) continue; // Paper
 
                 if (entityClass.isInstance(t0) && t0.getBoundingBox().intersects(box) && (predicate == null || predicate.test(t0))) { // Spigot - instance check
                     result.add(t0);
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 3a3466cd9bbd34dbc0b79567f5579e84a81d6009..9807612aed6c4393cbe1f4b6078e45bf1ba3deb2 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1022,6 +1022,7 @@ public class CraftWorld implements World {
         for (Object o : world.entitiesById.values()) {
             if (o instanceof net.minecraft.world.entity.Entity) {
                 net.minecraft.world.entity.Entity mcEnt = (net.minecraft.world.entity.Entity) o;
+                if (mcEnt.shouldBeRemoved) continue; // Paper
                 Entity bukkitEntity = mcEnt.getBukkitEntity();
 
                 // Assuming that bukkitEntity isn't null
@@ -1041,6 +1042,7 @@ public class CraftWorld implements World {
         for (Object o : world.entitiesById.values()) {
             if (o instanceof net.minecraft.world.entity.Entity) {
                 net.minecraft.world.entity.Entity mcEnt = (net.minecraft.world.entity.Entity) o;
+                if (mcEnt.shouldBeRemoved) continue; // Paper
                 Entity bukkitEntity = mcEnt.getBukkitEntity();
 
                 // Assuming that bukkitEntity isn't null
@@ -1067,6 +1069,7 @@ public class CraftWorld implements World {
 
         for (Object entity: world.entitiesById.values()) {
             if (entity instanceof net.minecraft.world.entity.Entity) {
+                if (((net.minecraft.world.entity.Entity) entity).shouldBeRemoved) continue; // Paper
                 Entity bukkitEntity = ((net.minecraft.world.entity.Entity) entity).getBukkitEntity();
 
                 if (bukkitEntity == null) {
@@ -1090,6 +1093,7 @@ public class CraftWorld implements World {
 
         for (Object entity: world.entitiesById.values()) {
             if (entity instanceof net.minecraft.world.entity.Entity) {
+                if (((net.minecraft.world.entity.Entity) entity).shouldBeRemoved) continue; // Paper
                 Entity bukkitEntity = ((net.minecraft.world.entity.Entity) entity).getBukkitEntity();
 
                 if (bukkitEntity == null) {
