commands mabe

* Added commands (**might change later**)

* Fixed  in stringifying translatable components

* Fixed the kaboom chat parser a tiny bit
This commit is contained in:
Chipmunk 2023-01-19 17:20:10 -05:00
parent d0ea9a159d
commit eddbe38e0e
17 changed files with 399 additions and 104 deletions

View file

@ -0,0 +1,82 @@
package land.chipmunk.chipmunkbot.command;
import com.mojang.brigadier.Message;
import com.mojang.brigadier.exceptions.BuiltInExceptionProvider;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.CommandExceptionType;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.TextComponent;
import java.util.Map;
import java.util.HashMap;
public class BuiltInExceptions implements BuiltInExceptionProvider {
private static final Dynamic2CommandExceptionType DOUBLE_TOO_SMALL = new Dynamic2CommandExceptionType((found, min) -> message("argument.double.low", text(min), text(found)));
private static final Dynamic2CommandExceptionType DOUBLE_TOO_BIG = new Dynamic2CommandExceptionType((found, max) -> message("argument.double.big", text(max), text(found)));
private static final Dynamic2CommandExceptionType FLOAT_TOO_SMALL = new Dynamic2CommandExceptionType((found, min) -> message("argument.float.low", text(min), text(found)));
private static final Dynamic2CommandExceptionType FLOAT_TOO_BIG = new Dynamic2CommandExceptionType((found, max) -> message("argument.float.big", text(max), text(found)));
private static final Dynamic2CommandExceptionType INTEGER_TOO_SMALL = new Dynamic2CommandExceptionType((found, min) -> message("argument.integer.low", text(min), text(found)));
private static final Dynamic2CommandExceptionType INTEGER_TOO_BIG = new Dynamic2CommandExceptionType((found, max) -> message("argument.integer.big", text(max), text(found)));
private static final Dynamic2CommandExceptionType LONG_TOO_SMALL = new Dynamic2CommandExceptionType((found, min) -> message("argument.long.low", text(min), text(found)));
private static final Dynamic2CommandExceptionType LONG_TOO_BIG = new Dynamic2CommandExceptionType((found, max) -> message("argument.long.big", text(max), text(found)));
private static final DynamicCommandExceptionType LITERAL_INCORRECT = new DynamicCommandExceptionType(expected -> message("argument.literal.incorrect", text(expected)));
private static final SimpleCommandExceptionType READER_EXPECTED_START_OF_QUOTE = new SimpleCommandExceptionType(message("parsing.quote.expected.start"));
private static final SimpleCommandExceptionType READER_EXPECTED_END_OF_QUOTE = new SimpleCommandExceptionType(message("parsing.quote.expected.end"));
private static final DynamicCommandExceptionType READER_INVALID_ESCAPE = new DynamicCommandExceptionType(character -> message("parsing.quote.escape", text(character)));
private static final DynamicCommandExceptionType READER_INVALID_BOOL = new DynamicCommandExceptionType(value -> message("parsing.bool.invalid", text(value)));
private static final DynamicCommandExceptionType READER_INVALID_INT = new DynamicCommandExceptionType(value -> message("parsing.int.invalid", text(value)));
private static final SimpleCommandExceptionType READER_EXPECTED_INT = new SimpleCommandExceptionType(message("parsing.int.expected"));
private static final DynamicCommandExceptionType READER_INVALID_LONG = new DynamicCommandExceptionType(value -> message("parsing.long.invalid", text(value)));
private static final SimpleCommandExceptionType READER_EXPECTED_LONG = new SimpleCommandExceptionType(message("parsing.long.expected"));
private static final DynamicCommandExceptionType READER_INVALID_DOUBLE = new DynamicCommandExceptionType(value -> message("parsing.double.invalid", text(value)));
private static final SimpleCommandExceptionType READER_EXPECTED_DOUBLE = new SimpleCommandExceptionType(message("parsing.double.expected"));
private static final DynamicCommandExceptionType READER_INVALID_FLOAT = new DynamicCommandExceptionType(value -> message("parsing.float.invalid", text(value)));
private static final SimpleCommandExceptionType READER_EXPECTED_FLOAT = new SimpleCommandExceptionType(message("parsing.float.expected"));
private static final SimpleCommandExceptionType READER_EXPECTED_BOOL = new SimpleCommandExceptionType(message("parsing.bool.expected"));
private static final DynamicCommandExceptionType READER_EXPECTED_SYMBOL = new DynamicCommandExceptionType(symbol -> message("parsing.expected", text(symbol)));
private static final SimpleCommandExceptionType DISPATCHER_UNKNOWN_COMMAND = new SimpleCommandExceptionType(message("command.unknown.command"));
private static final SimpleCommandExceptionType DISPATCHER_UNKNOWN_ARGUMENT = new SimpleCommandExceptionType(message("command.unknown.argument"));
private static final SimpleCommandExceptionType DISPATCHER_EXPECTED_ARGUMENT_SEPARATOR = new SimpleCommandExceptionType(message("command.expected.separator"));
private static final DynamicCommandExceptionType DISPATCHER_PARSE_EXCEPTION = new DynamicCommandExceptionType(_message -> message("command.exception", text(_message)));
@Override public Dynamic2CommandExceptionType doubleTooLow () { return DOUBLE_TOO_SMALL; }
@Override public Dynamic2CommandExceptionType doubleTooHigh () { return DOUBLE_TOO_BIG; }
@Override public Dynamic2CommandExceptionType floatTooLow () { return FLOAT_TOO_SMALL; }
@Override public Dynamic2CommandExceptionType floatTooHigh () { return FLOAT_TOO_BIG; }
@Override public Dynamic2CommandExceptionType integerTooLow () { return INTEGER_TOO_SMALL; }
@Override public Dynamic2CommandExceptionType integerTooHigh () { return INTEGER_TOO_BIG; }
@Override public Dynamic2CommandExceptionType longTooLow () { return LONG_TOO_SMALL; }
@Override public Dynamic2CommandExceptionType longTooHigh () { return LONG_TOO_BIG; }
@Override public DynamicCommandExceptionType literalIncorrect () { return LITERAL_INCORRECT; }
@Override public SimpleCommandExceptionType readerExpectedStartOfQuote () { return READER_EXPECTED_START_OF_QUOTE; }
@Override public SimpleCommandExceptionType readerExpectedEndOfQuote () { return READER_EXPECTED_END_OF_QUOTE; }
@Override public DynamicCommandExceptionType readerInvalidEscape () { return READER_INVALID_ESCAPE; }
@Override public DynamicCommandExceptionType readerInvalidBool () { return READER_INVALID_BOOL; }
@Override public DynamicCommandExceptionType readerInvalidInt () { return READER_INVALID_INT; }
@Override public SimpleCommandExceptionType readerExpectedInt () { return READER_EXPECTED_INT; }
@Override public DynamicCommandExceptionType readerInvalidLong () { return READER_INVALID_LONG; }
@Override public SimpleCommandExceptionType readerExpectedLong () { return READER_EXPECTED_LONG; }
@Override public DynamicCommandExceptionType readerInvalidDouble () { return READER_INVALID_DOUBLE; }
@Override public SimpleCommandExceptionType readerExpectedDouble () { return READER_EXPECTED_DOUBLE; }
@Override public DynamicCommandExceptionType readerInvalidFloat () { return READER_INVALID_FLOAT; }
@Override public SimpleCommandExceptionType readerExpectedFloat () { return READER_EXPECTED_FLOAT; }
@Override public SimpleCommandExceptionType readerExpectedBool () { return READER_EXPECTED_BOOL; }
@Override public DynamicCommandExceptionType readerExpectedSymbol () { return READER_EXPECTED_SYMBOL; }
@Override public SimpleCommandExceptionType dispatcherUnknownCommand () { return DISPATCHER_UNKNOWN_COMMAND; }
@Override public SimpleCommandExceptionType dispatcherUnknownArgument () { return DISPATCHER_UNKNOWN_ARGUMENT; }
@Override public SimpleCommandExceptionType dispatcherExpectedArgumentSeparator () { return DISPATCHER_EXPECTED_ARGUMENT_SEPARATOR; }
@Override public DynamicCommandExceptionType dispatcherParseException () { return DISPATCHER_PARSE_EXCEPTION; }
private static Message message (final String key, final ComponentLike... args) { return ComponentMessage.wrap(Component.translatable(key, args)); }
private static TextComponent text (final Object text) { return Component.text(String.valueOf(text)); }
}

