From 40fa45ef8d297de77cc039cadfa19be72f33fdae Mon Sep 17 00:00:00 2001 From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> Date: Mon, 17 Mar 2025 20:54:15 -0400 Subject: [PATCH] Refactor `Improve Purpur AFK system` * Move Leaf config init before Minecraft commands register * Fix broken afk command cooldown * Cleanup code --- .../features/0002-Leaf-config.patch | 14 +- ...0007-Purpur-Server-Minecraft-Changes.patch | 4 +- .../0044-Improve-Purpur-AFK-system.patch | 168 ++++++++++-------- .../config/modules/gameplay/AfkCommand.java | 23 +++ 4 files changed, 126 insertions(+), 83 deletions(-) create mode 100644 leaf-server/src/main/java/org/dreeam/leaf/config/modules/gameplay/AfkCommand.java diff --git a/leaf-server/minecraft-patches/features/0002-Leaf-config.patch b/leaf-server/minecraft-patches/features/0002-Leaf-config.patch index 4487f23f..3a006aac 100644 --- a/leaf-server/minecraft-patches/features/0002-Leaf-config.patch +++ b/leaf-server/minecraft-patches/features/0002-Leaf-config.patch @@ -11,17 +11,17 @@ Add per world config Add config reload diff --git a/net/minecraft/server/Main.java b/net/minecraft/server/Main.java -index 9aa664537cc37e44db46d5a2a64ae3116938c681..748816e3f325468f523bdb8dfb94992883ed1989 100644 +index 9aa664537cc37e44db46d5a2a64ae3116938c681..43842de34adda95e78025c2b00639b31b774a78b 100644 --- a/net/minecraft/server/Main.java +++ b/net/minecraft/server/Main.java -@@ -112,6 +112,7 @@ public class Main { +@@ -108,6 +108,7 @@ public class Main { + JvmProfiler.INSTANCE.start(Environment.SERVER); + } + ++ org.dreeam.leaf.config.LeafConfig.loadConfig(); // Leaf - Leaf config + io.papermc.paper.plugin.PluginInitializerManager.load(optionSet); // Paper Bootstrap.bootStrap(); Bootstrap.validate(); - Util.startTimerHackThread(); -+ org.dreeam.leaf.config.LeafConfig.loadConfig(); // Leaf - Leaf config - Path path1 = Paths.get("server.properties"); - DedicatedServerSettings dedicatedServerSettings = new DedicatedServerSettings(optionSet); // CraftBukkit - CLI argument support - dedicatedServerSettings.forceSave(); diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java index f33fb9b30863dd8ff7207db905fcfb7547b09383..4ba85d704ffebae38f7a76a97a182e3674730c6f 100644 --- a/net/minecraft/server/MinecraftServer.java diff --git a/leaf-server/minecraft-patches/features/0007-Purpur-Server-Minecraft-Changes.patch b/leaf-server/minecraft-patches/features/0007-Purpur-Server-Minecraft-Changes.patch index b9f59e40..e1b6f6c2 100644 --- a/leaf-server/minecraft-patches/features/0007-Purpur-Server-Minecraft-Changes.patch +++ b/leaf-server/minecraft-patches/features/0007-Purpur-Server-Minecraft-Changes.patch @@ -292,7 +292,7 @@ index 4ed9611994c5c8da01fede690197527c5b3a5731..00a82873d226f113278632a53c0faca4 } // Paper end - Buffer joins to world diff --git a/net/minecraft/server/Main.java b/net/minecraft/server/Main.java -index 748816e3f325468f523bdb8dfb94992883ed1989..427788e8747ae8d3a49c0dc094e04b6d7727daa2 100644 +index 43842de34adda95e78025c2b00639b31b774a78b..398aac2a63ae84bb8b9bfb7be6e6d56bf019abda 100644 --- a/net/minecraft/server/Main.java +++ b/net/minecraft/server/Main.java @@ -108,6 +108,12 @@ public class Main { @@ -305,9 +305,9 @@ index 748816e3f325468f523bdb8dfb94992883ed1989..427788e8747ae8d3a49c0dc094e04b6d + org.purpurmc.purpur.PurpurConfig.registerMinecraftDebugCommands = purpurConfiguration.getBoolean("settings.register-minecraft-debug-commands"); // Purpur - register minecraft debug commands + // Purpur end - Add toggle for enchant level clamping - load config files early + + org.dreeam.leaf.config.LeafConfig.loadConfig(); // Leaf - Leaf config io.papermc.paper.plugin.PluginInitializerManager.load(optionSet); // Paper Bootstrap.bootStrap(); - Bootstrap.validate(); diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java index a76b67a846b12a7b3d0c41b6ac4833d4f0372531..5fb7a76faf72f7d91122e5bf01c51853164a73c0 100644 --- a/net/minecraft/server/MinecraftServer.java diff --git a/leaf-server/minecraft-patches/features/0044-Improve-Purpur-AFK-system.patch b/leaf-server/minecraft-patches/features/0044-Improve-Purpur-AFK-system.patch index a1e72616..0c3a6db5 100644 --- a/leaf-server/minecraft-patches/features/0044-Improve-Purpur-AFK-system.patch +++ b/leaf-server/minecraft-patches/features/0044-Improve-Purpur-AFK-system.patch @@ -7,14 +7,14 @@ AFK command & command cooldown AFK title message diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java -index ee7bdfd8f9da8d5989c9cc25f8cbcc94640361c5..fb18f69cb26132fc8c53b185454c6aadb8a5f7e5 100644 +index ee7bdfd8f9da8d5989c9cc25f8cbcc94640361c5..8b9374ee6df71228bb8ea22661622a15cf3bc350 100644 --- a/net/minecraft/commands/Commands.java +++ b/net/minecraft/commands/Commands.java @@ -247,6 +247,7 @@ public class Commands { StopCommand.register(this.dispatcher); TransferCommand.register(this.dispatcher); WhitelistCommand.register(this.dispatcher); -+ org.purpurmc.purpur.command.AFKCommand.register(this.dispatcher); // Leaf - Improve Purpur AFK system ++ if (org.dreeam.leaf.config.modules.gameplay.AfkCommand.enabled) org.purpurmc.purpur.command.AFKCommand.register(this.dispatcher); // Leaf - Improve Purpur AFK system org.purpurmc.purpur.command.CreditsCommand.register(this.dispatcher); // Purpur - Add credits command org.purpurmc.purpur.command.DemoCommand.register(this.dispatcher); // Purpur - Add demo command org.purpurmc.purpur.command.PingCommand.register(this.dispatcher); // Purpur - Add ping command @@ -53,90 +53,110 @@ index f89d28595fa9ca12e414f7b3cc86085ff0769e72..29fd9cea422e1ee09f6983a9b72847fb } else { getBukkitEntity().setPlayerListName(prefix + scoreboardName + suffix, true); diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index f10946b641e0af144ca653850c5d5292c0095412..90ff9e0a0b7ef1307ed4ee839571cf1aa5632c15 100644 +index f10946b641e0af144ca653850c5d5292c0095412..a069760d916da9dd9efa99fd01b41e5dfe88acf3 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2270,6 +2270,8 @@ public class ServerGamePacketListenerImpl +@@ -2272,6 +2272,7 @@ public class ServerGamePacketListenerImpl + + @Override + public void handleChatCommand(ServerboundChatCommandPacket packet) { ++ final boolean isAfkCommandCooldown = this.performAfkCooldown(packet.command()); // Leaf - Improve Purpur AFK system + this.tryHandleChat(packet.command(), () -> { + // CraftBukkit start - SPIGOT-7346: Prevent disconnected players from executing commands + if (this.player.hasDisconnected()) { +@@ -2280,7 +2281,7 @@ public class ServerGamePacketListenerImpl + // CraftBukkit end + this.performUnsignedChatCommand(packet.command()); + this.detectRateSpam("/" + packet.command()); // Spigot +- }, true); // CraftBukkit - sync commands ++ }, true, isAfkCommandCooldown); // CraftBukkit - sync commands // Leaf - Improve Purpur AFK system + } + + private void performUnsignedChatCommand(String command) { +@@ -2313,6 +2314,7 @@ public class ServerGamePacketListenerImpl + public void handleSignedChatCommand(ServerboundChatCommandSignedPacket packet) { + Optional optional = this.unpackAndApplyLastSeen(packet.lastSeenMessages()); + if (!optional.isEmpty()) { ++ final boolean isAfkCommandCooldown = this.performAfkCooldown(packet.command()); // Leaf - Improve Purpur AFK system + this.tryHandleChat(packet.command(), () -> { + // CraftBukkit start - SPIGOT-7346: Prevent disconnected players from executing commands + if (this.player.hasDisconnected()) { +@@ -2321,7 +2323,7 @@ public class ServerGamePacketListenerImpl + // CraftBukkit end + this.performSignedChatCommand(packet, optional.get()); + this.detectRateSpam("/" + packet.command()); // Spigot +- }, true); // CraftBukkit - sync commands ++ }, true, isAfkCommandCooldown); // CraftBukkit - sync commands // Leaf - Improve Purpur AFK system } } -+ public static final Map afkCooldown = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>(); // Leaf - Improve Purpur AFK system -+ - @Override - public void handleChatCommand(ServerboundChatCommandPacket packet) { - this.tryHandleChat(packet.command(), () -> { -@@ -2290,6 +2292,32 @@ public class ServerGamePacketListenerImpl - LOGGER.info("{} issued server command: {}", this.player.getScoreboardName(), prefixedCommand); +@@ -2426,12 +2428,17 @@ public class ServerGamePacketListenerImpl + return dispatcher.parse(command, this.player.createCommandSourceStack()); + } + +- private void tryHandleChat(String message, Runnable handler, boolean sync) { // CraftBukkit ++ // Leaf start - Improve Purpur AFK system ++ private void tryHandleChat(String message, Runnable handler, boolean sync) { ++ tryHandleChat(message, handler, sync, false); ++ } ++ private void tryHandleChat(String message, Runnable handler, boolean sync, boolean afkCommandCooldown) { // CraftBukkit ++ // Leaf end - Improve Purpur AFK system + if (isChatMessageIllegal(message)) { + this.disconnectAsync(Component.translatable("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - add proper async disconnect + } else if (this.player.isRemoved() || this.player.getChatVisibility() == ChatVisiblity.HIDDEN) { // CraftBukkit - dead men tell no tales + this.send(new ClientboundSystemChatPacket(Component.translatable("chat.disabled.options").withStyle(ChatFormatting.RED), false)); +- } else if (player.didPlayerJoinEvent) { // Gale - EMC - do not process chat/commands before player has joined ++ } else if (player.didPlayerJoinEvent && !afkCommandCooldown) { // Gale - EMC - do not process chat/commands before player has joined // Leaf - Improve Purpur AFK system - don't process afk command if in cooldown + this.player.resetLastActionTime(); + // CraftBukkit start + if (sync) { +@@ -2443,6 +2450,46 @@ public class ServerGamePacketListenerImpl } + } -+ // Leaf start - Improve Purpur AFK system -+ if (command.equals("afk")) { -+ this.player.commandAfkStatus = this.player.isAfk(); -+ this.player.isCommandAfk = true; -+ -+ if (org.purpurmc.purpur.PurpurConfig.afkCommandCooldown > 0) { -+ java.util.UUID uuid = this.player.getUUID(); -+ Long cooldown = afkCooldown.get(uuid); -+ long currentTime = System.nanoTime(); -+ -+ if (cooldown != null && (currentTime - cooldown) / 1_000_000_000 <= org.purpurmc.purpur.PurpurConfig.afkCommandCooldown) { -+ String msg = org.purpurmc.purpur.PurpurConfig.afkCooldown; -+ -+ if (msg != null && !msg.isEmpty()) { -+ net.kyori.adventure.text.Component message = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(msg.replace("%time%", String.valueOf(org.purpurmc.purpur.PurpurConfig.afkCommandCooldown - (currentTime - cooldown) / 1_000_000_000))); -+ this.player.sendMessage(message); -+ } -+ -+ return; -+ } else { -+ afkCooldown.put(uuid, currentTime); -+ } -+ } ++ // Leaf start - Improve Purpur AFK system ++ public static final Map afkCooldown = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>(); ++ private boolean performAfkCooldown(String command) { ++ if (!"afk".equals(command)) { ++ return false; + } -+ // Leaf end - Improve Purpur AFK system + - PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(this.getCraftPlayer(), prefixedCommand, new LazyPlayerSet(this.server)); - this.cserver.getPluginManager().callEvent(event); - -@@ -2327,11 +2355,37 @@ public class ServerGamePacketListenerImpl - - private void performSignedChatCommand(ServerboundChatCommandSignedPacket packet, LastSeenMessages lastSeenMessages) { - // CraftBukkit start -- String command = "/" + packet.command(); -+ String command = "/" + packet.command(); // Leaf start - Improve Purpur AFK system - diff on change - if (org.spigotmc.SpigotConfig.logCommands) { // Paper - Add missing SpigotConfig logCommands check - LOGGER.info("{} issued server command: {}", this.player.getScoreboardName(), command); - } // Paper - Add missing SpigotConfig logCommands check - -+ // Leaf start - Improve Purpur AFK system -+ if (command.equals("/afk")) { -+ this.player.commandAfkStatus = this.player.isAfk(); -+ this.player.isCommandAfk = true; ++ this.player.commandAfkStatus = this.player.isAfk(); ++ this.player.isCommandAfk = true; + -+ if (org.purpurmc.purpur.PurpurConfig.afkCommandCooldown > 0) { -+ java.util.UUID uuid = this.player.getUUID(); -+ Long cooldown = afkCooldown.get(uuid); -+ long currentTime = System.nanoTime(); -+ -+ if (cooldown != null && (currentTime - cooldown) / 1_000_000_000 <= org.purpurmc.purpur.PurpurConfig.afkCommandCooldown) { -+ String msg = org.purpurmc.purpur.PurpurConfig.afkCooldown; -+ -+ if (msg != null && !msg.isEmpty()) { -+ net.kyori.adventure.text.Component message = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(msg.replace("%time%", String.valueOf(org.purpurmc.purpur.PurpurConfig.afkCommandCooldown - (currentTime - cooldown) / 1_000_000_000))); -+ this.player.sendMessage(message); -+ } -+ -+ return; -+ } else { -+ afkCooldown.put(uuid, currentTime); -+ } -+ } ++ if (org.purpurmc.purpur.PurpurConfig.afkCommandCooldown <= 0) { ++ return false; + } -+ // Leaf end - Improve Purpur AFK system + - PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(this.getCraftPlayer(), command, new LazyPlayerSet(this.server)); - this.cserver.getPluginManager().callEvent(event); - command = event.getMessage().substring(1); ++ java.util.UUID uuid = this.player.getUUID(); ++ Long cooldown = afkCooldown.get(uuid); ++ long currentTime = System.nanoTime(); ++ ++ boolean ifnull = cooldown != null; ++ System.out.println(ifnull); ++ if (ifnull) { ++ System.out.println((currentTime - cooldown) / 1_000_000_000 <= org.purpurmc.purpur.PurpurConfig.afkCommandCooldown); ++ System.out.println((currentTime - cooldown) / 1_000_000_000); ++ } ++ if (ifnull && (currentTime - cooldown) / 1_000_000_000 <= org.purpurmc.purpur.PurpurConfig.afkCommandCooldown) { ++ String msg = org.purpurmc.purpur.PurpurConfig.afkCooldown; ++ ++ if (msg != null && !msg.isEmpty()) { ++ net.kyori.adventure.text.Component message = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(msg.replace("%time%", String.valueOf(org.purpurmc.purpur.PurpurConfig.afkCommandCooldown - (currentTime - cooldown) / 1_000_000_000))); ++ this.player.sendMessage(message); ++ } ++ ++ return true; ++ } else { ++ afkCooldown.put(uuid, currentTime); ++ return false; ++ } ++ } ++ // Leaf end - Improve Purpur AFK system ++ + private Optional unpackAndApplyLastSeen(LastSeenMessages.Update update) { + synchronized (this.lastSeenMessages) { + Optional optional = this.lastSeenMessages.applyUpdate(update); diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java index 386423589443051b8c461926c570352dd612a051..84f9a8a606ede4ef8361a2683d775121e57b6d9b 100644 --- a/net/minecraft/server/players/PlayerList.java diff --git a/leaf-server/src/main/java/org/dreeam/leaf/config/modules/gameplay/AfkCommand.java b/leaf-server/src/main/java/org/dreeam/leaf/config/modules/gameplay/AfkCommand.java new file mode 100644 index 00000000..63f66e76 --- /dev/null +++ b/leaf-server/src/main/java/org/dreeam/leaf/config/modules/gameplay/AfkCommand.java @@ -0,0 +1,23 @@ +package org.dreeam.leaf.config.modules.gameplay; + +import org.dreeam.leaf.config.ConfigModules; +import org.dreeam.leaf.config.EnumConfigCategory; + +public class AfkCommand extends ConfigModules { + + public String getBasePath() { + return EnumConfigCategory.GAMEPLAY.getBaseKeyName() + ".afk-command"; + } + + public static boolean enabled = false; + + @Override + public void onLoaded() { + enabled = config.getBoolean(getBasePath() + ".enabled", enabled, config.pickStringRegionBased(""" + The AFK command based on Minecraft built-in idle-timeout mechanism + Rest of AFK settings are in the Purpur config""", + """ + 基于原版 idle-timeout 系统的 AFK 指令 + 剩余配置项在 Purpur 配置里""")); + } +}