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.
This commit is contained in:
Spottedleaf 2019-03-31 22:18:39 -07:00 committed by Aikar
parent e9b353ff02
commit 2e43721654
No known key found for this signature in database
GPG key ID: 401ADFC9891FAAFE

View file

@ -0,0 +1,72 @@
From c285a117f05799e780ccde777d07772c5cacbc05 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
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