From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar 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 entities = world.entitiesById.values(); entities.forEach(e -> { ResourceLocation key = e.getMinecraftKey(); + if (e.shouldBeRemoved) return; // Paper MutablePair> 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) {