Ensure player entity schedulers are ticked when they are dead

If the player dies, then they are removed from the world and
as a result are not present in the world entity map.

To guarantee that the player entity scheduler is ticked, we can
tick all schedulers for players in the server player list, and
then skip all players we find in the world entity map.

This problem is not present on Folia since Folia must guarantee
that the player remains in the world.
This commit is contained in:
Spottedleaf
2025-06-24 05:10:19 -07:00
parent 38c1ddb52a
commit 2f083acbed
5 changed files with 21 additions and 12 deletions

View File

@@ -14,17 +14,17 @@ movement will load only the chunk the player enters anyways and avoids loading
massive amounts of surrounding chunks due to large AABB lookups. massive amounts of surrounding chunks due to large AABB lookups.
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 7453ddb09f349b7836f966573e4933646a75cba6..58eda0d6426f30cda604f4120f1ddb012316c108 100644 index 23dfc87db1d5e90099270627197abc0f787a4393..27a01fd28ea565221768f31df02f0a2ddf242fce 100644
--- a/net/minecraft/world/entity/Entity.java --- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java
@@ -229,6 +229,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -230,6 +230,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
// Paper end - Share random for entities to make them more random
public @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason public @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason
private volatile @Nullable org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity; // Paper - Folia schedulers - volatile
+ public boolean collisionLoadChunks = false; // Paper + public boolean collisionLoadChunks = false; // Paper
private @Nullable org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity;
public org.bukkit.craftbukkit.entity.CraftEntity getBukkitEntity() { public org.bukkit.craftbukkit.entity.CraftEntity getBukkitEntity() {
if (this.bukkitEntity == null) {
diff --git a/net/minecraft/world/level/BlockCollisions.java b/net/minecraft/world/level/BlockCollisions.java diff --git a/net/minecraft/world/level/BlockCollisions.java b/net/minecraft/world/level/BlockCollisions.java
index ed6e4f9fd0c7ad1219e66bc1cb4038191dd6edd8..45a20dbb935b12d429153463dba5d6fd3385dd7a 100644 index ed6e4f9fd0c7ad1219e66bc1cb4038191dd6edd8..45a20dbb935b12d429153463dba5d6fd3385dd7a 100644
--- a/net/minecraft/world/level/BlockCollisions.java --- a/net/minecraft/world/level/BlockCollisions.java

View File

@@ -23866,7 +23866,7 @@ index 46de98a6bbbae48c4837e1e588ba198a363d2dde..fd3553bdc1c3cdbf6aa3dc00e0a4987f
thread1 -> { thread1 -> {
DedicatedServer dedicatedServer1 = new DedicatedServer( DedicatedServer dedicatedServer1 = new DedicatedServer(
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index aea96ab1c5f2dae9f2a19126e8be314d06b99bc3..388bf752fd09745e8c470b5bca4d004708a2d82f 100644 index 75aba65cbe1a943f21c7464ff9465e64f63e8e5b..32475c0958fd7e0f1f9b494b0cc78a4a718d12b8 100644
--- a/net/minecraft/server/MinecraftServer.java --- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java
@@ -173,7 +173,7 @@ import net.minecraft.world.phys.Vec2; @@ -173,7 +173,7 @@ import net.minecraft.world.phys.Vec2;
@@ -24058,7 +24058,7 @@ index aea96ab1c5f2dae9f2a19126e8be314d06b99bc3..388bf752fd09745e8c470b5bca4d0047
return true; return true;
} else { } else {
boolean ret = false; // Paper - force execution of all worlds, do not just bias the first boolean ret = false; // Paper - force execution of all worlds, do not just bias the first
@@ -2469,6 +2557,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -2478,6 +2566,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} }
} }
@@ -28727,7 +28727,7 @@ index 8cc5c0716392ba06501542ff5cbe71ee43979e5d..09fd99c9cbd23b5f3c899bfb00c9b896
+ // Paper end - block counting + // Paper end - block counting
} }
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index fa2ffc44336c3ddfe576b202154f14ef91a301b9..7546ff4c5ffc62d93a3f874519db8fef1e3bfbcb 100644 index 27a01fd28ea565221768f31df02f0a2ddf242fce..45cdbea0bbf12697ffd1fb2193c2eafe34142ea9 100644
--- a/net/minecraft/world/entity/Entity.java --- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java
@@ -147,7 +147,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter; @@ -147,7 +147,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter;

View File

@@ -48,10 +48,10 @@ index 0000000000000000000000000000000000000000..24a2090e068ad3c0d08705050944abdf
+ } + }
+} +}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 39581095ccc69d113d954ed835bdfa32d25b5489..ce7d72e02797da1ae408d0d310420e30aaa0ce28 100644 index cff9d761dfee8a90b19fb2f3e678f99a39fc000c..0a260fdf6b198a8ab52e60bf6db2fb5eab719c48 100644
--- a/net/minecraft/server/MinecraftServer.java --- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java
@@ -1709,6 +1709,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1718,6 +1718,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
serverLevel.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent serverLevel.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent
serverLevel.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent serverLevel.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent
serverLevel.updateLagCompensationTick(); // Paper - lag compensation serverLevel.updateLagCompensationTick(); // Paper - lag compensation

