From e2f0efd1af7d3d22ee7ec2d964d2c553d44a6baf Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Tue, 28 Jan 2025 17:25:26 -0800 Subject: [PATCH] Remove nms.Entity#isChunkLoaded This method was used pre 1.17 era where an Entity was explicitly tied to a (then called) Chunk's entity slices. If an entity was not inside a Chunk, then it was considered invalid as it was not possible to save the entity. In 1.17+, entities are now tied to a separately tracked entity section management system. This system is far more reliable now as it no longer requires a full chunk load to properly track entities for saving. As a result, an Entity if inside the world is always attached to some entity chunk section (except in rare cases in Vanilla which are fixed in Moonrise). As a result, whether the chunk the entity is in is loaded is no longer an indication of whether they are tracked in the world and we can reliably infer that the entity is correctly in the world through the valid field alone. Additionally drop the isInWorld() check, as valid=true implies isInWorld=true. More importantly, the isInWorld() check invokes getHandle which may trip a thread check on Folia. This will fix World#getEntities() and friends exploding on Folia. However, World#getEntities() on Folia still cannot reliably return all entities in the world as actions such as cross-region (not cross-world) teleporting will remove entities from the world. --- .../0003-Entity-Activation-Range-2.0.patch | 10 +++++----- .../0016-Moonrise-optimisation-patches.patch | 20 +++++++++---------- .../minecraft/world/entity/Entity.java.patch | 6 +----- .../org/bukkit/craftbukkit/CraftWorld.java | 4 ++-- .../craftbukkit/entity/CraftEntity.java | 2 +- 5 files changed, 19 insertions(+), 23 deletions(-) diff --git a/paper-server/patches/features/0003-Entity-Activation-Range-2.0.patch b/paper-server/patches/features/0003-Entity-Activation-Range-2.0.patch index cbfc717b36..dcb46b821e 100644 --- a/paper-server/patches/features/0003-Entity-Activation-Range-2.0.patch +++ b/paper-server/patches/features/0003-Entity-Activation-Range-2.0.patch @@ -366,7 +366,7 @@ index d95413af04121fe91ca0f3b0c70025b9808acef9..ad665c7535c615d2b03a3e7864be435f import org.slf4j.Logger; diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 3164f3784131babf9a6663335517a12df7e88a7b..da8848e2a3e3745949eb2356a049451d30f763a7 100644 +index 79d23c3403efc6dbef2381a3fa5946023f862452..3b19229427d83290bba1431bee5357e2ced34f94 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java @@ -551,6 +551,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -476,7 +476,7 @@ index 24735284fda151414d99faad401d25ba60995f9a..23b342cc31c7e72ade0e1ccad86a9ccf public void tick() { super.tick(); diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index e7889c9c7b155db46730f5e168bb7fd3d1732a8c..334859c5ff7023c730513301cc11c9837b2c7823 100644 +index bf5f2b753e3cbe3dfa8ad86df06718fbc1fbcbc4..988e5740b86c7768fee7391dc7e2900305a51be9 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java @@ -380,6 +380,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -495,7 +495,7 @@ index e7889c9c7b155db46730f5e168bb7fd3d1732a8c..334859c5ff7023c730513301cc11c983 public void setOrigin(@javax.annotation.Nonnull org.bukkit.Location location) { this.origin = location.toVector(); -@@ -417,6 +426,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -413,6 +422,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.position = Vec3.ZERO; this.blockPosition = BlockPos.ZERO; this.chunkPosition = ChunkPos.ZERO; @@ -509,7 +509,7 @@ index e7889c9c7b155db46730f5e168bb7fd3d1732a8c..334859c5ff7023c730513301cc11c983 SynchedEntityData.Builder builder = new SynchedEntityData.Builder(this); builder.define(DATA_SHARED_FLAGS_ID, (byte)0); builder.define(DATA_AIR_SUPPLY_ID, this.getMaxAirSupply()); -@@ -981,6 +997,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -977,6 +993,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } else { this.wasOnFire = this.isOnFire(); if (type == MoverType.PISTON) { @@ -518,7 +518,7 @@ index e7889c9c7b155db46730f5e168bb7fd3d1732a8c..334859c5ff7023c730513301cc11c983 movement = this.limitPistonMovement(movement); if (movement.equals(Vec3.ZERO)) { return; -@@ -994,6 +1012,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -990,6 +1008,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.stuckSpeedMultiplier = Vec3.ZERO; this.setDeltaMovement(Vec3.ZERO); } diff --git a/paper-server/patches/features/0016-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0016-Moonrise-optimisation-patches.patch index 1d02952046..de786f06e0 100644 --- a/paper-server/patches/features/0016-Moonrise-optimisation-patches.patch +++ b/paper-server/patches/features/0016-Moonrise-optimisation-patches.patch @@ -28372,7 +28372,7 @@ index 8cc5c0716392ba06501542ff5cbe71ee43979e5d..09fd99c9cbd23b5f3c899bfb00c9b896 + // Paper end - block counting } diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 8d7c1ee6c1cd4419621b11029eb06bf8135e59aa..1d0151a042ed5de4e235ef0bdac1a0e8240e85e7 100644 +index 55e0bd63a65867f4e496ec0b188ccba7a4a8ebef..161c7a53427917fdbd328401a84a7cab703701a8 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java @@ -135,7 +135,7 @@ import net.minecraft.world.scores.ScoreHolder; @@ -28466,7 +28466,7 @@ index 8d7c1ee6c1cd4419621b11029eb06bf8135e59aa..1d0151a042ed5de4e235ef0bdac1a0e8 } // Paper end - Share random for entities to make them more random public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason -@@ -419,6 +375,156 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -415,6 +371,156 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return this.dimensions.makeBoundingBox(x, y, z); } // Paper end @@ -28623,7 +28623,7 @@ index 8d7c1ee6c1cd4419621b11029eb06bf8135e59aa..1d0151a042ed5de4e235ef0bdac1a0e8 public Entity(EntityType entityType, Level level) { this.type = entityType; -@@ -1327,35 +1433,77 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1323,35 +1429,77 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return distance; } @@ -28725,7 +28725,7 @@ index 8d7c1ee6c1cd4419621b11029eb06bf8135e59aa..1d0151a042ed5de4e235ef0bdac1a0e8 } private static float[] collectCandidateStepUpHeights(AABB box, List colliders, float deltaY, float maxUpStep) { -@@ -2662,23 +2810,110 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2658,23 +2806,110 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public boolean isInWall() { @@ -28849,7 +28849,7 @@ index 8d7c1ee6c1cd4419621b11029eb06bf8135e59aa..1d0151a042ed5de4e235ef0bdac1a0e8 } public InteractionResult interact(Player player, InteractionHand hand) { -@@ -4102,15 +4337,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4098,15 +4333,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public Iterable getIndirectPassengers() { @@ -28875,7 +28875,7 @@ index 8d7c1ee6c1cd4419621b11029eb06bf8135e59aa..1d0151a042ed5de4e235ef0bdac1a0e8 } public int countPlayerPassengers() { -@@ -4248,77 +4485,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4244,77 +4481,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return Mth.lerp(partialTick, this.yRotO, this.yRot); } @@ -29066,7 +29066,7 @@ index 8d7c1ee6c1cd4419621b11029eb06bf8135e59aa..1d0151a042ed5de4e235ef0bdac1a0e8 public boolean touchingUnloadedChunk() { AABB aabb = this.getBoundingBox().inflate(1.0); -@@ -4471,6 +4767,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4467,6 +4763,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.setPosRaw(x, y, z, false); } public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) { @@ -29082,7 +29082,7 @@ index 8d7c1ee6c1cd4419621b11029eb06bf8135e59aa..1d0151a042ed5de4e235ef0bdac1a0e8 if (!checkPosition(this, x, y, z)) { return; } -@@ -4601,6 +4906,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4597,6 +4902,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @Override public final void setRemoved(Entity.RemovalReason removalReason, org.bukkit.event.entity.EntityRemoveEvent.Cause cause) { @@ -29095,7 +29095,7 @@ index 8d7c1ee6c1cd4419621b11029eb06bf8135e59aa..1d0151a042ed5de4e235ef0bdac1a0e8 org.bukkit.craftbukkit.event.CraftEventFactory.callEntityRemoveEvent(this, cause); // CraftBukkit end final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers -@@ -4612,7 +4923,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4608,7 +4919,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.stopRiding(); } @@ -29104,7 +29104,7 @@ index 8d7c1ee6c1cd4419621b11029eb06bf8135e59aa..1d0151a042ed5de4e235ef0bdac1a0e8 this.levelCallback.onRemove(removalReason); this.onRemoval(removalReason); // Paper start - Folia schedulers -@@ -4646,7 +4957,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4642,7 +4953,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess public boolean shouldBeSaved() { return (this.removalReason == null || this.removalReason.shouldSave()) && !this.isPassenger() diff --git a/paper-server/patches/sources/net/minecraft/world/entity/Entity.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/Entity.java.patch index 780a51d408..d4f61b6652 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/Entity.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/Entity.java.patch @@ -127,7 +127,7 @@ private final double[] pistonDeltas = new double[]{0.0, 0.0, 0.0}; private long pistonDeltasGameTime; private EntityDimensions dimensions; -@@ -250,6 +_,63 @@ +@@ -250,6 +_,59 @@ private final List movementThisTick = new ArrayList<>(); private final Set blocksInside = new ReferenceArraySet<>(); private final LongSet visitedBlocks = new LongOpenHashSet(); @@ -178,10 +178,6 @@ + public float getBukkitYaw() { + return this.yRot; + } -+ -+ public boolean isChunkLoaded() { -+ return this.level.hasChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); -+ } + // CraftBukkit end + // Paper start + public final AABB getBoundingBoxAt(double x, double y, double z) { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index 20f709a4e8..e5fe32d175 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -209,8 +209,8 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public int getEntityCount() { int ret = 0; - for (net.minecraft.world.entity.Entity entity : world.getEntities().getAll()) { - if (entity.isChunkLoaded()) { + for (net.minecraft.world.entity.Entity entity : this.world.getEntities().getAll()) { + if (entity.getBukkitEntity().isValid()) { ++ret; } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java index 6d81a19741..659f0f9c7e 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java @@ -414,7 +414,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @Override public boolean isValid() { - return this.entity.isAlive() && this.entity.valid && this.entity.isChunkLoaded() && this.isInWorld(); + return this.entity.isAlive() && this.entity.valid; } @Override