From c5ead7d843133f2aff04241436ef4e620974ce97 Mon Sep 17 00:00:00 2001
From: amyavi <144570677+amyavi@users.noreply.github.com>
Date: Sat, 25 Jan 2025 20:37:28 -0300
Subject: [PATCH] refactor: rewrite KaboomCheck

---
 .../chipmunk/chipmunkmod/ChipmunkMod.java     |  2 -
 .../chipmunkmod/listeners/Listener.java       |  5 +-
 .../mixin/ClientPlayNetworkHandlerMixin.java  |  9 ++
 .../chipmunkmod/modules/KaboomCheck.java      | 85 +++----------------
 4 files changed, 24 insertions(+), 77 deletions(-)

diff --git a/src/main/java/land/chipmunk/chipmunkmod/ChipmunkMod.java b/src/main/java/land/chipmunk/chipmunkmod/ChipmunkMod.java
index 024c058..c8b918d 100644
--- a/src/main/java/land/chipmunk/chipmunkmod/ChipmunkMod.java
+++ b/src/main/java/land/chipmunk/chipmunkmod/ChipmunkMod.java
@@ -2,7 +2,6 @@ package land.chipmunk.chipmunkmod;
 
 import land.chipmunk.chipmunkmod.config.ChipmunkModMigrations;
 import land.chipmunk.chipmunkmod.config.Configuration;
-import land.chipmunk.chipmunkmod.modules.KaboomCheck;
 import land.chipmunk.chipmunkmod.modules.SelfCare;
 import land.chipmunk.chipmunkmod.util.configurate.ConfigurateUtilities;
 import net.fabricmc.api.ModInitializer;
@@ -40,7 +39,6 @@ public class ChipmunkMod implements ModInitializer {
             throw new RuntimeException("Could not load the config", exception);
         }
 
-        KaboomCheck.INSTANCE.init();
         SelfCare.INSTANCE.init();
 
         LOGGER.info("Loaded ChipmunkMod (chayapak's fork)");
diff --git a/src/main/java/land/chipmunk/chipmunkmod/listeners/Listener.java b/src/main/java/land/chipmunk/chipmunkmod/listeners/Listener.java
index 959fb94..7f5e235 100644
--- a/src/main/java/land/chipmunk/chipmunkmod/listeners/Listener.java
+++ b/src/main/java/land/chipmunk/chipmunkmod/listeners/Listener.java
@@ -4,13 +4,10 @@ import net.minecraft.network.packet.Packet;
 import net.minecraft.text.Text;
 
 public interface Listener {
-    default void chatMessageReceived (Text message) {}
-
     default void packetReceived (Packet<?> packet) {}
-
+    default void chatMessageReceived (Text message) {}
     default void packetSent (Packet<?> packet) {}
 
     default void coreReady () {}
-
     default void coreMoved () {}
 }
diff --git a/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerMixin.java
index c22d392..461957e 100644
--- a/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerMixin.java
+++ b/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerMixin.java
@@ -1,5 +1,6 @@
 package land.chipmunk.chipmunkmod.mixin;
 
+import com.mojang.brigadier.CommandDispatcher;
 import land.chipmunk.chipmunkmod.ChipmunkMod;
 import land.chipmunk.chipmunkmod.command.CommandManager;
 import land.chipmunk.chipmunkmod.listeners.Listener;
@@ -8,12 +9,14 @@ import land.chipmunk.chipmunkmod.modules.*;
 import land.chipmunk.chipmunkmod.modules.custom_chat.CustomChat;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.command.CommandRegistryAccess;
+import net.minecraft.command.CommandSource;
 import net.minecraft.network.encryption.NetworkEncryptionUtils;
 import net.minecraft.network.message.LastSeenMessagesCollector;
 import net.minecraft.network.message.MessageBody;
 import net.minecraft.network.message.MessageChain;
 import net.minecraft.network.message.MessageSignatureData;
 import net.minecraft.network.packet.c2s.play.ChatMessageC2SPacket;
+import net.minecraft.network.packet.s2c.play.CommandTreeS2CPacket;
 import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
 import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket;
 import net.minecraft.registry.DynamicRegistryManager;