View file

@ -0,0 +1,13 @@
package land.chipmunk.chipmunkbot.command;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Command {
private LiteralArgumentBuilder<CommandSource> builder;
}

View file

@ -1,12 +1,27 @@
package land.chipmunk.chipmunkbot.command;
import com.mojang.brigadier.Message;
import land.chipmunk.chipmunkbot.data.MutablePlayerListEntry;
import land.chipmunk.chipmunkbot.ChipmunkBot;
import net.kyori.adventure.text.Component;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import lombok.Getter;
import lombok.AllArgsConstructor;
@AllArgsConstructor
public class CommandSource {
@Getter private final ChipmunkBot client;
public interface CommandSource {
// ? Should I support message objects?
void sendOutput (Component message, boolean broadcast);
void sendOutput (Component message);
public void sendOutput (Component message, boolean broadcast) {}
public void sendOutput (Component message) { sendOutput(message, true); }
Component displayName ();
public Component displayName () { return Component.empty(); }
public MutablePlayerListEntry player () { return null; }
public MutablePlayerListEntry playerOrThrow () {
MutablePlayerListEntry player = player();
// if (player == null) throw new CommandSyntaxException(Component.text("Command must be executed by a player"));
return player;
}
}

View file

@ -1,66 +0,0 @@
package land.chipmunk.chipmunkbot.command;
import com.mojang.brigadier.Message;
import com.mojang.brigadier.exceptions.BuiltInExceptionProvider;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.CommandExceptionType;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.TextComponent;
import java.util.Map;
import java.util.HashMap;
public class CommandSyntaxErrorTypeMap {
private CommandSyntaxErrorTypeMap () {
}
// Just some methods for stuff repeated a lot
private static Message message (final String key, final ComponentLike... args) { return ComponentMessage.wrap(Component.translatable(key, args)); }
private static TextComponent text (final Object text) { return Component.text(String.valueOf(text)); }
private static TextComponent text (final int text) { return Component.text(text); }
private static TextComponent text (final char text) { return Component.text(String.valueOf(text)); }
public static Map<CommandExceptionType, CommandExceptionType> map = new HashMap<>();
static {
final BuiltInExceptionProvider builtIn = CommandSyntaxException.BUILT_IN_EXCEPTIONS;
map.put(builtIn.doubleTooLow(), new Dynamic2CommandExceptionType((found, min) -> message("argument.double.low", text(min), text(found))));
map.put(builtIn.doubleTooHigh(), new Dynamic2CommandExceptionType((found, max) -> message("argument.double.big", text(max), text(found))));
map.put(builtIn.floatTooLow(), new Dynamic2CommandExceptionType((found, min) -> message("argument.float.low", text(min), text(found))));
map.put(builtIn.floatTooHigh(), new Dynamic2CommandExceptionType((found, max) -> message("argument.float.big", text(max), text(found))));
map.put(builtIn.integerTooLow(), new Dynamic2CommandExceptionType((found, min) -> message("argument.integer.low", text(min), text(found))));
map.put(builtIn.integerTooHigh(), new Dynamic2CommandExceptionType((found, max) -> message("argument.integer.big", text(max), text(found))));
map.put(builtIn.longTooLow(), new Dynamic2CommandExceptionType((found, min) -> message("argument.long.low", text(min), text(found))));
map.put(builtIn.longTooHigh(), new Dynamic2CommandExceptionType((found, max) -> message("argument.long.big", text(max), text(found))));
map.put(builtIn.literalIncorrect(), new DynamicCommandExceptionType(expected -> message("argument.literal.incorrect", text(expected))));
map.put(builtIn.readerExpectedStartOfQuote(), new SimpleCommandExceptionType(message("parsing.quote.expected.start")));
map.put(builtIn.readerExpectedEndOfQuote(), new SimpleCommandExceptionType(message("parsing.quote.expected.end")));
map.put(builtIn.readerInvalidEscape(), new DynamicCommandExceptionType(character -> message("parsing.quote.escape", text(character))));
map.put(builtIn.readerInvalidBool(), new DynamicCommandExceptionType(value -> message("parsing.bool.invalid", text(value))));
map.put(builtIn.readerInvalidInt(), new DynamicCommandExceptionType(value -> message("parsing.int.invalid", text(value))));
map.put(builtIn.readerExpectedInt(), new SimpleCommandExceptionType(message("parsing.int.expected")));
map.put(builtIn.readerInvalidLong(), new DynamicCommandExceptionType(value -> message("parsing.long.invalid", text(value))));
map.put(builtIn.readerExpectedLong(), new SimpleCommandExceptionType(message("parsing.long.expected")));
map.put(builtIn.readerInvalidDouble(), new DynamicCommandExceptionType(value -> message("parsing.double.invalid", text(value))));
map.put(builtIn.readerExpectedDouble(), new SimpleCommandExceptionType(message("parsing.double.expected")));
map.put(builtIn.readerInvalidFloat(), new DynamicCommandExceptionType(value -> message("parsing.float.invalid", text(value))));
map.put(builtIn.readerExpectedFloat(), new SimpleCommandExceptionType(message("parsing.float.expected")));
map.put(builtIn.readerExpectedBool(), new SimpleCommandExceptionType(message("parsing.bool.expected")));
map.put(builtIn.readerExpectedSymbol(), new DynamicCommandExceptionType(symbol -> message("parsing.expected", text(symbol))));
map.put(builtIn.dispatcherUnknownCommand(), new SimpleCommandExceptionType(message("command.unknown.command")));
map.put(builtIn.dispatcherUnknownArgument(), new SimpleCommandExceptionType(message("command.unknown.argument")));
map.put(builtIn.dispatcherExpectedArgumentSeparator(), new SimpleCommandExceptionType(message("command.expected.separator")));
map.put(builtIn.dispatcherParseException(), new SimpleCommandExceptionType(message("command.exception")));
}
}

View file

@ -1,5 +1,6 @@
package land.chipmunk.chipmunkbot.command;
import land.chipmunk.chipmunkbot.util.ComponentUtilities;
import net.kyori.adventure.text.Component;
import com.mojang.brigadier.Message;
import lombok.Getter;
@ -16,7 +17,7 @@ public class ComponentMessage implements Message {
}
public String getString () {
return component.toString(); // ? Is this the best way to get the string?
return ComponentUtilities.stringify(component);
}
public String toString () {

View file

@ -1,18 +1,18 @@
package land.chipmunk.chipmunkbot.command;
import com.mojang.brigadier.Message;
import land.chipmunk.chipmunkbot.ChipmunkBot;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
public class ConsoleCommandSource extends CommandSource {
public ConsoleCommandSource (ChipmunkBot client) { super(client); }
public class ConsoleCommandSource implements CommandSource {
@Override
public void sendOutput (Component message, boolean broadcast) {
System.out.println(message);
// TODO: broadcast
}
@Override
public void sendOutput (Component message) {
sendOutput(message, true);
if (broadcast) client().chat().tellraw(Component.translatable("chat.type.admin", displayName(), message).color(NamedTextColor.GRAY).decoration(TextDecoration.ITALIC, true));
}
@Override

View file

@ -0,0 +1,36 @@
package land.chipmunk.chipmunkbot.command;
import land.chipmunk.chipmunkbot.data.MutablePlayerListEntry;
import land.chipmunk.chipmunkbot.util.UUIDUtilities;
import land.chipmunk.chipmunkbot.ChipmunkBot;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import java.util.UUID;
public class PlayerCommandSource extends CommandSource {
private final MutablePlayerListEntry player;
public PlayerCommandSource (ChipmunkBot client, MutablePlayerListEntry entry) {
super(client);
player = entry;
}
@Override
public void sendOutput (Component message, boolean broadcast) {
final UUID uuid = player.profile().getId();
client().chat().tellraw(message, uuid);
if (broadcast) client().chat().tellraw(Component.translatable("chat.type.admin", displayName(), message).color(NamedTextColor.GRAY).decoration(TextDecoration.ITALIC, true), UUIDUtilities.exclusiveSelector(uuid));
}
@Override
public Component displayName () {
final Component explicitDisplayName = player.displayName();
final Component displayName = explicitDisplayName != null ? explicitDisplayName : Component.text(player.profile().getName());
return displayName;
}
@Override public MutablePlayerListEntry player () { return this.player; }
}

View file

@ -0,0 +1,58 @@
package land.chipmunk.chipmunkbot.commands;
import land.chipmunk.chipmunkbot.ChipmunkBot;
import land.chipmunk.chipmunkbot.command.*;
import static land.chipmunk.chipmunkbot.plugins.CommandManager.literal;
import static land.chipmunk.chipmunkbot.plugins.CommandManager.argument;
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.context.CommandContext;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.JoinConfiguration;
import java.util.List;
import java.util.ArrayList;
public class HelpCommand extends Command {
public HelpCommand () {
super();
this.builder(
literal("help")
.executes(this::sendCommandList)
);
}
public int sendCommandList (CommandContext<CommandSource> context) {
final CommandSource source = context.getSource();
final ChipmunkBot client = source.client();
final CommandDispatcher dispatcher = client.commandManager().dispatcher();
source.sendOutput(generateCommandList(dispatcher), false);
return 1;
}
public Component generateCommandList (CommandDispatcher<CommandSource> dispatcher) {
final List<Component> list = new ArrayList<>();
for (CommandNode<CommandSource> node : dispatcher.getRoot().getChildren()) {
final String name = node.getName();
final List<Component> usages = new ArrayList<>();
for (String usage : dispatcher.getAllUsage(node, null, false)) {
final String text = (name + " " + usage).trim();
usages.add(Component.text(text));
}
final HoverEvent hoverEvent = HoverEvent.showText(Component.join(JoinConfiguration.separator(Component.newline()), usages));
list.add(Component.text(name).hoverEvent(hoverEvent));
}
return Component.translatable("Commands - %s", Component.join(JoinConfiguration.separator(Component.space()), list));
}
}

View file

@ -0,0 +1,33 @@
package land.chipmunk.chipmunkbot.commands;
import land.chipmunk.chipmunkbot.ChipmunkBot;
import land.chipmunk.chipmunkbot.command.*;
import static land.chipmunk.chipmunkbot.plugins.CommandManager.literal;
import static land.chipmunk.chipmunkbot.plugins.CommandManager.argument;
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
import com.mojang.brigadier.context.CommandContext;
import net.kyori.adventure.text.Component;
public class RunCommand extends Command {
public RunCommand () {
super();
this.builder(
literal("run")
.then(
argument("command", greedyString())
.executes(this::run)
)
);
}
public int run (CommandContext<CommandSource> context) {
final CommandSource source = context.getSource();
final ChipmunkBot client = source.client();
client.core().run(getString(context, "command"));
return 1;
}
}

View file

@ -0,0 +1,24 @@
package land.chipmunk.chipmunkbot.commands;
import land.chipmunk.chipmunkbot.command.*;
import static land.chipmunk.chipmunkbot.plugins.CommandManager.literal;
import com.mojang.brigadier.context.CommandContext;
import net.kyori.adventure.text.Component;
public class TestCommand extends Command {
public TestCommand () {
super();
this.builder(
literal("test")
.executes(this::helloWorld)
);
}
public int helloWorld (CommandContext<CommandSource> context) {
CommandSource source = context.getSource();
source.sendOutput(Component.text("Hello, world!"));
return 1;
}
}

View file

@ -2,11 +2,17 @@ package land.chipmunk.chipmunkbot.plugins;
import land.chipmunk.chipmunkbot.ChipmunkBot;
import land.chipmunk.chipmunkbot.command.CommandSource;
import land.chipmunk.chipmunkbot.command.PlayerCommandSource;
import land.chipmunk.chipmunkbot.command.ComponentMessage;
import land.chipmunk.chipmunkbot.plugins.ChatPlugin;
import land.chipmunk.chipmunkbot.data.chat.PlayerMessage;
import land.chipmunk.chipmunkbot.chat.ComponentUtilities;
import land.chipmunk.chipmunkbot.util.ComponentUtilities;
import land.chipmunk.chipmunkbot.plugins.CommandManager;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.Message;
import lombok.Getter;
import lombok.Setter;
@ -27,6 +33,16 @@ public class ChatCommandHandler extends ChatPlugin.Listener {
if (!contentsString.startsWith(prefix)) return;
final String commandString = contentsString.substring(prefix.length());
// System.out.println(ComponentUtilities.stringify(message.parameters().get("sender")) + " issued the command " + commandString);
final PlayerCommandSource source = new PlayerCommandSource(client, message.sender());
try {
CommandDispatcher dispatcher = client.commandManager().dispatcher();
dispatcher.execute(commandString, source);
} catch (CommandSyntaxException exception) {
CommandManager.sendException(source, exception);
} catch (Exception exception) {
exception.printStackTrace();
source.sendOutput(Component.translatable("command.failed", NamedTextColor.RED), false);
}
}
}

View file

@ -3,6 +3,7 @@ package land.chipmunk.chipmunkbot.plugins;
import land.chipmunk.chipmunkbot.ChipmunkBot;
import land.chipmunk.chipmunkbot.data.chat.PlayerMessage;
import land.chipmunk.chipmunkbot.data.chat.SystemChatParser;
import land.chipmunk.chipmunkbot.util.UUIDUtilities;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundPlayerChatPacket;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSystemChatPacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatPacket;
@ -12,9 +13,11 @@ import com.github.steveice10.packetlib.Session;
import com.github.steveice10.packetlib.event.session.SessionAdapter;
import com.github.steveice10.packetlib.event.session.SessionListener;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import java.util.BitSet;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.time.Instant;
import land.chipmunk.chipmunkbot.systemChat.*;
@ -67,6 +70,13 @@ public class ChatPlugin extends SessionAdapter {
}
}
// ? Should this be here?
public void tellraw (Component message, String targets) {
client.core.run("minecraft:tellraw " + targets + " " + GsonComponentSerializer.gson().serialize(message));
}
public void tellraw (Component message) { tellraw(message, "@a"); }
public void tellraw (Component message, UUID uuid) { tellraw(message, UUIDUtilities.selector(uuid)); }
public void addListener (Listener listener) {
listeners.add(listener);
}

View file

@ -1,19 +1,77 @@
package land.chipmunk.chipmunkbot.plugins;
import land.chipmunk.chipmunkbot.ChipmunkBot;
import land.chipmunk.chipmunkbot.command.Command;
import land.chipmunk.chipmunkbot.command.CommandSource;
import land.chipmunk.chipmunkbot.chat.ComponentUtilities;
import land.chipmunk.chipmunkbot.command.ComponentMessage;
import land.chipmunk.chipmunkbot.command.BuiltInExceptions;
import land.chipmunk.chipmunkbot.commands.*;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.event.ClickEvent;
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.Message;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import lombok.Getter;
import lombok.Setter;
public class CommandManager {
private ChipmunkBot client;
@Getter @Setter private CommandDispatcher<CommandSource> dispatcher = new CommandDispatcher<>();
@Getter @Setter private String prefix = "'"; // TODO: Don't hardcode this
private final Command[] commands = {new TestCommand(), new HelpCommand(), new RunCommand()};
static {
// ? Is messing with static properties a good idea?
CommandSyntaxException.BUILT_IN_EXCEPTIONS = new BuiltInExceptions();
}
public CommandManager (ChipmunkBot client) {
this.client = client;
for (Command command : commands) dispatcher.register(command.builder());
}
public static void sendException (CommandSource source, CommandSyntaxException exception) {
final Message message = exception.getRawMessage();
Component component;
if (message instanceof ComponentMessage) component = ((ComponentMessage) message).component();
else component = Component.text(message.getString());
source.sendOutput(component.color(NamedTextColor.RED), false);
final Component context = getContext(exception);
if (context != null) source.sendOutput(context, false);
}
public static Component getContext (CommandSyntaxException exception) {
final int _cursor = exception.getCursor();
final String input = exception.getInput();
if (input == null || _cursor < 0) {
return null;
}
Component component = Component.empty()
.color(NamedTextColor.GRAY)
.clickEvent(ClickEvent.suggestCommand(input));
final int cursor = Math.min(input.length(), _cursor);
if (cursor > CommandSyntaxException.CONTEXT_AMOUNT) {
component = component.append(Component.text("..."));
}
component = component
.append(Component.text(input.substring(Math.max(0, cursor - CommandSyntaxException.CONTEXT_AMOUNT), cursor)))
.append(Component.text(input.substring(cursor), NamedTextColor.RED).decoration(TextDecoration.UNDERLINED, true))
.append(Component.translatable("command.context.here", NamedTextColor.RED).decoration(TextDecoration.ITALIC, true));
return Component.empty().color(NamedTextColor.RED).append(component); // ? Should I Impostor Notchian here?
}
public static LiteralArgumentBuilder<CommandSource> literal(String name) { return LiteralArgumentBuilder.<CommandSource>literal(name); }
public static <T> RequiredArgumentBuilder<CommandSource, T> argument(String name, ArgumentType<T> type) { return RequiredArgumentBuilder.<CommandSource, T>argument(name, type); }
}

View file

@ -1,18 +0,0 @@
package land.chipmunk.chipmunkbot.plugins;
import land.chipmunk.chipmunkbot.ChipmunkBot;
import land.chipmunk.chipmunkbot.command.CommandSource;
import land.chipmunk.chipmunkbot.chat.ComponentUtilities;
import net.kyori.adventure.text.Component;
import com.mojang.brigadier.CommandDispatcher;
import lombok.Getter;
import lombok.Setter;
public class CommandManagerPlugin {
private ChipmunkBot client;
@Getter @Setter private CommandDispatcher<CommandSource> dispatcher = new CommandDispatcher<>();
public CommandManagerPlugin (ChipmunkBot client) {
this.client = client;
}
}

View file

@ -35,7 +35,7 @@ public class KaboomChatParser implements SystemChatParser {
}
public PlayerMessage parse (TranslatableComponent message) {
if (!message.key().equals("%") || message.args() == null || message.args().size() != 1 || !message.style().equals(empty)) return parse(message.args().get(0));
if (message.key().equals("%s") && message.args() != null && message.args().size() == 1 && message.style().equals(empty)) return parse(message.args().get(0));
return null;
}

View file

@ -1,4 +1,4 @@
package land.chipmunk.chipmunkbot.chat;
package land.chipmunk.chipmunkbot.util;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@ -80,7 +80,7 @@ public class ComponentUtilities {
matcher.appendReplacement(sb, "%");
} else {
String idxStr = matcher.group(1);
int idx = (idxStr == null ? i++ : Integer.parseInt(idxStr)) - 1;
int idx = idxStr == null ? i++ : (Integer.parseInt(idxStr) - 1);
if (idx >= 0 && idx < message.args().size()) {
matcher.appendReplacement(sb, Matcher.quoteReplacement( stringify(message.args().get(idx)) ));
} else {

View file

@ -0,0 +1,33 @@
package land.chipmunk.chipmunkbot.util;
import com.github.steveice10.opennbt.tag.builtin.IntArrayTag;
import java.util.UUID;
import java.nio.ByteBuffer;
public class UUIDUtilities {
private UUIDUtilities () {
}
public static int[] intArray (UUID uuid) {
final ByteBuffer buffer = ByteBuffer.wrap(new byte[16]);
buffer.putLong(0, uuid.getMostSignificantBits());
buffer.putLong(8, uuid.getLeastSignificantBits());
final int[] intArray = new int[4];
for (int i = 0; i < intArray.length; i++) intArray[i] = buffer.getInt();
return intArray;
}
public static IntArrayTag tag (UUID uuid) {
return new IntArrayTag("", intArray(uuid));
}
public static String snbt (UUID uuid) {
int[] array = intArray(uuid);
return "[I;" + array[0] + "," + array[1] + "," + array[2] + "," + array[3] + "]"; // TODO: improve lol
}
public static String selector (UUID uuid) { return "@a[limit=1,nbt={UUID:" + snbt(uuid) + "}]"; }
public static String exclusiveSelector (UUID uuid) { return "@a[nbt=!{UUID:" + snbt(uuid) + "}]"; }
}