View File

@@ -984,16 +984,25 @@
ObjectArrayList<GameProfile> list = new ObjectArrayList<>(min); ObjectArrayList<GameProfile> list = new ObjectArrayList<>(min);
int randomInt = Mth.nextInt(this.random, 0, players.size() - min); int randomInt = Mth.nextInt(this.random, 0, players.size() - min);
@@ -1040,17 +_,66 @@ @@ -1040,17 +_,75 @@
protected void tickChildren(BooleanSupplier hasTimeLeft) { protected void tickChildren(BooleanSupplier hasTimeLeft) {
ProfilerFiller profilerFiller = Profiler.get(); ProfilerFiller profilerFiller = Profiler.get();
this.getPlayerList().getPlayers().forEach(serverPlayer1 -> serverPlayer1.connection.suspendFlushing()); this.getPlayerList().getPlayers().forEach(serverPlayer1 -> serverPlayer1.connection.suspendFlushing());
+ this.server.getScheduler().mainThreadHeartbeat(); // CraftBukkit + this.server.getScheduler().mainThreadHeartbeat(); // CraftBukkit
+ // Paper start - Folia scheduler API + // Paper start - Folia scheduler API
+ ((io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler) org.bukkit.Bukkit.getGlobalRegionScheduler()).tick(); + ((io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler) org.bukkit.Bukkit.getGlobalRegionScheduler()).tick();
+ for (ServerPlayer player : this.playerList.players) {
+ if (!this.playerList.players.contains(player)) {
+ continue;
+ }
+ final org.bukkit.craftbukkit.entity.CraftEntity bukkit = player.getBukkitEntityRaw();
+ if (bukkit != null) {
+ bukkit.taskScheduler.executeTick();
+ }
+ }
+ getAllLevels().forEach(level -> { + getAllLevels().forEach(level -> {
+ for (final net.minecraft.world.entity.Entity entity : io.papermc.paper.FeatureHooks.getAllEntities(level)) { + for (final net.minecraft.world.entity.Entity entity : io.papermc.paper.FeatureHooks.getAllEntities(level)) {
+ if (entity.isRemoved()) { + if (entity.isRemoved() || entity instanceof ServerPlayer) {
+ continue; + continue;
+ } + }
+ final org.bukkit.craftbukkit.entity.CraftEntity bukkit = entity.getBukkitEntityRaw(); + final org.bukkit.craftbukkit.entity.CraftEntity bukkit = entity.getBukkitEntityRaw();

View File

@@ -85,7 +85,7 @@
+ // Paper end - Share random for entities to make them more random + // Paper end - Share random for entities to make them more random
+ public @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason + public @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason
+ +
+ private @Nullable org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity; + private volatile @Nullable org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity; // Paper - Folia schedulers - volatile
+ +
+ public org.bukkit.craftbukkit.entity.CraftEntity getBukkitEntity() { + public org.bukkit.craftbukkit.entity.CraftEntity getBukkitEntity() {
+ if (this.bukkitEntity == null) { + if (this.bukkitEntity == null) {