From 14f174ae0a972112d8dbf857febbdf2c53dc4612 Mon Sep 17 00:00:00 2001 From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> Date: Sun, 3 Mar 2024 05:29:29 -0500 Subject: [PATCH] Improve Purpur AFK system --- .../0072-Improve-Purpur-AFK-system.patch | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 patches/server/0072-Improve-Purpur-AFK-system.patch diff --git a/patches/server/0072-Improve-Purpur-AFK-system.patch b/patches/server/0072-Improve-Purpur-AFK-system.patch new file mode 100644 index 000000000..3ef9ee067 --- /dev/null +++ b/patches/server/0072-Improve-Purpur-AFK-system.patch @@ -0,0 +1,137 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> +Date: Sat, 2 Mar 2024 18:22:15 -0500 +Subject: [PATCH] Improve Purpur AFK system + +Add afk command +Add custom afk tab name + +diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java +index edbdcdac30a9c80849045c5225bb1d6bdd091e2d..f1ddbbf41a7232ad3c432dfef9a8420935572337 100644 +--- a/src/main/java/net/minecraft/commands/Commands.java ++++ b/src/main/java/net/minecraft/commands/Commands.java +@@ -248,6 +248,7 @@ public class Commands { + SetPlayerIdleTimeoutCommand.register(this.dispatcher); + StopCommand.register(this.dispatcher); + WhitelistCommand.register(this.dispatcher); ++ org.purpurmc.purpur.command.AFKCommand.register(this.dispatcher); // Purpur + org.purpurmc.purpur.command.CreditsCommand.register(this.dispatcher); // Purpur + org.purpurmc.purpur.command.DemoCommand.register(this.dispatcher); // Purpur + org.purpurmc.purpur.command.PingCommand.register(this.dispatcher); // Purpur +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 9950580f3d0387b142576bfdb6a8f74365c12878..4270b24734affdeff0cd49ab494b7fadcb8f248f 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -2277,6 +2277,8 @@ public class ServerPlayer extends Player { + + // Purpur Start + private boolean isAfk = false; ++ public boolean isCommandAfk = false; ++ public boolean commandAfkStatus = false; + + @Override + public void setAfk(boolean afk) { +@@ -2308,15 +2310,19 @@ public class ServerPlayer extends Player { + } + + if (this.level().purpurConfig.idleTimeoutUpdateTabList) { +- String scoreboardName = getScoreboardName(); ++ String scoreboardName = org.purpurmc.purpur.PurpurConfig.afkTabListCustomName.replace("%player_name%", getScoreboardName()); + String playerListName = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().serialize(getBukkitEntity().playerListName()); + String[] split = playerListName.split(scoreboardName); +- String prefix = (split.length > 0 ? split[0] : "").replace(org.purpurmc.purpur.PurpurConfig.afkTabListPrefix, ""); ++ String prefix = (split.length > 0 ? split[0] : "").replace(org.purpurmc.purpur.PurpurConfig.afkTabListPrefix, "").replace(playerListName, ""); + String suffix = (split.length > 1 ? split[1] : "").replace(org.purpurmc.purpur.PurpurConfig.afkTabListSuffix, ""); + if (afk) { ++ net.kyori.adventure.title.Title tile = net.kyori.adventure.title.Title.title(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(org.purpurmc.purpur.PurpurConfig.afkTitleAway), net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(org.purpurmc.purpur.PurpurConfig.afkSubTitleAway), net.kyori.adventure.title.Title.Times.times(net.kyori.adventure.util.Ticks.duration(10), net.kyori.adventure.util.Ticks.duration(70), net.kyori.adventure.util.Ticks.duration(20))); ++ getBukkitEntity().showTitle(tile); ++ + getBukkitEntity().setPlayerListName(org.purpurmc.purpur.PurpurConfig.afkTabListPrefix + prefix + scoreboardName + suffix + org.purpurmc.purpur.PurpurConfig.afkTabListSuffix, true); + } else { +- getBukkitEntity().setPlayerListName(prefix + scoreboardName + suffix); ++ scoreboardName = getScoreboardName(); ++ getBukkitEntity().setPlayerListName(prefix + scoreboardName + suffix, true); + } + } + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 42885c7f374f619fe63d9fe22a4b7f88d68008c3..c7fbf58f0aa653bf4b89fa0787f5ad4ca83e51d5 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2266,6 +2266,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + + @Override + public void handleChatCommand(ServerboundChatCommandPacket packet) { ++ // Purpur start ++ if (packet.command().equals("afk")) { ++ player.commandAfkStatus = player.isAfk(); ++ player.isCommandAfk = true; ++ } ++ // Purpur end + if (ServerGamePacketListenerImpl.isChatMessageIllegal(packet.command())) { + this.disconnect(Component.translatable("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper + } else { +diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java +index e45c11bf2c42e6d57f803349d8ca6936ac98c995..61dc8b798f1246c19c7e45e9ae9c54366286cfce 100644 +--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java ++++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java +@@ -176,8 +176,11 @@ public class PurpurConfig { + public static String cannotRideMob = "You cannot mount that mob"; + public static String afkBroadcastAway = "%s is now AFK"; + public static String afkBroadcastBack = "%s is no longer AFK"; ++ public static String afkTitleAway = "AFK"; ++ public static String afkSubTitleAway = "You are now AFK..."; + public static boolean afkBroadcastUseDisplayName = false; + public static String afkTabListPrefix = "[AFK] "; ++ public static String afkTabListCustomName = "%player_name% [AFK]"; + public static String afkTabListSuffix = ""; + public static String creditsCommandOutput = "%s has been shown the end credits"; + public static String demoCommandOutput = "%s has been shown the demo screen"; +@@ -197,6 +200,7 @@ public class PurpurConfig { + afkBroadcastBack = getString("settings.messages.afk-broadcast-back", afkBroadcastBack); + afkBroadcastUseDisplayName = getBoolean("settings.messages.afk-broadcast-use-display-name", afkBroadcastUseDisplayName); + afkTabListPrefix = MiniMessage.miniMessage().serialize(MiniMessage.miniMessage().deserialize(getString("settings.messages.afk-tab-list-prefix", afkTabListPrefix))); ++ afkTabListCustomName = MiniMessage.miniMessage().serialize(MiniMessage.miniMessage().deserialize(getString("settings.messages.afk-tab-list-custom-name", afkTabListCustomName))); + afkTabListSuffix = MiniMessage.miniMessage().serialize(MiniMessage.miniMessage().deserialize(getString("settings.messages.afk-tab-list-suffix", afkTabListSuffix))); + creditsCommandOutput = getString("settings.messages.credits-command-output", creditsCommandOutput); + demoCommandOutput = getString("settings.messages.demo-command-output", demoCommandOutput); +diff --git a/src/main/java/org/purpurmc/purpur/command/AFKCommand.java b/src/main/java/org/purpurmc/purpur/command/AFKCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8dca966c25f8e3f5622ef8f5862fdb43eae3813f +--- /dev/null ++++ b/src/main/java/org/purpurmc/purpur/command/AFKCommand.java +@@ -0,0 +1,34 @@ ++package org.purpurmc.purpur.command; ++ ++import com.mojang.brigadier.CommandDispatcher; ++import net.minecraft.commands.CommandSourceStack; ++import net.minecraft.commands.Commands; ++import net.minecraft.commands.arguments.EntityArgument; ++import net.minecraft.server.level.ServerPlayer; ++ ++import java.util.Collection; ++import java.util.Collections; ++ ++public class AFKCommand { ++ public static void register(CommandDispatcher dispatcher) { ++ dispatcher.register(Commands.literal("afk") ++ .requires((listener) -> listener.hasPermission(2, "bukkit.command.afk")) ++ .executes((context) -> execute(context.getSource(), Collections.singleton(context.getSource().getPlayerOrException()))) ++ .then(Commands.argument("targets", EntityArgument.players()) ++ .requires(listener -> listener.hasPermission(2, "bukkit.command.afk.other")) ++ .executes((context) -> execute(context.getSource(), EntityArgument.getPlayers(context, "targets"))) ++ ) ++ ); ++ } ++ ++ private static int execute(CommandSourceStack sender, Collection targets) { ++ for (ServerPlayer player : targets) { ++ boolean afk = player.isCommandAfk ? !player.commandAfkStatus : !player.isAfk(); ++ if (afk) { ++ player.setAfk(true); ++ } ++ player.isCommandAfk = false; ++ } ++ return targets.size(); ++ } ++}