Enable users to override exception handling and make the velocity test plugin less stupid

This commit is contained in:
Alexander Söderberg 2020-09-19 16:38:58 +02:00
parent 5f48b0a032
commit 1fede2b4c0
No known key found for this signature in database
GPG key ID: C0207FF7EA146678
8 changed files with 285 additions and 100 deletions

View file

@ -23,6 +23,7 @@
// //
package com.intellectualsites.commands; package com.intellectualsites.commands;
import com.google.common.collect.Maps;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
import com.intellectualsites.commands.arguments.CommandArgument; import com.intellectualsites.commands.arguments.CommandArgument;
import com.intellectualsites.commands.arguments.CommandSyntaxFormatter; import com.intellectualsites.commands.arguments.CommandSyntaxFormatter;
@ -45,12 +46,16 @@ import com.intellectualsites.services.ServicePipeline;
import com.intellectualsites.services.State; import com.intellectualsites.services.State;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
import java.util.function.Function; import java.util.function.Function;
/** /**
@ -64,6 +69,7 @@ public abstract class CommandManager<C> {
private final CommandContextFactory<C> commandContextFactory = new StandardCommandContextFactory<>(); private final CommandContextFactory<C> commandContextFactory = new StandardCommandContextFactory<>();
private final ServicePipeline servicePipeline = ServicePipeline.builder().build(); private final ServicePipeline servicePipeline = ServicePipeline.builder().build();
private final ParserRegistry<C> parserRegistry = new StandardParserRegistry<>(); private final ParserRegistry<C> parserRegistry = new StandardParserRegistry<>();
private final Map<Class<? extends Exception>, BiConsumer<C, ? extends Exception>> exceptionHandlers = Maps.newHashMap();
private final CommandExecutionCoordinator<C> commandExecutionCoordinator; private final CommandExecutionCoordinator<C> commandExecutionCoordinator;
private final CommandRegistrationHandler commandRegistrationHandler; private final CommandRegistrationHandler commandRegistrationHandler;
@ -336,4 +342,50 @@ public abstract class CommandManager<C> {
return this.parserRegistry; return this.parserRegistry;
} }
/**
* Get the exception handler for an exception type, if one has been registered
*
* @param clazz Exception class
* @param <E> Exception type
* @return Exception handler, or {@code null}
*/
@Nullable
public final <E extends Exception> BiConsumer<C, E> getExceptionHandler(@Nullable final Class<E> clazz) {
final BiConsumer<C, ? extends Exception> consumer = this.exceptionHandlers.get(clazz);
if (consumer == null) {
return null;
}
//noinspection unchecked
return (BiConsumer<C, E>) consumer;
}
/**
* Register an exception handler for an exception type
*
* @param clazz Exception class
* @param handler Exception handler
* @param <E> Exception type
*/
public final <E extends Exception> void registerExceptionHandler(@Nonnull final Class<E> clazz,
@Nonnull final BiConsumer<C, E> 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 <E> Exception type
*/
public final <E extends Exception> void handleException(@Nonnull final C sender,
@Nonnull final Class<E> clazz,
@Nonnull final E exception,
@Nonnull final BiConsumer<C, E> defaultHandler) {
Optional.ofNullable(this.getExceptionHandler(clazz)).orElse(defaultHandler).accept(sender, exception);
}
} }

View file

@ -77,10 +77,22 @@ public class StandardCommandSyntaxFormatter<C> implements CommandSyntaxFormatter
break; break;
} }
final CommandArgument<C, ?> argument = tail.getChildren().get(0).getValue(); final CommandArgument<C, ?> 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(" ") stringBuilder.append(" ")
.append(argument.isRequired() ? '<' : '[') .append(prefix)
.append(argument.getName()) .append(argument.getName())
.append(argument.isRequired() ? '>' : ']'); .append(suffix);
tail = tail.getChildren().get(0); tail = tail.getChildren().get(0);
} }
return stringBuilder.toString(); return stringBuilder.toString();

View file

