From 6b3f3d8d8c37935db479ea0fa561d993ffd6b978 Mon Sep 17 00:00:00 2001 From: Aikar Date: Wed, 29 Apr 2020 04:14:47 -0400 Subject: [PATCH] Improve Async Login to avoid firing in middle of Entity Ticking If a sync load was triggered, it would process pending join events, causing them to be added to the world in the middle of the entity ticking process. This caused their add to be queued instead of immediate, causing "Illegal Tracking" errors. This schedules it to fire at the players next Connection Tick, which is exactly where this entire process use to run anyways. Also added missing tab complete and syntax for syncloadinfo debug command --- .../Allow-sleeping-players-to-float.patch | 2 +- ...low-bees-to-load-chunks-for-beehives.patch | 4 +- ...Load-Chunks-for-Login-Asynchronously.patch | 52 ++++++++++++++++--- Spigot-Server-Patches/Reduce-sync-loads.patch | 19 ++++++- 4 files changed, 66 insertions(+), 11 deletions(-) diff --git a/Spigot-Server-Patches/Allow-sleeping-players-to-float.patch b/Spigot-Server-Patches/Allow-sleeping-players-to-float.patch index ca49abb44..5b21655d5 100644 --- a/Spigot-Server-Patches/Allow-sleeping-players-to-float.patch +++ b/Spigot-Server-Patches/Allow-sleeping-players-to-float.patch @@ -9,7 +9,7 @@ their position to the ground/exit location when entering the bed, resulting in the server believing they're still in the air. diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index c3710b73af..b62535ba04 100644 +index 8800a8fcf9..38ec22f4c0 100644 --- a/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/PlayerConnection.java @@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { diff --git a/Spigot-Server-Patches/Do-not-allow-bees-to-load-chunks-for-beehives.patch b/Spigot-Server-Patches/Do-not-allow-bees-to-load-chunks-for-beehives.patch index b3e277e5c..dd4814335 100644 --- a/Spigot-Server-Patches/Do-not-allow-bees-to-load-chunks-for-beehives.patch +++ b/Spigot-Server-Patches/Do-not-allow-bees-to-load-chunks-for-beehives.patch @@ -1,11 +1,11 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer +From: chickeneer Date: Tue, 17 Mar 2020 14:18:50 -0500 Subject: [PATCH] Do not allow bees to load chunks for beehives diff --git a/src/main/java/net/minecraft/server/EntityBee.java b/src/main/java/net/minecraft/server/EntityBee.java -index c7d79efd..dd1d246a 100644 +index c7d79efdf6..dd1d246aeb 100644 --- a/src/main/java/net/minecraft/server/EntityBee.java +++ b/src/main/java/net/minecraft/server/EntityBee.java @@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements EntityBird { diff --git a/Spigot-Server-Patches/Load-Chunks-for-Login-Asynchronously.patch b/Spigot-Server-Patches/Load-Chunks-for-Login-Asynchronously.patch index 19fa95cd8..cb860e80c 100644 --- a/Spigot-Server-Patches/Load-Chunks-for-Login-Asynchronously.patch +++ b/Spigot-Server-Patches/Load-Chunks-for-Login-Asynchronously.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Load Chunks for Login Asynchronously diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 96a47dd1c2..96ebe0b226 100644 +index 324fd07bce..01330045c0 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java @@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke @@ -18,7 +18,7 @@ index 96a47dd1c2..96ebe0b226 100644 public void setPositionRotation(BlockPosition blockposition, float f, float f1) { diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index 686fd4cbad..079ddc714e 100644 +index a48e113b53..0f9bca8b8b 100644 --- a/src/main/java/net/minecraft/server/EntityPlayer.java +++ b/src/main/java/net/minecraft/server/EntityPlayer.java @@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { @@ -60,19 +60,37 @@ index f1222fcb2b..28f48f2252 100644 if (entityplayer != null) { this.g = LoginListener.EnumProtocolState.DELAY_ACCEPT; diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 7929fcc800..c3710b73af 100644 +index 2e81f3a1d9..8800a8fcf9 100644 --- a/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { + private static final Logger LOGGER = LogManager.getLogger(); + public final NetworkManager networkManager; + private final MinecraftServer minecraftServer; ++ Runnable playerJoinReady; // Paper + public EntityPlayer player; + private int e; + private long lastKeepAlive = SystemUtils.getMonotonicMillis(); private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER @@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { // CraftBukkit end public void tick() { -+ if (!this.player.valid) return; // Paper ++ // Paper start - login async ++ Runnable playerJoinReady = this.playerJoinReady; ++ if (playerJoinReady != null) { ++ this.playerJoinReady = null; ++ playerJoinReady.run(); ++ } ++ // Don't tick if not valid (dead), otherwise we load chunks below ++ if (!this.player.valid) { ++ return; ++ } ++ // Paper end this.syncPosition(); this.player.lastX = this.player.locX(); this.player.lastY = this.player.locY(); diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java -index ec45c30dd3..eaba3cbf06 100644 +index ec45c30dd3..edf9df8c8a 100644 --- a/src/main/java/net/minecraft/server/PlayerList.java +++ b/src/main/java/net/minecraft/server/PlayerList.java @@ -0,0 +0,0 @@ public abstract class PlayerList { @@ -119,8 +137,12 @@ index ec45c30dd3..eaba3cbf06 100644 + int chunkX = loc.getBlockX() >> 4; + int chunkZ = loc.getBlockZ() >> 4; + worldserver.getChunkProvider().getTickingChunkAsync(chunkX, chunkZ, (chunk -> { // use ticking - as it has at least 1 neighbours loaded -+ postChunkLoadJoin(entityplayer, finalWorldserver, networkmanager, playerconnection, nbttagcompound, networkmanager.getSocketAddress().toString(), -+ lastKnownName); ++ playerconnection.playerJoinReady = () -> { ++ postChunkLoadJoin( ++ entityplayer, finalWorldserver, networkmanager, playerconnection, ++ nbttagcompound, networkmanager.getSocketAddress().toString(), lastKnownName ++ ); ++ }; + })); + // boost the priorities + worldserver.asyncChunkTaskManager.raisePriority(chunkX, chunkZ, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); @@ -158,6 +180,22 @@ index ec45c30dd3..eaba3cbf06 100644 if (entityplayer.getProfile().getName().equalsIgnoreCase(s)) { @@ -0,0 +0,0 @@ public abstract class PlayerList { + } + entityplayer.sentListPacket = true; + entityplayer.supressTrackerForLogin = false; // Paper +- ((WorldServer)entityplayer.world).getChunkProvider().playerChunkMap.addEntity(entityplayer); // Paper - track entity now + // CraftBukkit end + + entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityMetadata(entityplayer.getId(), entityplayer.datawatcher, true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn +@@ -0,0 +0,0 @@ public abstract class PlayerList { + } + + // Paper start - move vehicle into method so it can be called above - short circuit around that code ++ ((WorldServer)entityplayer.world).getChunkProvider().playerChunkMap.addEntity(entityplayer); // track entity now + onPlayerJoinFinish(entityplayer, worldserver, s1); + } + private void mountSavedVehicle(EntityPlayer entityplayer, WorldServer worldserver, NBTTagCompound nbttagcompound) { +@@ -0,0 +0,0 @@ public abstract class PlayerList { protected void savePlayerFile(EntityPlayer entityplayer) { if (!entityplayer.getBukkitEntity().isPersistent()) return; // CraftBukkit diff --git a/Spigot-Server-Patches/Reduce-sync-loads.patch b/Spigot-Server-Patches/Reduce-sync-loads.patch index 93926e368..d81df3296 100644 --- a/Spigot-Server-Patches/Reduce-sync-loads.patch +++ b/Spigot-Server-Patches/Reduce-sync-loads.patch @@ -11,7 +11,7 @@ it must be enabled by setting the startup flag -Dpaper.debug-sync-loads=true To get a debug log for sync loads, the command is /paper syncloadinfo diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index af81098784..dfe92780ad 100644 +index af81098784..ddb60e9a48 100644 --- a/src/main/java/com/destroystokyo/paper/PaperCommand.java +++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java @@ -0,0 +0,0 @@ @@ -38,6 +38,23 @@ index af81098784..dfe92780ad 100644 import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; +@@ -0,0 +0,0 @@ public class PaperCommand extends Command { + public PaperCommand(String name) { + super(name); + this.description = "Paper related commands"; +- this.usageMessage = "/paper [heap | entity | reload | version | debug | chunkinfo]"; ++ this.usageMessage = "/paper [heap | entity | reload | version | debug | chunkinfo | syncloadinfo]"; + this.setPermission("bukkit.command.paper"); + } + + @Override + public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { + if (args.length <= 1) +- return getListMatchingLast(args, "heap", "entity", "reload", "version", "debug", "chunkinfo"); ++ return getListMatchingLast(args, "heap", "entity", "reload", "version", "debug", "chunkinfo", "syncloadinfo"); + + switch (args[0].toLowerCase(Locale.ENGLISH)) + { @@ -0,0 +0,0 @@ public class PaperCommand extends Command { case "chunkinfo": doChunkInfo(sender, args);