diff --git a/src/main/java/net/saltymc/eaa/commands/Command.java b/src/main/java/net/saltymc/eaa/commands/Command.java new file mode 100644 index 0000000..77b1837 --- /dev/null +++ b/src/main/java/net/saltymc/eaa/commands/Command.java @@ -0,0 +1,9 @@ +package net.saltymc.eaa.commands; + +import net.fabricmc.fabric.api.client.command.v1.FabricClientCommandSource; + +public interface Command { + + int run(FabricClientCommandSource cs, String[] args); + +} diff --git a/src/main/java/net/saltymc/eaa/commands/CommandHandler.java b/src/main/java/net/saltymc/eaa/commands/CommandHandler.java new file mode 100644 index 0000000..a9ef4e3 --- /dev/null +++ b/src/main/java/net/saltymc/eaa/commands/CommandHandler.java @@ -0,0 +1,118 @@ +package net.saltymc.eaa.commands; + +import com.mojang.brigadier.exceptions.BuiltInExceptionProvider; +import com.mojang.brigadier.exceptions.CommandExceptionType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.fabricmc.fabric.api.client.command.v1.FabricClientCommandSource; +import net.minecraft.client.MinecraftClient; +import net.minecraft.command.CommandException; +import net.minecraft.network.MessageType; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import net.minecraft.text.Texts; +import net.minecraft.text.TranslatableText; +import net.minecraft.util.Formatting; +import net.minecraft.util.Util; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.HashMap; + +import static net.fabricmc.fabric.api.client.command.v1.ClientCommandManager.DISPATCHER; + +public class CommandHandler { + + private static final char PREFIX = '/'; + private static final Logger LOGGER = LogManager.getLogger(); + private static HashMap commands; + //above line stolen from net.fabricmc.fabric.impl.command.client.ClientCommandInternals; + + static { + if(CommandHandler.commands == null){ + CommandHandler.commands = new HashMap<>(); + } + CommandHandler.commands.put("p", new EaaCommand()); + //TODO implement + } + + /** + * Executes a client-sided command from a message. + * + * @param message the command message + * @return true if the message should not be sent to the server, false otherwise + */ + public static boolean executeCommand(String message) { + if (message.isEmpty()) { + return false; // Nothing to process + } + + if (message.charAt(0) != PREFIX) { + return false; // Incorrect prefix, won't execute anything. + } + + FabricClientCommandSource commandSource = (FabricClientCommandSource) MinecraftClient.getInstance().getNetworkHandler().getCommandSource(); + + //commandSource.getClient().getProfiler().push(message); + + try { + //DISPATCHER.execute(message.substring(1), commandSource); + String command = message.replaceFirst(""+PREFIX,"").split(" ")[0]; + String[] args = message.replaceFirst(""+PREFIX,"").split(" "); //TODO remove first item from array + + System.out.println("command: $"+command+"$"); + + if(CommandHandler.commands.get(command) != null) { + CommandHandler.commands.get(command).run(commandSource, args); + }else{ + return false; + } + + return true; + /*} catch (CommandSyntaxException e) { + boolean ignored = isIgnoredException(e.getType()); + LOGGER.log(ignored ? Level.DEBUG : Level.WARN, "Syntax exception for client-sided command '{}'", message, e); + if (ignored) { + return false; + } + commandSource.sendError(getErrorMessage(e)); + return true;*/ + } catch (CommandException e) { + LOGGER.warn("Error while executing client-sided command '{}'", message, e); + commandSource.sendError(e.getTextMessage()); + return true; + } catch (RuntimeException e) { + LOGGER.warn("Error while executing client-sided command '{}'", message, e); + commandSource.sendError(Text.of(e.getMessage())); + return true; + } finally { + //commandSource.getClient().getProfiler().pop(); + } + } + + /** + * Tests whether a command syntax exception with the type + * should be ignored and the message sent to the server. + * + * @param type the exception type + * @return true if ignored, false otherwise + */ + private static boolean isIgnoredException(CommandExceptionType type) { + BuiltInExceptionProvider builtins = CommandSyntaxException.BUILT_IN_EXCEPTIONS; + + // Only ignore unknown commands and node parse exceptions. + // The argument-related dispatcher exceptions are not ignored because + // they will only happen if the user enters a correct command. + return type == builtins.dispatcherUnknownCommand() || type == builtins.dispatcherParseException(); + } + + // See CommandSuggestor.method_30505. That cannot be used directly as it returns an OrderedText instead of a Text. + private static Text getErrorMessage(CommandSyntaxException e) { + Text message = Texts.toText(e.getRawMessage()); + String context = e.getContext(); + + return context != null ? new TranslatableText("command.context.parse_error", message, context) : message; + } + + +} diff --git a/src/main/java/net/saltymc/eaa/commands/EaaCommand.java b/src/main/java/net/saltymc/eaa/commands/EaaCommand.java new file mode 100644 index 0000000..1193e52 --- /dev/null +++ b/src/main/java/net/saltymc/eaa/commands/EaaCommand.java @@ -0,0 +1,13 @@ +package net.saltymc.eaa.commands; + +import net.fabricmc.fabric.api.client.command.v1.FabricClientCommandSource; +import net.minecraft.text.Text; + +public class EaaCommand implements Command{ + @Override + public int run(FabricClientCommandSource cs, String[] args) { + cs.sendFeedback(Text.of("command catched!")); + + return 0; + } +} \ No newline at end of file diff --git a/src/main/java/net/saltymc/eaa/mixin/ExampleMixin.java b/src/main/java/net/saltymc/eaa/mixin/ExampleMixin.java index f71238b..d514018 100644 --- a/src/main/java/net/saltymc/eaa/mixin/ExampleMixin.java +++ b/src/main/java/net/saltymc/eaa/mixin/ExampleMixin.java @@ -1,11 +1,13 @@ package net.saltymc.eaa.mixin; import net.minecraft.client.gui.screen.TitleScreen; +import net.minecraft.client.network.ClientPlayerEntity; +import net.saltymc.eaa.commands.CommandHandler; 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") @@ -13,3 +15,14 @@ public class ExampleMixin { System.out.println("This line is printed by an example mod mixin!"); } } +*/ +@Mixin(ClientPlayerEntity.class) +public class ExampleMixin { //ClientPlayerEntityMixin + @Inject(method = "sendChatMessage", at = @At("HEAD"), cancellable = true) + private void onSendChatMessage(String message, CallbackInfo info) { + System.out.println("in onSendChatMessage"); + if (CommandHandler.executeCommand(message)) { + info.cancel(); + } + } +} \ No newline at end of file