diff --git a/paper-server/patches/features/0001-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0001-Moonrise-optimisation-patches.patch index a5f3d6a17457..417ebbcbb383 100644 --- a/paper-server/patches/features/0001-Moonrise-optimisation-patches.patch +++ b/paper-server/patches/features/0001-Moonrise-optimisation-patches.patch @@ -29298,7 +29298,7 @@ index 09b6da207530987b483444cebeadc2f1c9a15247..3666c3efd188508153b6482db425648e + // Paper end - block counting } diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index ec8b47eebc30a73adb3195aa91fd5b82518cac2d..4b74c91b47318d048abc53952ebeae7615f50524 100644 +index d6772f96af5a103c41fcc776f478f79ca72da447..23001241b9d9927b7207f40ad6d61811ff30f9eb 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java @@ -164,7 +164,7 @@ public abstract class Entity @@ -29549,7 +29549,7 @@ index ec8b47eebc30a73adb3195aa91fd5b82518cac2d..4b74c91b47318d048abc53952ebeae76 public Entity(final EntityType type, final Level level) { this.type = type; -@@ -1484,34 +1590,76 @@ public abstract class Entity +@@ -1501,34 +1607,76 @@ public abstract class Entity } private Vec3 collide(final Vec3 movement) { @@ -29649,7 +29649,7 @@ index ec8b47eebc30a73adb3195aa91fd5b82518cac2d..4b74c91b47318d048abc53952ebeae76 } private static float[] collectCandidateStepUpHeights( -@@ -2832,17 +2980,106 @@ public abstract class Entity +@@ -2849,17 +2997,106 @@ public abstract class Entity return false; } @@ -29766,7 +29766,7 @@ index ec8b47eebc30a73adb3195aa91fd5b82518cac2d..4b74c91b47318d048abc53952ebeae76 } public InteractionResult interact(final Player player, final InteractionHand hand, final Vec3 location) { -@@ -4449,15 +4686,17 @@ public abstract class Entity +@@ -4466,15 +4703,17 @@ public abstract class Entity } public Iterable getIndirectPassengers() { @@ -29792,7 +29792,7 @@ index ec8b47eebc30a73adb3195aa91fd5b82518cac2d..4b74c91b47318d048abc53952ebeae76 } public int countPlayerPassengers() { -@@ -4768,6 +5007,15 @@ public abstract class Entity +@@ -4785,6 +5024,15 @@ public abstract class Entity } public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) { @@ -29808,7 +29808,7 @@ index ec8b47eebc30a73adb3195aa91fd5b82518cac2d..4b74c91b47318d048abc53952ebeae76 if (!checkPosition(this, x, y, z)) { return; } -@@ -4917,6 +5165,12 @@ public abstract class Entity +@@ -4934,6 +5182,12 @@ public abstract class Entity @Override public final void setRemoved(final Entity.RemovalReason reason, org.bukkit.event.entity.EntityRemoveEvent.@Nullable Cause cause) { // CraftBukkit - add Bukkit remove cause @@ -29821,7 +29821,7 @@ index ec8b47eebc30a73adb3195aa91fd5b82518cac2d..4b74c91b47318d048abc53952ebeae76 org.bukkit.craftbukkit.event.CraftEventFactory.callEntityRemoveEvent(this, cause); // CraftBukkit final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers if (this.removalReason == null) { -@@ -4928,7 +5182,7 @@ public abstract class Entity +@@ -4945,7 +5199,7 @@ public abstract class Entity this.stopRiding(); } @@ -29830,7 +29830,7 @@ index ec8b47eebc30a73adb3195aa91fd5b82518cac2d..4b74c91b47318d048abc53952ebeae76 this.levelCallback.onRemove(reason); this.onRemoval(reason); // Paper start - Folia schedulers -@@ -4966,7 +5220,7 @@ public abstract class Entity +@@ -4983,7 +5237,7 @@ public abstract class Entity public boolean shouldBeSaved() { return (this.removalReason == null || this.removalReason.shouldSave()) && !this.isPassenger() 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 6ed4e07f3f37..6a0233096903 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 @@ -355,7 +355,7 @@ index 0000000000000000000000000000000000000000..829f7685904fd741e00403647ae76d32 + } +} diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index e5328f08d6a323aa1307ed791a88916b4588939c..1afbe7a877f8055702809bc33b110bdf2933f999 100644 +index 4fce291cb7cd6eb2f4e47237fe247a5d666da0ad..6cf92a7ae011fe4fa55cd744dce8d5f8fb49b1ec 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java @@ -880,6 +880,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet @@ -463,7 +463,7 @@ index 271ed1128959287f6c1b6ca59ded377b88f5afff..f03fa06c0ba56f7f5e1e45bc1568a490 public void tick() { super.tick(); diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index a5792bc27fdc85ecf388ab44c0b1b3055fc41d21..4a18f74c7513f0ac6a3415163165d9239ee5b567 100644 +index 23001241b9d9927b7207f40ad6d61811ff30f9eb..1484558ea50760fbee7a31df413637ce685ea001 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java @@ -383,6 +383,15 @@ public abstract class Entity @@ -496,7 +496,7 @@ index a5792bc27fdc85ecf388ab44c0b1b3055fc41d21..4a18f74c7513f0ac6a3415163165d923 SynchedEntityData.Builder entityDataBuilder = new SynchedEntityData.Builder(this); entityDataBuilder.define(DATA_SHARED_FLAGS_ID, (byte)0); entityDataBuilder.define(DATA_AIR_SUPPLY_ID, this.getMaxAirSupply()); -@@ -1141,6 +1157,10 @@ public abstract class Entity +@@ -1158,6 +1174,10 @@ public abstract class Entity } else { if (moverType == MoverType.PISTON) { delta = this.limitPistonMovement(delta); @@ -507,7 +507,7 @@ index a5792bc27fdc85ecf388ab44c0b1b3055fc41d21..4a18f74c7513f0ac6a3415163165d923 if (delta.equals(Vec3.ZERO)) { return; } -@@ -1156,6 +1176,13 @@ public abstract class Entity +@@ -1173,6 +1193,13 @@ public abstract class Entity this.stuckSpeedMultiplier = Vec3.ZERO; this.setDeltaMovement(Vec3.ZERO); } diff --git a/paper-server/patches/features/0017-Optimise-EntityScheduler-ticking.patch b/paper-server/patches/features/0017-Optimise-EntityScheduler-ticking.patch index c7b9ca610cfc..945dbdd9890a 100644 --- a/paper-server/patches/features/0017-Optimise-EntityScheduler-ticking.patch +++ b/paper-server/patches/features/0017-Optimise-EntityScheduler-ticking.patch @@ -66,10 +66,10 @@ index 6de2929fda582cc4ceecd7bfe0b440ac6608669d..2381f8571f6e614dba1cfb62a1d396be io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.ADVENTURE_CLICK_MANAGER.handleQueue(this.tickCount); // Paper io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.DIALOG_CLICK_MANAGER.handleQueue(this.tickCount); // Paper diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index f8f479bd0ce2498c0cf4beab07d961247735e23c..d958c4717739e588c5f8985dec5d215c745f49fc 100644 +index 1484558ea50760fbee7a31df413637ce685ea001..db67d4c41ad6174e9e543c5476b6d40aae1e7f04 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -5237,6 +5237,11 @@ public abstract class Entity +@@ -5254,6 +5254,11 @@ public abstract class Entity this.getBukkitEntity().taskScheduler.retire(); } // Paper end - Folia schedulers 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 ba31084206e7..55455898bb4f 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 @@ -492,7 +492,7 @@ } public boolean isFree(final double xa, final double ya, final double za) { -@@ -709,7 +_,28 @@ +@@ -709,7 +_,45 @@ return this.onGround; } @@ -504,6 +504,23 @@ + private double moveStartX; + private double moveStartY; + private double moveStartZ; ++ ++ @Nullable ++ public final Vec3 getMoveVector() { ++ return this.moveVector; ++ } ++ ++ public final double getMoveStartX() { ++ return this.moveStartX; ++ } ++ ++ public final double getMoveStartY() { ++ return this.moveStartY; ++ } ++ ++ public final double getMoveStartZ() { ++ return this.moveStartZ; ++ } + // Paper end - detailed watchdog information + public void move(final MoverType moverType, Vec3 delta) { diff --git a/paper-server/src/main/java/org/spigotmc/WatchdogThread.java b/paper-server/src/main/java/org/spigotmc/WatchdogThread.java index ab6c553f0f5c..de3f9113a075 100644 --- a/paper-server/src/main/java/org/spigotmc/WatchdogThread.java +++ b/paper-server/src/main/java/org/spigotmc/WatchdogThread.java @@ -109,6 +109,7 @@ public void run() { logger.log(Level.SEVERE, "------------------------------"); logger.log(Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):"); // Paper FeatureHooks.dumpAllChunkLoadInfo(MinecraftServer.getServer(), isLongTimeout); // Paper - log detailed tick information + WatchdogThread.dumpTickingInfo(logger); WatchdogThread.dumpThread(ManagementFactory.getThreadMXBean().getThreadInfo(MinecraftServer.getServer().getRunningThread().threadId(), Integer.MAX_VALUE), logger); logger.log(Level.SEVERE, "------------------------------"); @@ -156,6 +157,79 @@ public void run() { } } + private static void dumpTickingInfo(Logger logger) { + // The state read below is mutated by the (hung) server thread while we read it, so it may be torn or null + // in ways the normal invariants disallow. Never let that take down the watchdog itself - a failed dump must + // not stop us from printing the thread dump and, on a long timeout, halting the server. + try { + // ticking entities + for (net.minecraft.world.entity.Entity entity : net.minecraft.server.level.ServerLevel.getCurrentlyTickingEntities()) { + WatchdogThread.dumpEntity(entity, logger); + net.minecraft.world.entity.Entity vehicle = entity.getVehicle(); + if (vehicle != null) { + logger.log(Level.SEVERE, "Detailing vehicle for above entity:"); + WatchdogThread.dumpEntity(vehicle, logger); + } + } + + // packet processors + for (net.minecraft.network.PacketListener packetListener : net.minecraft.network.PacketProcessor.getCurrentPacketProcessors()) { + if (packetListener instanceof net.minecraft.server.network.ServerGamePacketListenerImpl gamePacketListener) { + net.minecraft.server.level.ServerPlayer player = gamePacketListener.player; + long totalPackets = net.minecraft.network.PacketProcessor.getTotalProcessedPackets(); + if (player == null) { + logger.log(Level.SEVERE, "Handling packet for player connection or ticking player connection (null player): " + packetListener); + } else { + WatchdogThread.dumpEntity(player, logger); + net.minecraft.world.entity.Entity vehicle = player.getVehicle(); + if (vehicle != null) { + logger.log(Level.SEVERE, "Detailing vehicle for above entity:"); + WatchdogThread.dumpEntity(vehicle, logger); + } + } + logger.log(Level.SEVERE, "Total packets processed on the main thread for all players: " + totalPackets); + } else { + logger.log(Level.SEVERE, "Handling packet for connection: " + packetListener); + } + } + } catch (Throwable thr) { + logger.log(Level.SEVERE, "Failed to dump ticking information", thr); + } + } + + private static void dumpEntity(final net.minecraft.world.entity.Entity entity, Logger logger) { + double posX, posY, posZ; + net.minecraft.world.phys.Vec3 mot; + double moveStartX, moveStartY, moveStartZ; + net.minecraft.world.phys.Vec3 moveVec; + synchronized (entity.posLock) { + posX = entity.getX(); + posY = entity.getY(); + posZ = entity.getZ(); + mot = entity.getDeltaMovement(); + moveStartX = entity.getMoveStartX(); + moveStartY = entity.getMoveStartY(); + moveStartZ = entity.getMoveStartZ(); + moveVec = entity.getMoveVector(); + } + + String entityType = net.minecraft.world.entity.EntityType.getKey(entity.getType()).toString(); + java.util.UUID entityUUID = entity.getUUID(); + net.minecraft.world.level.Level world = entity.level(); + + logger.log(Level.SEVERE, "Ticking entity: " + entityType + ", entity class: " + entity.getClass().getName()); + logger.log(Level.SEVERE, "Entity status: removed: " + entity.isRemoved() + ", valid: " + entity.valid + ", alive: " + entity.isAlive() + ", is passenger: " + entity.isPassenger()); + logger.log(Level.SEVERE, "Entity UUID: " + entityUUID); + logger.log(Level.SEVERE, "Position: world: '" + (world == null ? "unknown world?" : world.getWorld().getName()) + "' at location (" + posX + ", " + posY + ", " + posZ + ")"); + logger.log(Level.SEVERE, "Velocity: " + (mot == null ? "unknown velocity" : mot.toString()) + " (in blocks per tick)"); + logger.log(Level.SEVERE, "Entity AABB: " + entity.getBoundingBox()); + if (moveVec != null) { + logger.log(Level.SEVERE, "Move call information: "); + logger.log(Level.SEVERE, "Start position: (" + moveStartX + ", " + moveStartY + ", " + moveStartZ + ")"); + logger.log(Level.SEVERE, "Move vector: " + moveVec.toString()); + } + } + private static void dumpThread(ThreadInfo thread, Logger logger) { logger.log(Level.SEVERE, "------------------------------");