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 AFK command & command cooldown AFK title message diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java index 6191930c133758936ffd3cc2588c3f8713145508..11f9ac80dd5e53ae9a43ab5f4e9d3c867ab94b15 100644 --- a/src/main/java/net/minecraft/commands/Commands.java +++ b/src/main/java/net/minecraft/commands/Commands.java @@ -252,6 +252,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 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 df6f21a7cc2be3e006814896c4a80ad53f9b02f5..3eb3cd1089ec46c64f82e99f25d19cee9e0cdfbe 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -2680,6 +2680,10 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple // Purpur Start private boolean isAfk = false; + // Leaf sart - Improve Purpur AFK system + public boolean isCommandAfk = false; + public boolean commandAfkStatus = false; + // Leaf end - Improve Purpur AFK system @Override public void setAfk(boolean afk) { @@ -2717,6 +2721,22 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple String prefix = (split.length > 0 ? split[0] : "").replace(org.purpurmc.purpur.PurpurConfig.afkTabListPrefix, ""); String suffix = (split.length > 1 ? split[1] : "").replace(org.purpurmc.purpur.PurpurConfig.afkTabListSuffix, ""); if (afk) { + // Leaf start - Improve Purpur AFK system + String[] rawTitle = org.purpurmc.purpur.PurpurConfig.afkTitleAway.split(":"); + if (rawTitle.length == 5) { + String title = rawTitle[0]; + String subTitle = rawTitle[1]; + long fadeInTicks = Long.parseLong(rawTitle[2]); + long stayTicks = Long.parseLong(rawTitle[3]); + long fadeOutTicks = Long.parseLong(rawTitle[4]); + net.kyori.adventure.title.Title tile = net.kyori.adventure.title.Title.title(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(title), net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(subTitle), net.kyori.adventure.title.Title.Times.times(net.kyori.adventure.util.Ticks.duration(fadeInTicks), net.kyori.adventure.util.Ticks.duration(stayTicks), net.kyori.adventure.util.Ticks.duration(fadeOutTicks))); + getBukkitEntity().showTitle(tile); + } else { + LOGGER.error("You put wrong format of afk-title-away in PurpurConfig, it should look like AFK:You are now AFK...:10:70:20"); + LOGGER.error("'Title:Sub Title:Title Fade In Ticks:Title Stay Ticks:Title Fade Out Ticks', split with :"); + } + // Leaf end - Improve Purpur AFK system + getBukkitEntity().setPlayerListName(org.purpurmc.purpur.PurpurConfig.afkTabListPrefix + prefix + scoreboardName + suffix + org.purpurmc.purpur.PurpurConfig.afkTabListSuffix, true); } else { 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 68cf6f0f0d2d1eb23de070ea8471111a41a9f9bf..615622f3ce63d2150c57cfd9f664bfa8fa5d6124 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -2294,6 +2294,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } } + public static final Map afkCooldown = new java.util.concurrent.ConcurrentHashMap<>(); // Leaf - Improve Purpur AFK system + @Override public void handleChatCommand(ServerboundChatCommandPacket packet) { this.tryHandleChat(packet.command(), () -> { @@ -2314,6 +2316,32 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl ServerGamePacketListenerImpl.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + command1); } + // 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) { + 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 end - Improve Purpur AFK system + PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(this.getCraftPlayer(), command1, new LazyPlayerSet(this.server)); this.cserver.getPluginManager().callEvent(event); @@ -2351,11 +2379,37 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl 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 ServerGamePacketListenerImpl.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + 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; + + if (org.purpurmc.purpur.PurpurConfig.afkCommandCooldown > 0) { + 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 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); diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java index 348c3c6a5d99fece14a9eb987a06934c8e8bac59..8efd2183309c285e0a7760922bf1b4766248d5f0 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -706,6 +706,7 @@ public abstract class PlayerList { org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerLeave(entityplayer); // Leaves - protocol // Paper end - Fix kick event leave message not being sent org.purpurmc.purpur.task.BossBarTask.removeFromAll(entityplayer.getBukkitEntity()); // Purpur + net.minecraft.server.network.ServerGamePacketListenerImpl.afkCooldown.remove(entityplayer.getBukkitEntity().getUniqueId()); // Leaf - Improve Purpur AFK system ServerLevel worldserver = entityplayer.serverLevel(); entityplayer.awardStat(Stats.LEAVE_GAME); diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java index 05d77ccd9bf8ce0534fbac7d4354536e3187229f..aa1f5f69346a75af8e9b8dd185f211682a74db2c 100644 --- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java +++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java @@ -179,9 +179,14 @@ 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:You are now AFK...:10:70:20"; // Leaf - Improve Purpur AFK system public static boolean afkBroadcastUseDisplayName = false; public static String afkTabListPrefix = "[AFK] "; public static String afkTabListSuffix = ""; + // Leaf start - Improve Purpur AFK system + public static int afkCommandCooldown = 0; + public static String afkCooldown = "You need to wait %time%s to use /afk."; + // Leaf end - Improve Purpur AFK system public static String creditsCommandOutput = "%s has been shown the end credits"; public static String demoCommandOutput = "%s has been shown the demo screen"; public static String pingCommandOutput = "%s's ping is %sms"; @@ -198,9 +203,14 @@ public class PurpurConfig { cannotRideMob = getString("settings.messages.cannot-ride-mob", cannotRideMob); afkBroadcastAway = getString("settings.messages.afk-broadcast-away", afkBroadcastAway); afkBroadcastBack = getString("settings.messages.afk-broadcast-back", afkBroadcastBack); + afkTitleAway = getString("settings.messages.afk-title-away", afkTitleAway); // Leaf - Improve Purpur AFK system 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))); afkTabListSuffix = MiniMessage.miniMessage().serialize(MiniMessage.miniMessage().deserialize(getString("settings.messages.afk-tab-list-suffix", afkTabListSuffix))); + // Leaf start - Improve Purpur AFK system + afkCommandCooldown = getInt("settings.messages.afk-command-cooldown", afkCommandCooldown); + afkCooldown = MiniMessage.miniMessage().serialize(MiniMessage.miniMessage().deserialize(getString("settings.messages.afk-command-cooldown-msg", afkCooldown))); + // Leaf end - Improve Purpur AFK system creditsCommandOutput = getString("settings.messages.credits-command-output", creditsCommandOutput); demoCommandOutput = getString("settings.messages.demo-command-output", demoCommandOutput); pingCommandOutput = getString("settings.messages.ping-command-output", pingCommandOutput); 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..1b8eee9cce3ae069be7c97bd0840338e9287ce4e --- /dev/null +++ b/src/main/java/org/purpurmc/purpur/command/AFKCommand.java @@ -0,0 +1,37 @@ +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(); + } +}