forked from chipmunkmc/chipmunkbot
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:
parent
d0ea9a159d
commit
eddbe38e0e
17 changed files with 399 additions and 104 deletions
|
@ -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)); }
|
||||||
|
}
|
13
src/main/java/land/chipmunk/chipmunkbot/command/Command.java
Normal file
13
src/main/java/land/chipmunk/chipmunkbot/command/Command.java
Normal 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;
|
||||||
|
}
|
|
@ -1,12 +1,27 @@
|
||||||
package land.chipmunk.chipmunkbot.command;
|
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 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?
|
// ? Should I support message objects?
|
||||||
void sendOutput (Component message, boolean broadcast);
|
public void sendOutput (Component message, boolean broadcast) {}
|
||||||
void sendOutput (Component message);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,6 @@
|
||||||
package land.chipmunk.chipmunkbot.command;
|
package land.chipmunk.chipmunkbot.command;
|
||||||
|
|
||||||
|
import land.chipmunk.chipmunkbot.util.ComponentUtilities;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import com.mojang.brigadier.Message;
|
import com.mojang.brigadier.Message;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
@ -16,7 +17,7 @@ public class ComponentMessage implements Message {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getString () {
|
public String getString () {
|
||||||
return component.toString(); // ? Is this the best way to get the string?
|
return ComponentUtilities.stringify(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString () {
|
public String toString () {
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
package land.chipmunk.chipmunkbot.command;
|
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.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
|
@Override
|
||||||
public void sendOutput (Component message, boolean broadcast) {
|
public void sendOutput (Component message, boolean broadcast) {
|
||||||
System.out.println(message);
|
System.out.println(message);
|
||||||
// TODO: broadcast
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if (broadcast) client().chat().tellraw(Component.translatable("chat.type.admin", displayName(), message).color(NamedTextColor.GRAY).decoration(TextDecoration.ITALIC, true));
|
||||||
public void sendOutput (Component message) {
|
|
||||||
sendOutput(message, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -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; }
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,11 +2,17 @@ package land.chipmunk.chipmunkbot.plugins;
|
||||||
|
|
||||||
import land.chipmunk.chipmunkbot.ChipmunkBot;
|
import land.chipmunk.chipmunkbot.ChipmunkBot;
|
||||||
import land.chipmunk.chipmunkbot.command.CommandSource;
|
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.plugins.ChatPlugin;
|
||||||
import land.chipmunk.chipmunkbot.data.chat.PlayerMessage;
|
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.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import com.mojang.brigadier.CommandDispatcher;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
import com.mojang.brigadier.Message;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@ -27,6 +33,16 @@ public class ChatCommandHandler extends ChatPlugin.Listener {
|
||||||
if (!contentsString.startsWith(prefix)) return;
|
if (!contentsString.startsWith(prefix)) return;
|
||||||
final String commandString = contentsString.substring(prefix.length());
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package land.chipmunk.chipmunkbot.plugins;
|
||||||
import land.chipmunk.chipmunkbot.ChipmunkBot;
|
import land.chipmunk.chipmunkbot.ChipmunkBot;
|
||||||
import land.chipmunk.chipmunkbot.data.chat.PlayerMessage;
|
import land.chipmunk.chipmunkbot.data.chat.PlayerMessage;
|
||||||
import land.chipmunk.chipmunkbot.data.chat.SystemChatParser;
|
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.ClientboundPlayerChatPacket;
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSystemChatPacket;
|
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSystemChatPacket;
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatPacket;
|
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.SessionAdapter;
|
||||||
import com.github.steveice10.packetlib.event.session.SessionListener;
|
import com.github.steveice10.packetlib.event.session.SessionListener;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
|
||||||
import land.chipmunk.chipmunkbot.systemChat.*;
|
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) {
|
public void addListener (Listener listener) {
|
||||||
listeners.add(listener);
|
listeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,77 @@
|
||||||
package land.chipmunk.chipmunkbot.plugins;
|
package land.chipmunk.chipmunkbot.plugins;
|
||||||
|
|
||||||
import land.chipmunk.chipmunkbot.ChipmunkBot;
|
import land.chipmunk.chipmunkbot.ChipmunkBot;
|
||||||
|
import land.chipmunk.chipmunkbot.command.Command;
|
||||||
import land.chipmunk.chipmunkbot.command.CommandSource;
|
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.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.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.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
public class CommandManager {
|
public class CommandManager {
|
||||||
private ChipmunkBot client;
|
private ChipmunkBot client;
|
||||||
@Getter @Setter private CommandDispatcher<CommandSource> dispatcher = new CommandDispatcher<>();
|
@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) {
|
public CommandManager (ChipmunkBot client) {
|
||||||
this.client = 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); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -35,7 +35,7 @@ public class KaboomChatParser implements SystemChatParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerMessage parse (TranslatableComponent message) {
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package land.chipmunk.chipmunkbot.chat;
|
package land.chipmunk.chipmunkbot.util;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
@ -80,7 +80,7 @@ public class ComponentUtilities {
|
||||||
matcher.appendReplacement(sb, "%");
|
matcher.appendReplacement(sb, "%");
|
||||||
} else {
|
} else {
|
||||||
String idxStr = matcher.group(1);
|
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()) {
|
if (idx >= 0 && idx < message.args().size()) {
|
||||||
matcher.appendReplacement(sb, Matcher.quoteReplacement( stringify(message.args().get(idx)) ));
|
matcher.appendReplacement(sb, Matcher.quoteReplacement( stringify(message.args().get(idx)) ));
|
||||||
} else {
|
} else {
|
|
@ -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) + "}]"; }
|
||||||
|
}
|
Loading…
Reference in a new issue