1
0
Fork 0
mirror of https://github.com/PaperMC/Paper.git synced 2025-03-27 08:50:35 +01:00

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.
This commit is contained in:
Spottedleaf 2025-01-28 17:25:26 -08:00
parent 1004374a83
commit e2f0efd1af
5 changed files with 19 additions and 23 deletions
paper-server
patches
src/main/java/org/bukkit/craftbukkit

View file

@ -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);
}

View file

@ -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<VoxelShape> 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<Entity> 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()

View file

@ -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<Entity.Movement> movementThisTick = new ArrayList<>();
private final Set<BlockState> 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) {

View file

@ -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;
}
}

View file

@ -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