From 2e437216543251febabe759ba59ef1021d4a00a3 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Sun, 31 Mar 2019 22:18:39 -0700 Subject: [PATCH] Allow login events to fire only after the server has loaded Plugins that rely on the async login event to fire can miss the event if a player tries to log in before the server has loaded. The solution is to simply block the event threads from executing until the server has loaded. This will not have an adverse affect on logins since the event threads are cached and are only used for executing events asynchronously. --- ...ts-to-fire-only-after-the-server-plu.patch | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 Spigot-Server-Patches/0433-Allow-login-events-to-fire-only-after-the-server-plu.patch diff --git a/Spigot-Server-Patches/0433-Allow-login-events-to-fire-only-after-the-server-plu.patch b/Spigot-Server-Patches/0433-Allow-login-events-to-fire-only-after-the-server-plu.patch new file mode 100644 index 000000000..3cc4c1f49 --- /dev/null +++ b/Spigot-Server-Patches/0433-Allow-login-events-to-fire-only-after-the-server-plu.patch @@ -0,0 +1,72 @@ +From c285a117f05799e780ccde777d07772c5cacbc05 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sun, 31 Mar 2019 22:02:24 -0700 +Subject: [PATCH] Allow login events to fire only after the server plugins are + enabled + +Event threads will simply block until they're ready to accept. + +diff --git a/src/main/java/net/minecraft/server/LoginListener.java b/src/main/java/net/minecraft/server/LoginListener.java +index dfe7a029f..503f66582 100644 +--- a/src/main/java/net/minecraft/server/LoginListener.java ++++ b/src/main/java/net/minecraft/server/LoginListener.java +@@ -282,6 +282,36 @@ public class LoginListener implements PacketLoginInListener, ITickable { + } + } + ++ // Paper start - Delay async prelogin until plugins are ready ++ private static volatile Object blockingLogins = new Object(); ++ ++ public static void checkStartupAndBlock() { ++ final Object lock = LoginListener.blockingLogins; ++ if (lock != null) { ++ synchronized (lock) { ++ for (;;) { ++ if (LoginListener.blockingLogins == null) { ++ return; ++ } ++ try { ++ lock.wait(); ++ } catch (final InterruptedException ignore) {// handled by the if statement above ++ Thread.currentThread().interrupt(); ++ } ++ } ++ } ++ } ++ } ++ ++ public static void allowLogins() { ++ final Object lock = LoginListener.blockingLogins; ++ synchronized (lock) { ++ LoginListener.blockingLogins = null; ++ lock.notifyAll(); ++ } ++ } ++ // Paper end ++ + // Spigot start + public class LoginHandler { + +@@ -292,6 +322,7 @@ public class LoginListener implements PacketLoginInListener, ITickable { + return; + } + // Paper end ++ LoginListener.checkStartupAndBlock(); // Paper - Delay async login events until plugins are ready + String playerName = i.getName(); + java.net.InetAddress address = ((java.net.InetSocketAddress) networkManager.getSocketAddress()).getAddress(); + java.util.UUID uniqueId = i.getId(); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index d6250c472..8db5c6a35 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -606,6 +606,7 @@ public abstract class MinecraftServer implements IAsyncTaskHandler, IMojangStati + this.x = 0; + // CraftBukkit Start + this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD); ++ LoginListener.allowLogins(); // Paper - Allow logins once postworld + this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP)); + // CraftBukkit end + } +-- +2.21.0 +