From 4de49b1c8f7cf989408ace284518ce48d2048966 Mon Sep 17 00:00:00 2001 From: amyavi <144570677+amyavi@users.noreply.github.com> Date: Fri, 8 Aug 2025 02:15:14 -0300 Subject: [PATCH] refactor: use paper's new configuration phase events --- .../modules/player/PlayerConnection.java | 62 +++++++++++-------- .../extras/modules/player/PlayerPrefix.java | 4 +- .../java/pw/kaboom/extras/util/Utility.java | 23 +++++++ 3 files changed, 60 insertions(+), 29 deletions(-) diff --git a/src/main/java/pw/kaboom/extras/modules/player/PlayerConnection.java b/src/main/java/pw/kaboom/extras/modules/player/PlayerConnection.java index 4dd8c802..460156d5 100644 --- a/src/main/java/pw/kaboom/extras/modules/player/PlayerConnection.java +++ b/src/main/java/pw/kaboom/extras/modules/player/PlayerConnection.java @@ -3,19 +3,18 @@ import com.destroystokyo.paper.event.profile.PreLookupProfileEvent; import com.google.common.base.Charsets; import io.papermc.paper.event.player.AsyncPlayerSpawnLocationEvent; +import io.papermc.paper.event.connection.PlayerConnectionValidateLoginEvent; +import io.papermc.paper.event.player.PlayerServerFullCheckEvent; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.kyori.adventure.title.Title; -import org.bukkit.Bukkit; import org.bukkit.Location; -import org.bukkit.Server; import org.bukkit.World; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.*; -import org.bukkit.event.player.PlayerLoginEvent.Result; import org.bukkit.plugin.java.JavaPlugin; import pw.kaboom.extras.Main; import pw.kaboom.extras.modules.server.ServerTabComplete; @@ -23,6 +22,8 @@ import pw.kaboom.extras.util.Utility; import java.time.Duration; +import java.util.HashSet; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; @@ -55,6 +56,7 @@ public final class PlayerConnection implements Listener { "allowJoinOnFullServer"); private static final boolean OP_ON_JOIN = CONFIG.getBoolean("opOnJoin"); private static final boolean RANDOMIZE_SPAWN = CONFIG.getBoolean("randomizeSpawn"); + private final Set disallowedLogins = new HashSet<>(5); @EventHandler void onAsyncPlayerPreLogin(final AsyncPlayerPreLoginEvent event) { @@ -83,6 +85,10 @@ void onAsyncPlayerPreLogin(final AsyncPlayerPreLoginEvent event) { void onPlayerJoin(final PlayerJoinEvent event) { final Player player = event.getPlayer(); + if (OP_ON_JOIN && !player.isOp()) { + player.setOp(true); + } + player.showTitle(Title.title( TITLE, SUBTITLE, @@ -90,6 +96,10 @@ void onPlayerJoin(final PlayerJoinEvent event) { )); ServerTabComplete.getLoginNameList().put(player.getUniqueId(), player.getName()); + + if (!player.getPlayerProfile().hasTextures()) { + SkinManager.applySkin(player, player.getName(), false); + } } @EventHandler @@ -100,34 +110,32 @@ void onPlayerKick(final PlayerKickEvent event) { } @EventHandler - void onPlayerLogin(final PlayerLoginEvent event) { - // #312 - If allow join on full server is off, - // but join restrictions are disabled, - // player can still join on full server - - // Full server kicks should be handled differently from other join restrictions - // since we have a separate configuration value for it - - if (!ENABLE_JOIN_RESTRICTIONS && !Result.KICK_FULL.equals(event.getResult())) { - event.allow(); + void onPlayerServerFullCheck(final PlayerServerFullCheckEvent event) { + if (ALLOW_JOIN_ON_FULL_SERVER) { + event.allow(true); + } else if (!event.isAllowed()) { + this.disallowedLogins.add(event.getPlayerProfile().getId()); } + } - if (Result.KICK_FULL.equals(event.getResult()) && ALLOW_JOIN_ON_FULL_SERVER) { + // Note that this event gets fired even if FullCheckEvent returns disallowed, meaning we need + // to keep track of the player's allowed state across events. Yuck. + @SuppressWarnings("UnstableApiUsage") + @EventHandler + void onPlayerConnectionValidate(final PlayerConnectionValidateLoginEvent event) { + // #312 - If allow join on full server is off, but join restrictions are disabled, player + // can still join on full server + + // Full server kicks should be handled differently from other join restrictions since we + // have a separate configuration value for it + final UUID uuid = Utility.getConnectionUuid(event.getConnection()); + final boolean disallowed = this.disallowedLogins.remove(uuid); + + // If uuid is null, disallowedLogins will never contain it. So we always let connections + // without a UUID through if join restrictions are disabled. + if (!ENABLE_JOIN_RESTRICTIONS && !disallowed) { event.allow(); } - - final Player player = event.getPlayer(); - - if (OP_ON_JOIN && !player.isOp()) { - player.setOp(true); - } - - final Server server = Bukkit.getServer(); - - - if (!server.getOnlineMode()) { - SkinManager.applySkin(player, player.getName(), false); - } } @EventHandler diff --git a/src/main/java/pw/kaboom/extras/modules/player/PlayerPrefix.java b/src/main/java/pw/kaboom/extras/modules/player/PlayerPrefix.java index efae707f..da7d9368 100644 --- a/src/main/java/pw/kaboom/extras/modules/player/PlayerPrefix.java +++ b/src/main/java/pw/kaboom/extras/modules/player/PlayerPrefix.java @@ -9,7 +9,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitScheduler; @@ -110,7 +110,7 @@ private static void onUpdate(Player player) throws IOException { } @EventHandler(priority = EventPriority.MONITOR) - public void onPlayerLoginEvent(PlayerLoginEvent event) throws IOException { + public void onPlayerJoinEvent(PlayerJoinEvent event) throws IOException { final Player player = event.getPlayer(); final boolean isOp = player.isOp(); diff --git a/src/main/java/pw/kaboom/extras/util/Utility.java b/src/main/java/pw/kaboom/extras/util/Utility.java index 5c3c1649..ad402590 100644 --- a/src/main/java/pw/kaboom/extras/util/Utility.java +++ b/src/main/java/pw/kaboom/extras/util/Utility.java @@ -1,5 +1,9 @@ package pw.kaboom.extras.util; +import com.destroystokyo.paper.profile.PlayerProfile; +import io.papermc.paper.connection.PlayerConfigurationConnection; +import io.papermc.paper.connection.PlayerConnection; +import io.papermc.paper.connection.PlayerLoginConnection; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; @@ -13,10 +17,29 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.UUID; import java.util.concurrent.Callable; import java.util.function.Function; public final class Utility { + @SuppressWarnings("UnstableApiUsage") + public static @Nullable UUID getConnectionUuid(final PlayerConnection connection) { + // https://discord.com/channels/289587909051416579/555462289851940864/1391545447495237637 + // Thanks, Paper! + final PlayerProfile profile; + if ((connection instanceof final PlayerLoginConnection loginConnection)) { + profile = loginConnection.getAuthenticatedProfile() != null + ? loginConnection.getAuthenticatedProfile() + : loginConnection.getUnsafeProfile(); + } else if ((connection instanceof final PlayerConfigurationConnection configConnection)) { + profile = configConnection.getProfile(); + } else { + profile = null; + } + + return profile != null ? profile.getId() : null; + } + public static void teleportToSpawn(final Player player, final PlayerTeleportEvent.TeleportCause cause) { final World world = player.getServer().getRespawnWorld();