From d9bede9fb25216eb0ac89f7224e603841e0319a0 Mon Sep 17 00:00:00 2001 From: RacoonDog <32882447+racoondog@users.noreply.github.com> Date: Tue, 16 Sep 2025 23:47:18 -0400 Subject: [PATCH] add registry support for commands --- .../meteorclient/commands/Command.java | 2 +- .../meteorclient/commands/Commands.java | 38 ++++++++++++++++++- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/commands/Command.java b/src/main/java/meteordevelopment/meteorclient/commands/Command.java index 10c63e133a..18fea76782 100644 --- a/src/main/java/meteordevelopment/meteorclient/commands/Command.java +++ b/src/main/java/meteordevelopment/meteorclient/commands/Command.java @@ -23,7 +23,7 @@ import java.util.List; public abstract class Command { - protected static final CommandRegistryAccess REGISTRY_ACCESS = CommandManager.createRegistryAccess(BuiltinRegistries.createWrapperLookup()); + protected static CommandRegistryAccess REGISTRY_ACCESS = CommandManager.createRegistryAccess(BuiltinRegistries.createWrapperLookup()); protected static final int SINGLE_SUCCESS = com.mojang.brigadier.Command.SINGLE_SUCCESS; protected static final MinecraftClient mc = MeteorClient.mc; diff --git a/src/main/java/meteordevelopment/meteorclient/commands/Commands.java b/src/main/java/meteordevelopment/meteorclient/commands/Commands.java index de498a625c..8764f20636 100644 --- a/src/main/java/meteordevelopment/meteorclient/commands/Commands.java +++ b/src/main/java/meteordevelopment/meteorclient/commands/Commands.java @@ -7,9 +7,14 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import meteordevelopment.meteorclient.MeteorClient; import meteordevelopment.meteorclient.commands.commands.*; +import meteordevelopment.meteorclient.events.game.GameJoinedEvent; import meteordevelopment.meteorclient.pathing.PathManagers; import meteordevelopment.meteorclient.utils.PostInit; +import meteordevelopment.orbit.EventHandler; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.command.CommandRegistryAccess; import net.minecraft.command.CommandSource; import java.util.ArrayList; @@ -19,8 +24,8 @@ import static meteordevelopment.meteorclient.MeteorClient.mc; public class Commands { - public static final CommandDispatcher DISPATCHER = new CommandDispatcher<>(); public static final List COMMANDS = new ArrayList<>(); + public static CommandDispatcher DISPATCHER = new CommandDispatcher<>(); @PostInit(dependencies = PathManagers.class) public static void init() { @@ -64,11 +69,12 @@ public static void init() { add(new LocateCommand()); COMMANDS.sort(Comparator.comparing(Command::getName)); + + MeteorClient.EVENT_BUS.subscribe(Commands.class); } public static void add(Command command) { COMMANDS.removeIf(existing -> existing.getName().equals(command.getName())); - command.registerTo(DISPATCHER); COMMANDS.add(command); } @@ -85,4 +91,32 @@ public static Command get(String name) { return null; } + + /** + * Argument types that rely on Minecraft registries access those registries through a {@link CommandRegistryAccess} + * object. Since dynamic registries are specific to each server, we need to make a new CommandRegistryAccess object + * every time we join a server. + *

+ * The command tree and by extension the {@link CommandDispatcher} also have to be rebuilt because: + *

    + *
  1. Argument types that require registries use a registry wrapper object that is created and stored in the + * argument type objects when the command tree is built. + *
  2. Registry entries and keys are compared using referential equality. Even if the data encoded is the same, + * registry wrapper objects' dynamic data becomes stale after joining another server. + *
  3. The CommandDispatcher's node merging only adds missing children, it cannot replace stale argument type + * objects. + *
+ * + * @author Crosby + */ + @EventHandler + private static void onJoin(GameJoinedEvent event) { + ClientPlayNetworkHandler networkHandler = mc.getNetworkHandler(); + Command.REGISTRY_ACCESS = CommandRegistryAccess.of(networkHandler.getRegistryManager(), networkHandler.getEnabledFeatures()); + + DISPATCHER = new CommandDispatcher<>(); + for (Command command : COMMANDS) { + command.registerTo(DISPATCHER); + } + } }