From cd881265144c29ba6373dd719f3d2f39a4feddac Mon Sep 17 00:00:00 2001 From: Connor Date: Tue, 29 Oct 2024 05:44:57 +1300 Subject: [PATCH] Feature - Add packet spam debug command example (#177) * add spam packet debug command * decrease delay on packet spam * improve spam packets command --------- Co-authored-by: ItsNature --- bukkit-example/build.gradle.kts | 1 + .../apollo/example/ApolloExamplePlugin.java | 7 + .../commands/debug/ApolloDebugCommand.java | 63 +++++++++ .../commands/debug/SpamPacketsCommand.java | 104 +++++++++++++++ .../apollo/example/debug/SpamPacketDebug.java | 125 ++++++++++++++++++ bukkit-example/src/main/resources/plugin.yml | 2 + 6 files changed, 302 insertions(+) create mode 100644 bukkit-example/src/main/java/com/lunarclient/apollo/example/common/commands/debug/ApolloDebugCommand.java create mode 100644 bukkit-example/src/main/java/com/lunarclient/apollo/example/common/commands/debug/SpamPacketsCommand.java create mode 100644 bukkit-example/src/main/java/com/lunarclient/apollo/example/debug/SpamPacketDebug.java diff --git a/bukkit-example/build.gradle.kts b/bukkit-example/build.gradle.kts index 6e9ceb70..3f9240e3 100644 --- a/bukkit-example/build.gradle.kts +++ b/bukkit-example/build.gradle.kts @@ -19,4 +19,5 @@ dependencies { // Used for API Implementation compileOnly(project(":extra:apollo-extra-adventure4")) compileOnly(project(path = ":apollo-api", configuration = "bukkit")) + compileOnly(project(path = ":apollo-common", configuration = "shadow")) } diff --git a/bukkit-example/src/main/java/com/lunarclient/apollo/example/ApolloExamplePlugin.java b/bukkit-example/src/main/java/com/lunarclient/apollo/example/ApolloExamplePlugin.java index f55295fb..4526747e 100644 --- a/bukkit-example/src/main/java/com/lunarclient/apollo/example/ApolloExamplePlugin.java +++ b/bukkit-example/src/main/java/com/lunarclient/apollo/example/ApolloExamplePlugin.java @@ -50,6 +50,7 @@ import com.lunarclient.apollo.example.api.examples.WaypointApiExample; import com.lunarclient.apollo.example.api.listeners.ApolloPlayerApiListener; import com.lunarclient.apollo.example.common.commands.SwitchCommand; +import com.lunarclient.apollo.example.common.commands.debug.ApolloDebugCommand; import com.lunarclient.apollo.example.common.commands.module.BeamCommand; import com.lunarclient.apollo.example.common.commands.module.BorderCommand; import com.lunarclient.apollo.example.common.commands.module.ChatCommand; @@ -101,6 +102,7 @@ import com.lunarclient.apollo.example.common.modules.impl.TransferExample; import com.lunarclient.apollo.example.common.modules.impl.VignetteExample; import com.lunarclient.apollo.example.common.modules.impl.WaypointExample; +import com.lunarclient.apollo.example.debug.SpamPacketDebug; import com.lunarclient.apollo.example.json.examples.BeamJsonExample; import com.lunarclient.apollo.example.json.examples.BorderJsonExample; import com.lunarclient.apollo.example.json.examples.ChatJsonExample; @@ -194,6 +196,8 @@ public class ApolloExamplePlugin extends JavaPlugin { private VignetteExample vignetteExample; private WaypointExample waypointExample; + private SpamPacketDebug spamPacketDebug; + @Override public void onEnable() { plugin = this; @@ -208,6 +212,7 @@ public void onDisable() { } private void registerCommands() { + this.getCommand("apollodebug").setExecutor(new ApolloDebugCommand()); this.getCommand("switch").setExecutor(new SwitchCommand()); this.getCommand("beam").setExecutor(new BeamCommand()); @@ -260,6 +265,8 @@ public void changeImplementationType(ApolloExampleType type) { } private void registerModuleExamples() { + this.spamPacketDebug = new SpamPacketDebug(); + switch (TYPE) { case API: { this.beamExample = new BeamApiExample(); diff --git a/bukkit-example/src/main/java/com/lunarclient/apollo/example/common/commands/debug/ApolloDebugCommand.java b/bukkit-example/src/main/java/com/lunarclient/apollo/example/common/commands/debug/ApolloDebugCommand.java new file mode 100644 index 00000000..77373e72 --- /dev/null +++ b/bukkit-example/src/main/java/com/lunarclient/apollo/example/common/commands/debug/ApolloDebugCommand.java @@ -0,0 +1,63 @@ +/* + * This file is part of Apollo, licensed under the MIT License. + * + * Copyright (c) 2023 Moonsworth + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.lunarclient.apollo.example.common.commands.debug; + +import com.lunarclient.apollo.common.ApolloComponent; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public class ApolloDebugCommand implements CommandExecutor { + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if(!(sender instanceof Player)) { + sender.sendMessage("Player only!"); + return true; + } + + Player player = (Player) sender; + + if (args.length < 1) { + player.sendMessage(ApolloComponent.toLegacy(Component.text() + .append(Component.text("-------------------------------------", NamedTextColor.GRAY, TextDecoration.STRIKETHROUGH)) + .appendNewline() + .append(Component.text("/apollodebug spampackets [start|stop|stopall] ", NamedTextColor.WHITE)) + .append(Component.text("# Spam modsetting update packets to the client.", NamedTextColor.GREEN)) + .appendNewline() + .append(Component.text("-------------------------------------", NamedTextColor.GRAY, TextDecoration.STRIKETHROUGH)) + .build() + )); + } else if(args[0].equalsIgnoreCase("spampackets")) { + return new SpamPacketsCommand().onCommand(sender, command, label, args); + } + + return true; + } +} diff --git a/bukkit-example/src/main/java/com/lunarclient/apollo/example/common/commands/debug/SpamPacketsCommand.java b/bukkit-example/src/main/java/com/lunarclient/apollo/example/common/commands/debug/SpamPacketsCommand.java new file mode 100644 index 00000000..8c2379f9 --- /dev/null +++ b/bukkit-example/src/main/java/com/lunarclient/apollo/example/common/commands/debug/SpamPacketsCommand.java @@ -0,0 +1,104 @@ +/* + * This file is part of Apollo, licensed under the MIT License. + * + * Copyright (c) 2023 Moonsworth + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.lunarclient.apollo.example.common.commands.debug; + +import com.lunarclient.apollo.common.ApolloComponent; +import com.lunarclient.apollo.example.ApolloExamplePlugin; +import com.lunarclient.apollo.example.debug.SpamPacketDebug; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public class SpamPacketsCommand implements CommandExecutor { + + private final SpamPacketDebug spamPacketDebug = ApolloExamplePlugin.getPlugin().getSpamPacketDebug(); + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage("Player only!"); + return true; + } + + Player player = (Player) sender; + + if (args.length < 2) { + this.sendUsage(player); + } else { + switch (args[1].toLowerCase()) { + case "start": { + int amount = args.length > 2 ? Integer.parseInt(args[2]) : Integer.MAX_VALUE; + int delay = args.length > 3 ? Integer.parseInt(args[3]) : 50; + + this.spamPacketDebug.start(player, amount, delay, () -> player.sendMessage("Debug completed!")); + + player.sendMessage("Debug started. (Amount: " + amount + ", Delay: " + delay + "ms)"); + break; + } + + case "stop": { + this.spamPacketDebug.stop(player); + player.sendMessage("Debug stopped."); + break; + } + + case "stopall": { + this.spamPacketDebug.stopAll(); + player.sendMessage("Debug stopped for all debuggers."); + break; + } + + default: { + this.sendUsage(player); + break; + } + } + } + + return true; + } + + private void sendUsage(Player player) { + player.sendMessage(ApolloComponent.toLegacy(Component.text() + .append(Component.text("-------------------------------------", NamedTextColor.GRAY, TextDecoration.STRIKETHROUGH)) + .appendNewline() + .append(Component.text("/apollodebug spampackets start ", NamedTextColor.WHITE)) + .append(Component.text("# Starts spamming modsetting update packets to the client, delay is in milliseconds.", NamedTextColor.GREEN)) + .appendNewline() + .append(Component.text("/apollodebug spampackets stop ", NamedTextColor.WHITE)) + .append(Component.text("# Stop spamming modsetting update packets to the client.", NamedTextColor.GREEN)) + .appendNewline() + .append(Component.text("/apollodebug spampackets stopall ", NamedTextColor.WHITE)) + .append(Component.text("# Stops spamming modsetting update packets to the client, for all debuggers.", NamedTextColor.GREEN)) + .appendNewline() + .append(Component.text("-------------------------------------", NamedTextColor.GRAY, TextDecoration.STRIKETHROUGH)) + .build() + )); + } +} diff --git a/bukkit-example/src/main/java/com/lunarclient/apollo/example/debug/SpamPacketDebug.java b/bukkit-example/src/main/java/com/lunarclient/apollo/example/debug/SpamPacketDebug.java new file mode 100644 index 00000000..5d9de7e2 --- /dev/null +++ b/bukkit-example/src/main/java/com/lunarclient/apollo/example/debug/SpamPacketDebug.java @@ -0,0 +1,125 @@ +/* + * This file is part of Apollo, licensed under the MIT License. + * + * Copyright (c) 2023 Moonsworth + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.lunarclient.apollo.example.debug; + +import com.google.common.collect.Maps; +import com.lunarclient.apollo.Apollo; +import com.lunarclient.apollo.example.ApolloExamplePlugin; +import com.lunarclient.apollo.network.NetworkOptions; +import java.util.Map; +import java.util.UUID; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerQuitEvent; + +public class SpamPacketDebug implements Listener { + + private final Map players = Maps.newConcurrentMap(); + + public SpamPacketDebug() { + Bukkit.getPluginManager().registerEvents(this, ApolloExamplePlugin.getPlugin()); + } + + @EventHandler + private void onPlayerQuit(PlayerQuitEvent event) { + this.stop(event.getPlayer()); + } + + public void start(Player player, int amount, long delay, Runnable callback) { + UUID playerIdentifier = player.getUniqueId(); + SpamPacketTask task = new SpamPacketTask(playerIdentifier, amount, delay, callback); + this.players.put(playerIdentifier, task); + task.start(); + } + + public void stop(Player player) { + UUID playerIdentifier = player.getUniqueId(); + SpamPacketTask task = this.players.remove(playerIdentifier); + if (task != null) { + task.stop(); + } + } + + public void stopAll() { + for (SpamPacketTask task : this.players.values()) { + task.stop(); + } + + this.players.clear(); + } + + public static class SpamPacketTask implements Runnable { + private final UUID player; + private final int amount; + private final long delay; + private final Runnable onComplete; + + private volatile boolean running; + private int sent; + + public SpamPacketTask(UUID player, int amount, long delay, Runnable onComplete) { + this.player = player; + this.amount = amount; + this.delay = delay; + this.onComplete = onComplete; + } + + public void start() { + this.running = true; + + Thread debugThread = new Thread(this); + debugThread.setDaemon(true); + debugThread.start(); + } + + public void stop() { + this.running = false; + } + + @Override + public void run() { + while (this.running) { + if (this.sent > this.amount) { + this.onComplete.run(); + this.running = false; + break; + } + + Apollo.getPlayerManager().getPlayer(this.player) + .ifPresent(apolloPlayer -> NetworkOptions.sendOptions(Apollo.getModuleManager().getModules(), true, apolloPlayer)); + + this.sent++; + + try { + Thread.sleep(this.delay); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + break; + } + } + } + } +} diff --git a/bukkit-example/src/main/resources/plugin.yml b/bukkit-example/src/main/resources/plugin.yml index c0080cc7..bd7a701f 100644 --- a/bukkit-example/src/main/resources/plugin.yml +++ b/bukkit-example/src/main/resources/plugin.yml @@ -58,3 +58,5 @@ commands: description: "Vignette!" waypoint: description: "Waypoints!" + apollodebug: + description: "Apollo Debug!"