@ -256,12 +256,11 @@ public final class CloudBrigadierManager<C, S> {
final LiteralArgumentBuilder<S> literalArgumentBuilder = LiteralArgumentBuilder final LiteralArgumentBuilder<S> literalArgumentBuilder = LiteralArgumentBuilder
.<S>literal(cloudCommand.getArguments().get(0).getName()) .<S>literal(cloudCommand.getArguments().get(0).getName())
.requires(sender -> permissionChecker.test(sender, node.getNodeMeta().getOrDefault("permission", ""))); .requires(sender -> permissionChecker.test(sender, node.getNodeMeta().getOrDefault("permission", "")));
if (node.isLeaf() && node.getValue() != null) { literalArgumentBuilder.executes(executor);
literalArgumentBuilder.executes(executor);
}
final LiteralCommandNode<S> constructedRoot = literalArgumentBuilder.build(); final LiteralCommandNode<S> constructedRoot = literalArgumentBuilder.build();
for (final CommandTree.Node<CommandArgument<C, ?>> child : node.getChildren()) { for (final CommandTree.Node<CommandArgument<C, ?>> child : node.getChildren()) {
constructedRoot.addChild(this.constructCommandNode(child, permissionChecker, executor, provider).build()); constructedRoot.addChild(this.constructCommandNode(true, child,
permissionChecker, executor, provider).build());
} }
return constructedRoot; return constructedRoot;
} }
@ -289,12 +288,14 @@ public final class CloudBrigadierManager<C, S> {
} }
final LiteralCommandNode<S> constructedRoot = literalArgumentBuilder.build(); final LiteralCommandNode<S> constructedRoot = literalArgumentBuilder.build();
for (final CommandTree.Node<CommandArgument<C, ?>> child : cloudCommand.getChildren()) { for (final CommandTree.Node<CommandArgument<C, ?>> child : cloudCommand.getChildren()) {
constructedRoot.addChild(this.constructCommandNode(child, permissionChecker, executor, suggestionProvider).build()); constructedRoot.addChild(this.constructCommandNode(false, child, permissionChecker,
executor, suggestionProvider).build());
} }
return constructedRoot; return constructedRoot;
} }
private ArgumentBuilder<S, ?> constructCommandNode(@Nonnull final CommandTree.Node<CommandArgument<C, ?>> root, private ArgumentBuilder<S, ?> constructCommandNode(final boolean forceExecutor,
@Nonnull final CommandTree.Node<CommandArgument<C, ?>> root,
@Nonnull final BiPredicate<S, String> permissionChecker, @Nonnull final BiPredicate<S, String> permissionChecker,
@Nonnull final com.mojang.brigadier.Command<S> executor, @Nonnull final com.mojang.brigadier.Command<S> executor,
@Nonnull final SuggestionProvider<S> suggestionProvider) { @Nonnull final SuggestionProvider<S> suggestionProvider) {
@ -313,11 +314,11 @@ public final class CloudBrigadierManager<C, S> {
.suggests(provider) .suggests(provider)
.requires(sender -> permissionChecker.test(sender, root.getNodeMeta().getOrDefault("permission", ""))); .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); argumentBuilder.executes(executor);
} }
for (final CommandTree.Node<CommandArgument<C, ?>> node : root.getChildren()) { for (final CommandTree.Node<CommandArgument<C, ?>> node : root.getChildren()) {
argumentBuilder.then(constructCommandNode(node, permissionChecker, executor, suggestionProvider)); argumentBuilder.then(constructCommandNode(forceExecutor, node, permissionChecker, executor, suggestionProvider));
} }
return argumentBuilder; return argumentBuilder;
} }

View file

