diff --git a/src/main/java/land/chipmunk/chipmunkmod/command/CommandManager.java b/src/main/java/land/chipmunk/chipmunkmod/command/CommandManager.java new file mode 100644 index 0000000..448a7e4 --- /dev/null +++ b/src/main/java/land/chipmunk/chipmunkmod/command/CommandManager.java @@ -0,0 +1,70 @@ +package land.chipmunk.chipmunkmod.command; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.command.CommandException; +import net.minecraft.text.ClickEvent; +import net.minecraft.text.Text; +import net.minecraft.text.Texts; +import net.minecraft.text.MutableText; +import net.minecraft.util.Formatting; +import net.minecraft.client.MinecraftClient; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import land.chipmunk.chipmunkmod.commands.*; + +public class CommandManager { + public static CommandDispatcher dispatcher = new CommandDispatcher(); + public static String prefix = "."; + + public static void executeCommand (String command) { + final MinecraftClient client = MinecraftClient.getInstance(); + + final FabricClientCommandSource commandSource = (FabricClientCommandSource) client.getNetworkHandler().getCommandSource(); + + try { + dispatcher.execute(command, commandSource); + } catch (CommandSyntaxException e) { + commandSource.sendError(Texts.toText(e.getRawMessage())); + commandSource.sendError(getContext(e)); + } catch (CommandException e) { + commandSource.sendError(e.getTextMessage()); + } catch (RuntimeException e) { + commandSource.sendError(Text.of(e.getMessage())); + } + } + + public static Text getContext (CommandSyntaxException exception) { + final int _cursor = exception.getCursor(); + final String input = exception.getInput(); + + if (input == null || _cursor < 0) { + return null; + } + final MutableText text = Text.literal("") + .formatted(Formatting.GRAY); + text.setStyle(text.getStyle().withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, prefix + input))); + + final int cursor = Math.min(input.length(), _cursor); + + if (cursor > CommandSyntaxException.CONTEXT_AMOUNT) { + text.append(Text.literal("...")); + } + + text + .append(Text.literal(input.substring(Math.max(0, cursor - CommandSyntaxException.CONTEXT_AMOUNT), cursor))) + .append(Text.literal(input.substring(cursor)).formatted(Formatting.RED, Formatting.UNDERLINE)) + .append(Text.translatable("command.context.here").formatted(Formatting.RED, Formatting.ITALIC)); + + return text; + } + + public static LiteralArgumentBuilder literal (String name) { return LiteralArgumentBuilder.literal(name); } + public static RequiredArgumentBuilder argument (String name, ArgumentType type) { return RequiredArgumentBuilder.argument(name, type); } + + static { + TestCommand.register(dispatcher); + } +} \ No newline at end of file diff --git a/src/main/java/land/chipmunk/chipmunkmod/commands/TestCommand.java b/src/main/java/land/chipmunk/chipmunkmod/commands/TestCommand.java new file mode 100644 index 0000000..716b558 --- /dev/null +++ b/src/main/java/land/chipmunk/chipmunkmod/commands/TestCommand.java @@ -0,0 +1,24 @@ +package land.chipmunk.chipmunkmod.commands; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.context.CommandContext; +import static land.chipmunk.chipmunkmod.command.CommandManager.literal; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.text.Text; + +public class TestCommand { + public static void register (CommandDispatcher dispatcher) { + dispatcher.register( + literal("test") + .executes(c -> helloWorld(c)) + ); + } + + public static int helloWorld (CommandContext context) { + final FabricClientCommandSource source = context.getSource(); + source.sendFeedback(Text.literal("Hello, world!")); + + return Command.SINGLE_SUCCESS; + } +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatScreenMixin.java b/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatScreenMixin.java new file mode 100644 index 0000000..c197811 --- /dev/null +++ b/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatScreenMixin.java @@ -0,0 +1,22 @@ +package land.chipmunk.chipmunkmod.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import net.minecraft.client.MinecraftClient; +import land.chipmunk.chipmunkmod.command.CommandManager; + +@Mixin(net.minecraft.client.gui.screen.ChatScreen.class) +public class ChatScreenMixin { + @Inject(at = @At("HEAD"), method = "sendMessage", cancellable = true) + public void sendMessage(String chatText, boolean addToHistory, CallbackInfoReturnable cir) { + if (chatText.startsWith(CommandManager.prefix)) { + CommandManager.executeCommand(chatText.substring(CommandManager.prefix.length())); + + if (addToHistory) MinecraftClient.getInstance().inGameHud.getChatHud().addToMessageHistory(chatText); + + cir.setReturnValue(true); + } + } +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/mixin/ExampleMixin.java b/src/main/java/land/chipmunk/chipmunkmod/mixin/ExampleMixin.java deleted file mode 100644 index 8b49e76..0000000 --- a/src/main/java/land/chipmunk/chipmunkmod/mixin/ExampleMixin.java +++ /dev/null @@ -1,16 +0,0 @@ -package land.chipmunk.chipmunkmod.mixin; - -import land.chipmunk.chipmunkmod.ChipmunkMod; -import net.minecraft.client.gui.screen.TitleScreen; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(TitleScreen.class) -public class ExampleMixin { - @Inject(at = @At("HEAD"), method = "init()V") - private void init(CallbackInfo info) { - ChipmunkMod.LOGGER.info("This line is printed by an example mod mixin!"); - } -} diff --git a/src/main/resources/modid.mixins.json b/src/main/resources/modid.mixins.json index c01fc62..d7e0255 100644 --- a/src/main/resources/modid.mixins.json +++ b/src/main/resources/modid.mixins.json @@ -6,7 +6,7 @@ "mixins": [ ], "client": [ - "ExampleMixin" + "ChatScreenMixin" ], "injectors": { "defaultRequire": 1