diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/CommandManager.java b/cloud-core/src/main/java/com/intellectualsites/commands/CommandManager.java index 3ee3a8de..71bb607c 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/CommandManager.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/CommandManager.java @@ -23,6 +23,7 @@ // package com.intellectualsites.commands; +import com.google.common.collect.Maps; import com.google.common.reflect.TypeToken; import com.intellectualsites.commands.arguments.CommandArgument; import com.intellectualsites.commands.arguments.CommandSyntaxFormatter; @@ -45,12 +46,16 @@ import com.intellectualsites.services.ServicePipeline; import com.intellectualsites.services.State; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.Map; +import java.util.Optional; import java.util.StringTokenizer; import java.util.concurrent.CompletableFuture; +import java.util.function.BiConsumer; import java.util.function.Function; /** @@ -64,6 +69,7 @@ public abstract class CommandManager { private final CommandContextFactory commandContextFactory = new StandardCommandContextFactory<>(); private final ServicePipeline servicePipeline = ServicePipeline.builder().build(); private final ParserRegistry parserRegistry = new StandardParserRegistry<>(); + private final Map, BiConsumer> exceptionHandlers = Maps.newHashMap(); private final CommandExecutionCoordinator commandExecutionCoordinator; private final CommandRegistrationHandler commandRegistrationHandler; @@ -336,4 +342,50 @@ public abstract class CommandManager { return this.parserRegistry; } + /** + * Get the exception handler for an exception type, if one has been registered + * + * @param clazz Exception class + * @param Exception type + * @return Exception handler, or {@code null} + */ + @Nullable + public final BiConsumer getExceptionHandler(@Nullable final Class clazz) { + final BiConsumer consumer = this.exceptionHandlers.get(clazz); + if (consumer == null) { + return null; + } + //noinspection unchecked + return (BiConsumer) consumer; + } + + /** + * Register an exception handler for an exception type + * + * @param clazz Exception class + * @param handler Exception handler + * @param Exception type + */ + public final void registerExceptionHandler(@Nonnull final Class clazz, + @Nonnull final BiConsumer handler) { + this.exceptionHandlers.put(clazz, handler); + } + + /** + * Handler an exception using the registered exception handler for the exception type, or using the + * provided default handler if no exception handler has been registered for the exception type + * + * @param sender Executing command sender + * @param clazz Exception class + * @param exception Exception + * @param defaultHandler Default exception handler + * @param Exception type + */ + public final void handleException(@Nonnull final C sender, + @Nonnull final Class clazz, + @Nonnull final E exception, + @Nonnull final BiConsumer defaultHandler) { + Optional.ofNullable(this.getExceptionHandler(clazz)).orElse(defaultHandler).accept(sender, exception); + } + } diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/arguments/StandardCommandSyntaxFormatter.java b/cloud-core/src/main/java/com/intellectualsites/commands/arguments/StandardCommandSyntaxFormatter.java index 3faf3d49..c4449c1a 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/arguments/StandardCommandSyntaxFormatter.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/arguments/StandardCommandSyntaxFormatter.java @@ -77,10 +77,22 @@ public class StandardCommandSyntaxFormatter implements CommandSyntaxFormatter break; } final CommandArgument argument = tail.getChildren().get(0).getValue(); + final String prefix; + final String suffix; + if (argument instanceof StaticArgument) { + prefix = ""; + suffix = ""; + } else if (argument.isRequired()) { + prefix = "<"; + suffix = ">"; + } else { + prefix = "["; + suffix = "]"; + } stringBuilder.append(" ") - .append(argument.isRequired() ? '<' : '[') + .append(prefix) .append(argument.getName()) - .append(argument.isRequired() ? '>' : ']'); + .append(suffix); tail = tail.getChildren().get(0); } return stringBuilder.toString(); diff --git a/cloud-minecraft/cloud-brigadier/src/main/java/com/intellectualsites/commands/brigadier/CloudBrigadierManager.java b/cloud-minecraft/cloud-brigadier/src/main/java/com/intellectualsites/commands/brigadier/CloudBrigadierManager.java index 564928e2..508fd167 100644 --- a/cloud-minecraft/cloud-brigadier/src/main/java/com/intellectualsites/commands/brigadier/CloudBrigadierManager.java +++ b/cloud-minecraft/cloud-brigadier/src/main/java/com/intellectualsites/commands/brigadier/CloudBrigadierManager.java @@ -256,12 +256,11 @@ public final class CloudBrigadierManager { final LiteralArgumentBuilder literalArgumentBuilder = LiteralArgumentBuilder .literal(cloudCommand.getArguments().get(0).getName()) .requires(sender -> permissionChecker.test(sender, node.getNodeMeta().getOrDefault("permission", ""))); - if (node.isLeaf() && node.getValue() != null) { - literalArgumentBuilder.executes(executor); - } + literalArgumentBuilder.executes(executor); final LiteralCommandNode constructedRoot = literalArgumentBuilder.build(); for (final CommandTree.Node> child : node.getChildren()) { - constructedRoot.addChild(this.constructCommandNode(child, permissionChecker, executor, provider).build()); + constructedRoot.addChild(this.constructCommandNode(true, child, + permissionChecker, executor, provider).build()); } return constructedRoot; } @@ -289,12 +288,14 @@ public final class CloudBrigadierManager { } final LiteralCommandNode constructedRoot = literalArgumentBuilder.build(); for (final CommandTree.Node> child : cloudCommand.getChildren()) { - constructedRoot.addChild(this.constructCommandNode(child, permissionChecker, executor, suggestionProvider).build()); + constructedRoot.addChild(this.constructCommandNode(false, child, permissionChecker, + executor, suggestionProvider).build()); } return constructedRoot; } - private ArgumentBuilder constructCommandNode(@Nonnull final CommandTree.Node> root, + private ArgumentBuilder constructCommandNode(final boolean forceExecutor, + @Nonnull final CommandTree.Node> root, @Nonnull final BiPredicate permissionChecker, @Nonnull final com.mojang.brigadier.Command executor, @Nonnull final SuggestionProvider suggestionProvider) { @@ -313,11 +314,11 @@ public final class CloudBrigadierManager { .suggests(provider) .requires(sender -> permissionChecker.test(sender, root.getNodeMeta().getOrDefault("permission", ""))); } - if (root.isLeaf() || !root.getValue().isRequired()) { + if (forceExecutor || root.isLeaf() || !root.getValue().isRequired()) { argumentBuilder.executes(executor); } for (final CommandTree.Node> node : root.getChildren()) { - argumentBuilder.then(constructCommandNode(node, permissionChecker, executor, suggestionProvider)); + argumentBuilder.then(constructCommandNode(forceExecutor, node, permissionChecker, executor, suggestionProvider)); } return argumentBuilder; } diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/bukkit/BukkitCommand.java b/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/bukkit/BukkitCommand.java index c4f6f93a..370736ac 100644 --- a/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/bukkit/BukkitCommand.java +++ b/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/bukkit/BukkitCommand.java @@ -47,19 +47,19 @@ final class BukkitCommand extends org.bukkit.command.Command implements Plugi private static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command. Type \"/help\" for help."; private final CommandArgument command; - private final BukkitCommandManager bukkitCommandManager; + private final BukkitCommandManager manager; private final Command cloudCommand; @SuppressWarnings("unchecked") BukkitCommand(@Nonnull final Command cloudCommand, @Nonnull final CommandArgument command, - @Nonnull final BukkitCommandManager bukkitCommandManager) { + @Nonnull final BukkitCommandManager manager) { super(command.getName(), cloudCommand.getCommandMeta().getOrDefault("description", ""), "", ((StaticArgument) command).getAlternativeAliases()); this.command = command; - this.bukkitCommandManager = bukkitCommandManager; + this.manager = manager; this.cloudCommand = cloudCommand; } @@ -70,31 +70,52 @@ final class BukkitCommand extends org.bukkit.command.Command implements Plugi for (final String string : strings) { builder.append(" ").append(string); } - this.bukkitCommandManager.executeCommand(this.bukkitCommandManager.getCommandSenderMapper().apply(commandSender), - builder.toString()) - .whenComplete(((commandResult, throwable) -> { - if (throwable != null) { - if (throwable instanceof InvalidSyntaxException) { - commandSender.sendMessage(ChatColor.RED + "Invalid Command Syntax. " - + "Correct command syntax is: " - + ChatColor.GRAY + "/" - + ((InvalidSyntaxException) throwable).getCorrectSyntax()); - } else if (throwable instanceof InvalidCommandSenderException) { - commandSender.sendMessage(ChatColor.RED + throwable.getMessage()); - } else if (throwable instanceof NoPermissionException) { - commandSender.sendMessage(MESSAGE_NO_PERMS); - } else if (throwable instanceof NoSuchCommandException) { - commandSender.sendMessage(MESSAGE_UNKNOWN_COMMAND); - } else if (throwable instanceof ArgumentParseException) { - commandSender.sendMessage(ChatColor.RED + "Invalid Command Argument: " - + ChatColor.GRAY + throwable.getCause() - .getMessage()); - } else { - commandSender.sendMessage(throwable.getMessage()); - throwable.printStackTrace(); - } - } - })); + final C sender = this.manager.getCommandSenderMapper().apply(commandSender); + this.manager.executeCommand(sender, + builder.toString()) + .whenComplete(((commandResult, throwable) -> { + if (throwable != null) { + if (throwable instanceof InvalidSyntaxException) { + this.manager.handleException(sender, + InvalidSyntaxException.class, + (InvalidSyntaxException) throwable, (c, e) -> + commandSender.sendMessage(ChatColor.RED + "Invalid Command Syntax. " + + "Correct command syntax is: " + + ChatColor.GRAY + "/" + + ((InvalidSyntaxException) throwable).getCorrectSyntax()) + ); + } else if (throwable instanceof InvalidCommandSenderException) { + this.manager.handleException(sender, + InvalidCommandSenderException.class, + (InvalidCommandSenderException) throwable, (c, e) -> + commandSender.sendMessage(ChatColor.RED + throwable.getMessage()) + ); + } else if (throwable instanceof NoPermissionException) { + this.manager.handleException(sender, + NoPermissionException.class, + (NoPermissionException) throwable, (c, e) -> + commandSender.sendMessage(MESSAGE_NO_PERMS) + ); + } else if (throwable instanceof NoSuchCommandException) { + this.manager.handleException(sender, + NoSuchCommandException.class, + (NoSuchCommandException) throwable, (c, e) -> + commandSender.sendMessage(MESSAGE_UNKNOWN_COMMAND) + ); + } else if (throwable instanceof ArgumentParseException) { + this.manager.handleException(sender, + ArgumentParseException.class, + (ArgumentParseException) throwable, (c, e) -> + commandSender.sendMessage(ChatColor.RED + "Invalid Command Argument: " + + ChatColor.GRAY + throwable.getCause() + .getMessage()) + ); + } else { + commandSender.sendMessage(throwable.getMessage()); + throwable.printStackTrace(); + } + } + })); return true; } @@ -110,13 +131,13 @@ final class BukkitCommand extends org.bukkit.command.Command implements Plugi for (final String string : args) { builder.append(" ").append(string); } - return this.bukkitCommandManager.suggest(this.bukkitCommandManager.getCommandSenderMapper().apply(sender), - builder.toString()); + return this.manager.suggest(this.manager.getCommandSenderMapper().apply(sender), + builder.toString()); } @Override public Plugin getPlugin() { - return this.bukkitCommandManager.getOwningPlugin(); + return this.manager.getOwningPlugin(); } @Override diff --git a/cloud-minecraft/cloud-bungee/src/main/java/com/intellectualsites/commands/bungee/BungeeCommand.java b/cloud-minecraft/cloud-bungee/src/main/java/com/intellectualsites/commands/bungee/BungeeCommand.java index ad5cb993..e13df31a 100644 --- a/cloud-minecraft/cloud-bungee/src/main/java/com/intellectualsites/commands/bungee/BungeeCommand.java +++ b/cloud-minecraft/cloud-bungee/src/main/java/com/intellectualsites/commands/bungee/BungeeCommand.java @@ -45,19 +45,19 @@ public final class BungeeCommand extends Command implements TabExecutor { + "Please contact the server administrators if you believe that this is in error."; private static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command. Type \"/help\" for help."; - private final BungeeCommandManager bungeeCommandManager; + private final BungeeCommandManager manager; private final CommandArgument command; private final com.intellectualsites.commands.Command cloudCommand; @SuppressWarnings("unchecked") BungeeCommand(@Nonnull final com.intellectualsites.commands.Command cloudCommand, @Nonnull final CommandArgument command, - @Nonnull final BungeeCommandManager bungeeCommandManager) { + @Nonnull final BungeeCommandManager manager) { super(command.getName(), cloudCommand.getCommandPermission(), ((StaticArgument) command).getAlternativeAliases().toArray(new String[0])); this.command = command; - this.bungeeCommandManager = bungeeCommandManager; + this.manager = manager; this.cloudCommand = cloudCommand; } @@ -68,43 +68,64 @@ public final class BungeeCommand extends Command implements TabExecutor { for (final String string : strings) { builder.append(" ").append(string); } - this.bungeeCommandManager.executeCommand(this.bungeeCommandManager.getCommandSenderMapper().apply(commandSender), - builder.toString()) - .whenComplete(((commandResult, throwable) -> { - if (throwable != null) { - if (throwable instanceof InvalidSyntaxException) { - commandSender.sendMessage( - new ComponentBuilder("Invalid Command Syntax. Correct command syntax is: ") - .color(ChatColor.RED) - .append("/") - .color(ChatColor.GRAY) - .append(((InvalidSyntaxException) throwable).getCorrectSyntax()) - .color(ChatColor.GRAY) - .create() - ); - } else if (throwable instanceof InvalidCommandSenderException) { - commandSender.sendMessage(new ComponentBuilder(throwable.getMessage()) - .color(ChatColor.RED) - .create()); - } else if (throwable instanceof NoPermissionException) { - commandSender.sendMessage(new ComponentBuilder(MESSAGE_NO_PERMS) - .color(ChatColor.WHITE) - .create()); - } else if (throwable instanceof NoSuchCommandException) { - commandSender.sendMessage(new ComponentBuilder(MESSAGE_UNKNOWN_COMMAND) - .color(ChatColor.WHITE) - .create()); - } else if (throwable instanceof ArgumentParseException) { - commandSender.sendMessage(new ComponentBuilder("Invalid Command Argument: ") - .color(ChatColor.GRAY) - .append(throwable.getCause().getMessage()) - .create()); - } else { - commandSender.sendMessage(new ComponentBuilder(throwable.getMessage()).create()); - throwable.printStackTrace(); - } - } - })); + final C sender = this.manager.getCommandSenderMapper().apply(commandSender); + this.manager.executeCommand(sender, + builder.toString()) + .whenComplete(((commandResult, throwable) -> { + if (throwable != null) { + if (throwable instanceof InvalidSyntaxException) { + this.manager.handleException(sender, + InvalidSyntaxException.class, + (InvalidSyntaxException) throwable, (c, e) -> + commandSender.sendMessage( + new ComponentBuilder("Invalid Command Syntax. Correct command syntax is: ") + .color(ChatColor.RED) + .append("/") + .color(ChatColor.GRAY) + .append(((InvalidSyntaxException) throwable).getCorrectSyntax()) + .color(ChatColor.GRAY) + .create() + ) + ); + } else if (throwable instanceof InvalidCommandSenderException) { + this.manager.handleException(sender, + InvalidCommandSenderException.class, + (InvalidCommandSenderException) throwable, (c, e) -> + commandSender.sendMessage(new ComponentBuilder(throwable.getMessage()) + .color(ChatColor.RED) + .create()) + ); + } else if (throwable instanceof NoPermissionException) { + this.manager.handleException(sender, + NoPermissionException.class, + (NoPermissionException) throwable, (c, e) -> + commandSender.sendMessage(new ComponentBuilder(MESSAGE_NO_PERMS) + .color(ChatColor.WHITE) + .create()) + ); + } else if (throwable instanceof NoSuchCommandException) { + this.manager.handleException(sender, + NoSuchCommandException.class, + (NoSuchCommandException) throwable, (c, e) -> + commandSender.sendMessage(new ComponentBuilder(MESSAGE_UNKNOWN_COMMAND) + .color(ChatColor.WHITE) + .create()) + ); + } else if (throwable instanceof ArgumentParseException) { + this.manager.handleException(sender, + ArgumentParseException.class, + (ArgumentParseException) throwable, (c, e) -> + commandSender.sendMessage(new ComponentBuilder("Invalid Command Argument: ") + .color(ChatColor.GRAY) + .append(throwable.getCause().getMessage()) + .create()) + ); + } else { + commandSender.sendMessage(new ComponentBuilder(throwable.getMessage()).create()); + throwable.printStackTrace(); + } + } + })); } @Override @@ -114,8 +135,8 @@ public final class BungeeCommand extends Command implements TabExecutor { for (final String string : args) { builder.append(" ").append(string); } - return this.bungeeCommandManager.suggest(this.bungeeCommandManager.getCommandSenderMapper().apply(sender), - builder.toString()); + return this.manager.suggest(this.manager.getCommandSenderMapper().apply(sender), + builder.toString()); } } diff --git a/cloud-minecraft/cloud-velocity-test/pom.xml b/cloud-minecraft/cloud-velocity-test/pom.xml index c8e8555b..5bda597d 100644 --- a/cloud-minecraft/cloud-velocity-test/pom.xml +++ b/cloud-minecraft/cloud-velocity-test/pom.xml @@ -210,5 +210,10 @@ cloud-velocity 1.0-SNAPSHOT + + com.intellectualsites + cloud-annotations + 1.0-SNAPSHOT + diff --git a/cloud-minecraft/cloud-velocity-test/src/main/java/com/intellectualsites/cloudvelocitytest/CloudVelocityTest.java b/cloud-minecraft/cloud-velocity-test/src/main/java/com/intellectualsites/cloudvelocitytest/CloudVelocityTest.java index 06726dad..17b43e78 100644 --- a/cloud-minecraft/cloud-velocity-test/src/main/java/com/intellectualsites/cloudvelocitytest/CloudVelocityTest.java +++ b/cloud-minecraft/cloud-velocity-test/src/main/java/com/intellectualsites/cloudvelocitytest/CloudVelocityTest.java @@ -24,7 +24,12 @@ package com.intellectualsites.cloudvelocitytest; import com.google.inject.Inject; +import com.intellectualsites.commands.annotations.AnnotationParser; +import com.intellectualsites.commands.annotations.Argument; +import com.intellectualsites.commands.annotations.CommandMethod; +import com.intellectualsites.commands.annotations.specifier.Range; import com.intellectualsites.commands.execution.CommandExecutionCoordinator; +import com.intellectualsites.commands.meta.SimpleCommandMeta; import com.intellectualsites.commands.velocity.VelocityCommandManager; import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.event.Subscribe; @@ -68,6 +73,22 @@ public class CloudVelocityTest { .handler(c -> c.getSender().sendMessage(TextComponent.of("That's right ;)").color(NamedTextColor.GOLD))) .build() ); + final AnnotationParser annotationParser = new AnnotationParser<>(m, CommandSource.class, + p -> SimpleCommandMeta.empty()); + annotationParser.parse(this); + } + + @CommandMethod("test [str]") + private void testCommand(@Nonnull @Argument("str") final String string, + @Nonnull final CommandSource source, + @Argument("num") @Range(max = "33") final int num) { + source.sendMessage(TextComponent.builder() + .append("You wrote: ", NamedTextColor.GOLD) + .append(string, NamedTextColor.LIGHT_PURPLE) + .append(" and ", NamedTextColor.GOLD) + .append(Integer.toString(num), NamedTextColor.LIGHT_PURPLE) + .append("!", NamedTextColor.GOLD) + ); } } diff --git a/cloud-minecraft/cloud-velocity/src/main/java/com/intellectualsites/commands/velocity/VelocityPluginRegistrationHandler.java b/cloud-minecraft/cloud-velocity/src/main/java/com/intellectualsites/commands/velocity/VelocityPluginRegistrationHandler.java index f20f7a36..64cd5de4 100644 --- a/cloud-minecraft/cloud-velocity/src/main/java/com/intellectualsites/commands/velocity/VelocityPluginRegistrationHandler.java +++ b/cloud-minecraft/cloud-velocity/src/main/java/com/intellectualsites/commands/velocity/VelocityPluginRegistrationHandler.java @@ -28,10 +28,17 @@ import com.intellectualsites.commands.arguments.CommandArgument; import com.intellectualsites.commands.arguments.StaticArgument; import com.intellectualsites.commands.brigadier.CloudBrigadierManager; import com.intellectualsites.commands.context.CommandContext; +import com.intellectualsites.commands.exceptions.ArgumentParseException; +import com.intellectualsites.commands.exceptions.InvalidCommandSenderException; +import com.intellectualsites.commands.exceptions.InvalidSyntaxException; +import com.intellectualsites.commands.exceptions.NoPermissionException; +import com.intellectualsites.commands.exceptions.NoSuchCommandException; import com.intellectualsites.commands.internal.CommandRegistrationHandler; import com.velocitypowered.api.command.BrigadierCommand; import com.velocitypowered.api.command.CommandMeta; import com.velocitypowered.api.command.CommandSource; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.format.NamedTextColor; import javax.annotation.Nonnull; import java.util.HashMap; @@ -40,12 +47,17 @@ import java.util.Map; final class VelocityPluginRegistrationHandler implements CommandRegistrationHandler { + private static final String MESSAGE_NO_PERMS = + "I'm sorry, but you do not have permission to perform this command. " + + "Please contact the server administrators if you believe that this is in error."; + private static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command. Type \"/help\" for help."; + private final Map, BrigadierCommand> registeredCommands = new HashMap<>(); private CloudBrigadierManager brigadierManager; - private VelocityCommandManager velocityCommandManager; + private VelocityCommandManager manager; void initialize(@Nonnull final VelocityCommandManager velocityCommandManager) { - this.velocityCommandManager = velocityCommandManager; + this.manager = velocityCommandManager; this.brigadierManager = new CloudBrigadierManager<>(velocityCommandManager, () -> new CommandContext<>( velocityCommandManager.getCommandSenderMapper() @@ -63,22 +75,62 @@ final class VelocityPluginRegistrationHandler implements CommandRegistrationH final List aliases = ((StaticArgument) argument).getAlternativeAliases(); final BrigadierCommand brigadierCommand = new BrigadierCommand( this.brigadierManager.createLiteralCommandNode((Command) command, - (c, p) -> this.velocityCommandManager.hasPermission( - this.velocityCommandManager.getCommandSenderMapper() - .apply(c), p), - commandContext -> { - final CommandSource source = commandContext.getSource(); - final String input = commandContext.getInput(); - this.velocityCommandManager.executeCommand( - this.velocityCommandManager.getCommandSenderMapper() - .apply(source), input); - return com.mojang.brigadier.Command.SINGLE_SUCCESS; - }) + (c, p) -> this.manager.hasPermission( + this.manager.getCommandSenderMapper() + .apply(c), p), + commandContext -> { + final CommandSource source = commandContext.getSource(); + final String input = commandContext.getInput(); + final C sender = this.manager.getCommandSenderMapper().apply(source); + this.manager.executeCommand(sender, input).whenComplete((result, throwable) -> { + if (throwable != null) { + if (throwable instanceof InvalidSyntaxException) { + this.manager.handleException(sender, + InvalidSyntaxException.class, + (InvalidSyntaxException) throwable, (c, e) -> + source.sendMessage(TextComponent.builder("Invalid Command Syntax. Correct command syntax is: ", + NamedTextColor.RED) + .append(e.getCorrectSyntax(), NamedTextColor.GRAY).build()) + ); + } else if (throwable instanceof InvalidCommandSenderException) { + this.manager.handleException(sender, + InvalidCommandSenderException.class, + (InvalidCommandSenderException) throwable, (c, e) -> + source.sendMessage(TextComponent.of(throwable.getMessage()).color(NamedTextColor.RED)) + ); + } else if (throwable instanceof NoPermissionException) { + this.manager.handleException(sender, + NoPermissionException.class, + (NoPermissionException) throwable, (c, e) -> + source.sendMessage(TextComponent.of(MESSAGE_NO_PERMS)) + ); + } else if (throwable instanceof NoSuchCommandException) { + this.manager.handleException(sender, + NoSuchCommandException.class, + (NoSuchCommandException) throwable, (c, e) -> + source.sendMessage(TextComponent.of(MESSAGE_UNKNOWN_COMMAND)) + ); + } else if (throwable instanceof ArgumentParseException) { + this.manager.handleException(sender, + ArgumentParseException.class, + (ArgumentParseException) throwable, (c, e) -> + source.sendMessage(TextComponent.builder("Invalid Command Argument: ", NamedTextColor.RED) + .append(throwable.getCause().getMessage(), NamedTextColor.GRAY) + .build()) + ); + } else { + source.sendMessage(TextComponent.of(throwable.getMessage()).color(NamedTextColor.RED)); + throwable.printStackTrace(); + } + } + }); + return com.mojang.brigadier.Command.SINGLE_SUCCESS; + }) ); - final CommandMeta commandMeta = this.velocityCommandManager.getProxyServer().getCommandManager() - .metaBuilder(brigadierCommand) - .aliases(aliases.toArray(new String[0])).build(); - this.velocityCommandManager.getProxyServer().getCommandManager().register(commandMeta, brigadierCommand); + final CommandMeta commandMeta = this.manager.getProxyServer().getCommandManager() + .metaBuilder(brigadierCommand) + .aliases(aliases.toArray(new String[0])).build(); + this.manager.getProxyServer().getCommandManager().register(commandMeta, brigadierCommand); this.registeredCommands.put(argument, brigadierCommand); return true; }