@@ -38,6 +41,7 @@ public class ClientPlayNetworkHandlerMixin {
   @Shadow private DynamicRegistryManager.Immutable combinedDynamicRegistries;
   @Shadow private LastSeenMessagesCollector lastSeenMessagesCollector;
   @Shadow private MessageChain.Packer messagePacker;
+  @Shadow private CommandDispatcher<CommandSource> commandDispatcher;
 
   @Inject(method = "onGameJoin", at = @At("TAIL"))
   private void onGameJoin (GameJoinS2CPacket packet, CallbackInfo ci) {
@@ -54,6 +58,11 @@ public class ClientPlayNetworkHandlerMixin {
     CustomChat.INSTANCE.init();
   }
 
+  @Inject(method = "onCommandTree", at = @At("TAIL"))
+  private void onCommandTree(final CommandTreeS2CPacket packet, final CallbackInfo ci) {
+    KaboomCheck.INSTANCE.onCommandTree(this.commandDispatcher);
+  }
+
   @Inject(method = "onGameMessage", at = @At("HEAD"), cancellable = true)
   private void onGameMessage (GameMessageS2CPacket packet, CallbackInfo ci) {
     final Text message = packet.content();
diff --git a/src/main/java/land/chipmunk/chipmunkmod/modules/KaboomCheck.java b/src/main/java/land/chipmunk/chipmunkmod/modules/KaboomCheck.java
index 34f6c6e..84747e7 100644
--- a/src/main/java/land/chipmunk/chipmunkmod/modules/KaboomCheck.java
+++ b/src/main/java/land/chipmunk/chipmunkmod/modules/KaboomCheck.java
@@ -1,83 +1,26 @@
 package land.chipmunk.chipmunkmod.modules;
 
-import com.mojang.brigadier.suggestion.Suggestion;
-import com.mojang.brigadier.suggestion.Suggestions;
-import land.chipmunk.chipmunkmod.listeners.Listener;
-import land.chipmunk.chipmunkmod.listeners.ListenerManager;
+import com.mojang.brigadier.CommandDispatcher;
 import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.network.ClientPlayNetworkHandler;
-import net.minecraft.network.packet.s2c.play.CommandSuggestionsS2CPacket;
+import net.minecraft.command.CommandSource;
 
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.concurrent.CompletableFuture;
+public class KaboomCheck {
+    private static final String CHECKED_COMMAND_OP = "extras:prefix"; // Added circa 2018
+    private static final String CHECKED_COMMAND = "minecraft:op"; // It'd be a bit weird for non-Kaboom servers to allow /op without OP...
+    public static final KaboomCheck INSTANCE = new KaboomCheck();
 
-public class KaboomCheck implements Listener {
+    private final MinecraftClient client = MinecraftClient.getInstance();
     public boolean isKaboom = false;
 
-    private Timer timer = null;
-
-    private final MinecraftClient client;
-
-    public static final KaboomCheck INSTANCE = new KaboomCheck(MinecraftClient.getInstance());
-
-    public KaboomCheck (MinecraftClient client) {
-        this.client = client;
-
-        ListenerManager.addListener(this);
+    public void onJoin() {
+        this.isKaboom = false;
     }
 
-    public void init () {}
+    public void onCommandTree(final CommandDispatcher<CommandSource> dispatcher) {
+        assert client.player != null; // We can only receive this packet while in a server
+        final String checkedCommand = client.player.getPermissionLevel() == 4
+                ? CHECKED_COMMAND_OP : CHECKED_COMMAND;
 
-    public void onJoin () {
-        final TimerTask task = new TimerTask() {
-            public void run () {
-                tick();
-            }
-        };
-
-        if (timer != null) cleanup();
-
-        timer = new Timer();
-
-        timer.schedule(task, 50, 50);
-
-        check();
+        this.isKaboom = dispatcher.getRoot().getChild(checkedCommand) != null;
     }
-
-    private void tick () {
-        final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
-
-        if (networkHandler == null) cleanup();
-    }
-
-    private void check () {
-        final CompletableFuture<CommandSuggestionsS2CPacket> future = TabComplete.INSTANCE.complete("/ver ");
-
-        future.thenApply((packet) -> {
-            final Suggestions suggestions = packet.getSuggestions();
-
-            for (int i = 0; i < suggestions.getList().size(); i++) {
-                final Suggestion suggestion = suggestions.getList().get(i);
-
-                if (suggestion.getText().equals("Extras")) {
-                    isKaboom = true;
-                    break;
-                }
-            }
-
-            return true;
-        });
-    }
-
-    private void cleanup () {
-        if (timer == null) return;
-
-        isKaboom = false;
-
-        timer.purge();
-        timer.cancel();
-    }
-
-
 }
-- 
2.47.2