@ -47,19 +47,19 @@ final class BukkitCommand<C> extends org.bukkit.command.Command implements Plugi
private static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command. Type \"/help\" for help."; private static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command. Type \"/help\" for help.";
private final CommandArgument<C, ?> command; private final CommandArgument<C, ?> command;
private final BukkitCommandManager<C> bukkitCommandManager; private final BukkitCommandManager<C> manager;
private final Command<C> cloudCommand; private final Command<C> cloudCommand;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
BukkitCommand(@Nonnull final Command<C> cloudCommand, BukkitCommand(@Nonnull final Command<C> cloudCommand,
@Nonnull final CommandArgument<C, ?> command, @Nonnull final CommandArgument<C, ?> command,
@Nonnull final BukkitCommandManager<C> bukkitCommandManager) { @Nonnull final BukkitCommandManager<C> manager) {
super(command.getName(), super(command.getName(),
cloudCommand.getCommandMeta().getOrDefault("description", ""), cloudCommand.getCommandMeta().getOrDefault("description", ""),
"", "",
((StaticArgument<C>) command).getAlternativeAliases()); ((StaticArgument<C>) command).getAlternativeAliases());
this.command = command; this.command = command;
this.bukkitCommandManager = bukkitCommandManager; this.manager = manager;
this.cloudCommand = cloudCommand; this.cloudCommand = cloudCommand;
} }
@ -70,31 +70,52 @@ final class BukkitCommand<C> extends org.bukkit.command.Command implements Plugi
for (final String string : strings) { for (final String string : strings) {
builder.append(" ").append(string); builder.append(" ").append(string);
} }
this.bukkitCommandManager.executeCommand(this.bukkitCommandManager.getCommandSenderMapper().apply(commandSender), final C sender = this.manager.getCommandSenderMapper().apply(commandSender);
builder.toString()) this.manager.executeCommand(sender,
.whenComplete(((commandResult, throwable) -> { builder.toString())
if (throwable != null) { .whenComplete(((commandResult, throwable) -> {
if (throwable instanceof InvalidSyntaxException) { if (throwable != null) {
commandSender.sendMessage(ChatColor.RED + "Invalid Command Syntax. " if (throwable instanceof InvalidSyntaxException) {
+ "Correct command syntax is: " this.manager.handleException(sender,
+ ChatColor.GRAY + "/" InvalidSyntaxException.class,
+ ((InvalidSyntaxException) throwable).getCorrectSyntax()); (InvalidSyntaxException) throwable, (c, e) ->
} else if (throwable instanceof InvalidCommandSenderException) { commandSender.sendMessage(ChatColor.RED + "Invalid Command Syntax. "
commandSender.sendMessage(ChatColor.RED + throwable.getMessage()); + "Correct command syntax is: "
} else if (throwable instanceof NoPermissionException) { + ChatColor.GRAY + "/"
commandSender.sendMessage(MESSAGE_NO_PERMS); + ((InvalidSyntaxException) throwable).getCorrectSyntax())
} else if (throwable instanceof NoSuchCommandException) { );
commandSender.sendMessage(MESSAGE_UNKNOWN_COMMAND); } else if (throwable instanceof InvalidCommandSenderException) {
} else if (throwable instanceof ArgumentParseException) { this.manager.handleException(sender,
commandSender.sendMessage(ChatColor.RED + "Invalid Command Argument: " InvalidCommandSenderException.class,
+ ChatColor.GRAY + throwable.getCause() (InvalidCommandSenderException) throwable, (c, e) ->
.getMessage()); commandSender.sendMessage(ChatColor.RED + throwable.getMessage())
} else { );
commandSender.sendMessage(throwable.getMessage()); } else if (throwable instanceof NoPermissionException) {
throwable.printStackTrace(); 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; return true;
} }
@ -110,13 +131,13 @@ final class BukkitCommand<C> extends org.bukkit.command.Command implements Plugi
for (final String string : args) { for (final String string : args) {
builder.append(" ").append(string); builder.append(" ").append(string);
} }
return this.bukkitCommandManager.suggest(this.bukkitCommandManager.getCommandSenderMapper().apply(sender), return this.manager.suggest(this.manager.getCommandSenderMapper().apply(sender),
builder.toString()); builder.toString());
} }
@Override @Override
public Plugin getPlugin() { public Plugin getPlugin() {
return this.bukkitCommandManager.getOwningPlugin(); return this.manager.getOwningPlugin();
} }
@Override @Override

View file

@ -45,19 +45,19 @@ public final class BungeeCommand<C> extends Command implements TabExecutor {
+ "Please contact the server administrators if you believe that this is in error."; + "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 static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command. Type \"/help\" for help.";
private final BungeeCommandManager<C> bungeeCommandManager; private final BungeeCommandManager<C> manager;
private final CommandArgument<C, ?> command; private final CommandArgument<C, ?> command;
private final com.intellectualsites.commands.Command<C> cloudCommand; private final com.intellectualsites.commands.Command<C> cloudCommand;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
BungeeCommand(@Nonnull final com.intellectualsites.commands.Command<C> cloudCommand, BungeeCommand(@Nonnull final com.intellectualsites.commands.Command<C> cloudCommand,
@Nonnull final CommandArgument<C, ?> command, @Nonnull final CommandArgument<C, ?> command,
@Nonnull final BungeeCommandManager<C> bungeeCommandManager) { @Nonnull final BungeeCommandManager<C> manager) {
super(command.getName(), super(command.getName(),
cloudCommand.getCommandPermission(), cloudCommand.getCommandPermission(),
((StaticArgument<C>) command).getAlternativeAliases().toArray(new String[0])); ((StaticArgument<C>) command).getAlternativeAliases().toArray(new String[0]));
this.command = command; this.command = command;
this.bungeeCommandManager = bungeeCommandManager; this.manager = manager;
this.cloudCommand = cloudCommand; this.cloudCommand = cloudCommand;
} }
@ -68,43 +68,64 @@ public final class BungeeCommand<C> extends Command implements TabExecutor {
for (final String string : strings) { for (final String string : strings) {
builder.append(" ").append(string); builder.append(" ").append(string);
} }
this.bungeeCommandManager.executeCommand(this.bungeeCommandManager.getCommandSenderMapper().apply(commandSender), final C sender = this.manager.getCommandSenderMapper().apply(commandSender);
builder.toString()) this.manager.executeCommand(sender,
.whenComplete(((commandResult, throwable) -> { builder.toString())
if (throwable != null) { .whenComplete(((commandResult, throwable) -> {
if (throwable instanceof InvalidSyntaxException) { if (throwable != null) {
commandSender.sendMessage( if (throwable instanceof InvalidSyntaxException) {
new ComponentBuilder("Invalid Command Syntax. Correct command syntax is: ") this.manager.handleException(sender,
.color(ChatColor.RED) InvalidSyntaxException.class,
.append("/") (InvalidSyntaxException) throwable, (c, e) ->
.color(ChatColor.GRAY) commandSender.sendMessage(
.append(((InvalidSyntaxException) throwable).getCorrectSyntax()) new ComponentBuilder("Invalid Command Syntax. Correct command syntax is: ")
.color(ChatColor.GRAY) .color(ChatColor.RED)
.create() .append("/")
); .color(ChatColor.GRAY)
} else if (throwable instanceof InvalidCommandSenderException) { .append(((InvalidSyntaxException) throwable).getCorrectSyntax())
commandSender.sendMessage(new ComponentBuilder(throwable.getMessage()) .color(ChatColor.GRAY)
.color(ChatColor.RED) .create()
.create()); )
} else if (throwable instanceof NoPermissionException) { );
commandSender.sendMessage(new ComponentBuilder(MESSAGE_NO_PERMS) } else if (throwable instanceof InvalidCommandSenderException) {
.color(ChatColor.WHITE) this.manager.handleException(sender,
.create()); InvalidCommandSenderException.class,
} else if (throwable instanceof NoSuchCommandException) { (InvalidCommandSenderException) throwable, (c, e) ->
commandSender.sendMessage(new ComponentBuilder(MESSAGE_UNKNOWN_COMMAND) commandSender.sendMessage(new ComponentBuilder(throwable.getMessage())
.color(ChatColor.WHITE) .color(ChatColor.RED)
.create()); .create())
} else if (throwable instanceof ArgumentParseException) { );
commandSender.sendMessage(new ComponentBuilder("Invalid Command Argument: ") } else if (throwable instanceof NoPermissionException) {
.color(ChatColor.GRAY) this.manager.handleException(sender,
.append(throwable.getCause().getMessage()) NoPermissionException.class,
.create()); (NoPermissionException) throwable, (c, e) ->
} else { commandSender.sendMessage(new ComponentBuilder(MESSAGE_NO_PERMS)
commandSender.sendMessage(new ComponentBuilder(throwable.getMessage()).create()); .color(ChatColor.WHITE)
throwable.printStackTrace(); .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 @Override
@ -114,8 +135,8 @@ public final class BungeeCommand<C> extends Command implements TabExecutor {
for (final String string : args) { for (final String string : args) {
builder.append(" ").append(string); builder.append(" ").append(string);
} }
return this.bungeeCommandManager.suggest(this.bungeeCommandManager.getCommandSenderMapper().apply(sender), return this.manager.suggest(this.manager.getCommandSenderMapper().apply(sender),
builder.toString()); builder.toString());
} }
} }

View file

@ -210,5 +210,10 @@
<artifactId>cloud-velocity</artifactId> <artifactId>cloud-velocity</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>com.intellectualsites</groupId>
<artifactId>cloud-annotations</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View file

@ -24,7 +24,12 @@
package com.intellectualsites.cloudvelocitytest; package com.intellectualsites.cloudvelocitytest;
import com.google.inject.Inject; 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.execution.CommandExecutionCoordinator;
import com.intellectualsites.commands.meta.SimpleCommandMeta;
import com.intellectualsites.commands.velocity.VelocityCommandManager; import com.intellectualsites.commands.velocity.VelocityCommandManager;
import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.event.Subscribe; 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))) .handler(c -> c.getSender().sendMessage(TextComponent.of("That's right ;)").color(NamedTextColor.GOLD)))
.build() .build()
); );
final AnnotationParser<CommandSource> annotationParser = new AnnotationParser<>(m, CommandSource.class,
p -> SimpleCommandMeta.empty());
annotationParser.parse(this);
}
@CommandMethod("test <num> [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)
);
} }
} }

View file

@ -28,10 +28,17 @@ import com.intellectualsites.commands.arguments.CommandArgument;
import com.intellectualsites.commands.arguments.StaticArgument; import com.intellectualsites.commands.arguments.StaticArgument;
import com.intellectualsites.commands.brigadier.CloudBrigadierManager; import com.intellectualsites.commands.brigadier.CloudBrigadierManager;
import com.intellectualsites.commands.context.CommandContext; 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.intellectualsites.commands.internal.CommandRegistrationHandler;
import com.velocitypowered.api.command.BrigadierCommand; import com.velocitypowered.api.command.BrigadierCommand;
import com.velocitypowered.api.command.CommandMeta; import com.velocitypowered.api.command.CommandMeta;
import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.CommandSource;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.HashMap; import java.util.HashMap;
@ -40,12 +47,17 @@ import java.util.Map;
final class VelocityPluginRegistrationHandler<C> implements CommandRegistrationHandler { final class VelocityPluginRegistrationHandler<C> 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<CommandArgument<?, ?>, BrigadierCommand> registeredCommands = new HashMap<>(); private final Map<CommandArgument<?, ?>, BrigadierCommand> registeredCommands = new HashMap<>();
private CloudBrigadierManager<C, CommandSource> brigadierManager; private CloudBrigadierManager<C, CommandSource> brigadierManager;
private VelocityCommandManager<C> velocityCommandManager; private VelocityCommandManager<C> manager;
void initialize(@Nonnull final VelocityCommandManager<C> velocityCommandManager) { void initialize(@Nonnull final VelocityCommandManager<C> velocityCommandManager) {
this.velocityCommandManager = velocityCommandManager; this.manager = velocityCommandManager;
this.brigadierManager = new CloudBrigadierManager<>(velocityCommandManager, this.brigadierManager = new CloudBrigadierManager<>(velocityCommandManager,
() -> new CommandContext<>( () -> new CommandContext<>(
velocityCommandManager.getCommandSenderMapper() velocityCommandManager.getCommandSenderMapper()
@ -63,22 +75,62 @@ final class VelocityPluginRegistrationHandler<C> implements CommandRegistrationH
final List<String> aliases = ((StaticArgument<C>) argument).getAlternativeAliases(); final List<String> aliases = ((StaticArgument<C>) argument).getAlternativeAliases();
final BrigadierCommand brigadierCommand = new BrigadierCommand( final BrigadierCommand brigadierCommand = new BrigadierCommand(
this.brigadierManager.createLiteralCommandNode((Command<C>) command, this.brigadierManager.createLiteralCommandNode((Command<C>) command,
(c, p) -> this.velocityCommandManager.hasPermission( (c, p) -> this.manager.hasPermission(
this.velocityCommandManager.getCommandSenderMapper() this.manager.getCommandSenderMapper()
.apply(c), p), .apply(c), p),
commandContext -> { commandContext -> {
final CommandSource source = commandContext.getSource(); final CommandSource source = commandContext.getSource();
final String input = commandContext.getInput(); final String input = commandContext.getInput();
this.velocityCommandManager.executeCommand( final C sender = this.manager.getCommandSenderMapper().apply(source);
this.velocityCommandManager.getCommandSenderMapper() this.manager.executeCommand(sender, input).whenComplete((result, throwable) -> {
.apply(source), input); if (throwable != null) {
return com.mojang.brigadier.Command.SINGLE_SUCCESS; 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() final CommandMeta commandMeta = this.manager.getProxyServer().getCommandManager()
.metaBuilder(brigadierCommand) .metaBuilder(brigadierCommand)
.aliases(aliases.toArray(new String[0])).build(); .aliases(aliases.toArray(new String[0])).build();
this.velocityCommandManager.getProxyServer().getCommandManager().register(commandMeta, brigadierCommand); this.manager.getProxyServer().getCommandManager().register(commandMeta, brigadierCommand);
this.registeredCommands.put(argument, brigadierCommand); this.registeredCommands.put(argument, brigadierCommand);
return true; return true;
} }