diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/CommandTree.java b/cloud-core/src/main/java/com/intellectualsites/commands/CommandTree.java index ce93a975..783bd8ac 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/CommandTree.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/CommandTree.java @@ -531,8 +531,17 @@ public final class CommandTree { */ @Nullable public Node> getNamedNode(@Nullable final String name) { - return this.getRootNodes().stream().filter(node -> node.getValue() != null - && node.getValue().getName().equalsIgnoreCase(name)).findAny().orElse(null); + for (final Node> node : this.getRootNodes()) { + if (node.getValue() != null && node.getValue() instanceof StaticArgument) { + final StaticArgument staticArgument = (StaticArgument) node.getValue(); + for (final String alias : staticArgument.getAliases()) { + if (alias.equalsIgnoreCase(name)) { + return node; + } + } + } + } + return null; } /** diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/arguments/CommandArgument.java b/cloud-core/src/main/java/com/intellectualsites/commands/arguments/CommandArgument.java index 0ef5dd70..ed40c1c2 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/arguments/CommandArgument.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/arguments/CommandArgument.java @@ -165,7 +165,7 @@ public class CommandArgument implements Comparable> @Nonnull @Override public final String toString() { - return String.format("CommandArgument{name=%s}", this.name); + return String.format("%s{name=%s}", this.getClass().getSimpleName(), this.name); } /** diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/ByteArgument.java b/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/ByteArgument.java index d3c27b07..f25000d4 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/ByteArgument.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/ByteArgument.java @@ -214,6 +214,24 @@ public final class ByteArgument extends CommandArgument { return IntegerArgument.IntegerParser.getSuggestions(this.min, this.max, input); } + /** + * Get the max value + * + * @return Max value + */ + public byte getMax() { + return this.max; + } + + /** + * Get the min value + * + * @return Min value + */ + public byte getMin() { + return this.min; + } + } diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/DoubleArgument.java b/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/DoubleArgument.java index b88e130a..21ace85c 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/DoubleArgument.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/DoubleArgument.java @@ -204,6 +204,24 @@ public final class DoubleArgument extends CommandArgument { return true; } + /** + * Get the max value + * + * @return Max value + */ + public double getMax() { + return this.max; + } + + /** + * Get the min value + * + * @return Min value + */ + public double getMin() { + return this.min; + } + } diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/FloatArgument.java b/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/FloatArgument.java index 71a55128..eeab6f20 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/FloatArgument.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/FloatArgument.java @@ -203,6 +203,25 @@ public final class FloatArgument extends CommandArgument { public boolean isContextFree() { return true; } + + /** + * Get the max value + * + * @return Max value + */ + public float getMax() { + return this.max; + } + + /** + * Get the min value + * + * @return Min value + */ + public float getMin() { + return this.min; + } + } diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/ShortArgument.java b/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/ShortArgument.java index 434a7a18..4e080c70 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/ShortArgument.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/ShortArgument.java @@ -212,6 +212,24 @@ public final class ShortArgument extends CommandArgument { return IntegerArgument.IntegerParser.getSuggestions(this.min, this.max, input); } + /** + * Get the max value + * + * @return Max value + */ + public short getMax() { + return this.max; + } + + /** + * Get the min value + * + * @return Min value + */ + public short getMin() { + return this.min; + } + } diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/StringArgument.java b/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/StringArgument.java index 0abaee95..7327fed1 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/StringArgument.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/StringArgument.java @@ -268,6 +268,16 @@ public final class StringArgument extends CommandArgument { public boolean isContextFree() { return true; } + + /** + * Get the string mode + * + * @return String mode + */ + @Nonnull + public StringMode getStringMode() { + return this.stringMode; + } } 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 508fd167..24ded607 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 @@ -30,6 +30,7 @@ import com.intellectualsites.commands.CommandManager; import com.intellectualsites.commands.CommandTree; import com.intellectualsites.commands.arguments.CommandArgument; import com.intellectualsites.commands.arguments.StaticArgument; +import com.intellectualsites.commands.arguments.parser.ArgumentParser; import com.intellectualsites.commands.arguments.standard.BooleanArgument; import com.intellectualsites.commands.arguments.standard.ByteArgument; import com.intellectualsites.commands.arguments.standard.DoubleArgument; @@ -77,7 +78,7 @@ import java.util.function.Supplier; */ public final class CloudBrigadierManager { - private final Map, Function, + private final Map, Function, ? extends ArgumentType>> mappers; private final Map, Supplier>> defaultArgumentTypeSuppliers; private final Supplier> dummyContextProvider; @@ -101,7 +102,7 @@ public final class CloudBrigadierManager { private void registerInternalMappings() { /* Map byte, short and int to IntegerArgumentType */ - this.registerMapping(new TypeToken>() { + this.registerMapping(new TypeToken>() { }, argument -> { final boolean hasMin = argument.getMin() != Byte.MIN_VALUE; final boolean hasMax = argument.getMax() != Byte.MAX_VALUE; @@ -113,7 +114,7 @@ public final class CloudBrigadierManager { return IntegerArgumentType.integer(); } }); - this.registerMapping(new TypeToken>() { + this.registerMapping(new TypeToken>() { }, argument -> { final boolean hasMin = argument.getMin() != Short.MIN_VALUE; final boolean hasMax = argument.getMax() != Short.MAX_VALUE; @@ -125,7 +126,7 @@ public final class CloudBrigadierManager { return IntegerArgumentType.integer(); } }); - this.registerMapping(new TypeToken>() { + this.registerMapping(new TypeToken>() { }, argument -> { final boolean hasMin = argument.getMin() != Integer.MIN_VALUE; final boolean hasMax = argument.getMax() != Integer.MAX_VALUE; @@ -138,7 +139,7 @@ public final class CloudBrigadierManager { } }); /* Map float to FloatArgumentType */ - this.registerMapping(new TypeToken>() { + this.registerMapping(new TypeToken>() { }, argument -> { final boolean hasMin = argument.getMin() != Float.MIN_VALUE; final boolean hasMax = argument.getMax() != Float.MAX_VALUE; @@ -151,7 +152,7 @@ public final class CloudBrigadierManager { } }); /* Map double to DoubleArgumentType */ - this.registerMapping(new TypeToken>() { + this.registerMapping(new TypeToken>() { }, argument -> { final boolean hasMin = argument.getMin() != Double.MIN_VALUE; final boolean hasMax = argument.getMax() != Double.MAX_VALUE; @@ -164,10 +165,10 @@ public final class CloudBrigadierManager { } }); /* Map boolean to BoolArgumentType */ - this.registerMapping(new TypeToken>() { + this.registerMapping(new TypeToken>() { }, argument -> BoolArgumentType.bool()); /* Map String properly to StringArgumentType */ - this.registerMapping(new TypeToken>() { + this.registerMapping(new TypeToken>() { }, argument -> { switch (argument.getStringMode()) { case QUOTED: @@ -189,7 +190,7 @@ public final class CloudBrigadierManager { * @param cloud argument type * @param Brigadier argument type value */ - public , O> void registerMapping(@Nonnull final TypeToken argumentType, + public , O> void registerMapping(@Nonnull final TypeToken argumentType, @Nonnull final Function> mapper) { this.mappers.put(argumentType.getRawType(), mapper); @@ -206,33 +207,25 @@ public final class CloudBrigadierManager { this.defaultArgumentTypeSuppliers.put(clazz, supplier); } - /** - * Get a Brigadier {@link ArgumentType} from a cloud {@link CommandArgument} - * - * @param argumentType cloud argument type - * @param argument cloud argument - * @param cloud argument value type (generic) - * @param cloud argument type (generic) - * @return Brigadier argument type - */ @Nullable @SuppressWarnings("all") - private > Pair, Boolean> getArgument( + private > Pair, Boolean> getArgument( + @Nonnull final Class valueType, @Nonnull final TypeToken argumentType, @Nonnull final K argument) { - final CommandArgument commandArgument = (CommandArgument) argument; + final ArgumentParser commandArgument = (ArgumentParser) argument; Function function = this.mappers.get(argumentType.getRawType()); if (function == null) { - return this.createDefaultMapper(commandArgument); + return this.createDefaultMapper(valueType, commandArgument); } - return new Pair<>((ArgumentType) function.apply(commandArgument), !argument.getValueType().equals(String.class)); + return new Pair<>((ArgumentType) function.apply(commandArgument), !(argument instanceof StringArgument.StringParser)); } @Nonnull - private > Pair, Boolean> createDefaultMapper( - @Nonnull final CommandArgument - argument) { - final Supplier> argumentTypeSupplier = this.defaultArgumentTypeSuppliers.get(argument.getValueType()); + private > Pair, Boolean> createDefaultMapper( + @Nonnull final Class clazz, + @Nonnull final ArgumentParser argument) { + final Supplier> argumentTypeSupplier = this.defaultArgumentTypeSuppliers.get(clazz); if (argumentTypeSupplier != null) { return new Pair<>(argumentTypeSupplier.get(), true); } @@ -306,8 +299,9 @@ public final class CloudBrigadierManager { .requires(sender -> permissionChecker.test(sender, root.getNodeMeta().getOrDefault("permission", ""))) .executes(executor); } else { - final Pair, Boolean> pair = this.getArgument(TypeToken.of(root.getValue().getClass()), - root.getValue()); + final Pair, Boolean> pair = this.getArgument(root.getValue().getValueType(), + TypeToken.of(root.getValue().getParser().getClass()), + root.getValue().getParser()); final SuggestionProvider provider = pair.getRight() ? null : suggestionProvider; argumentBuilder = RequiredArgumentBuilder .argument(root.getValue().getName(), (ArgumentType) pair.getLeft()) diff --git a/cloud-minecraft/cloud-bukkit-test/src/main/java/com/intellectualsites/commands/BukkitTest.java b/cloud-minecraft/cloud-bukkit-test/src/main/java/com/intellectualsites/commands/BukkitTest.java index 486830f2..2ccce983 100644 --- a/cloud-minecraft/cloud-bukkit-test/src/main/java/com/intellectualsites/commands/BukkitTest.java +++ b/cloud-minecraft/cloud-bukkit-test/src/main/java/com/intellectualsites/commands/BukkitTest.java @@ -74,13 +74,16 @@ public final class BukkitTest extends JavaPlugin { Function.identity(), Function.identity() ); + + ((PaperCommandManager) mgr).registerBrigadier(); + final AnnotationParser annotationParser = new AnnotationParser<>(mgr, CommandSender.class, p -> BukkitCommandMetaBuilder.builder().withDescription(p.get(StandardParameters.DESCRIPTION, "No description")).build()); annotationParser.parse(this); //noinspection all - ((PaperCommandManager) mgr).registerBrigadier(); + mgr.command(mgr.commandBuilder("gamemode", this.metaWithDescription("Your ugli"), "gajmöde") .argument(EnumArgument.required(GameMode.class, "gamemode")) .argument(StringArgument.newBuilder("player") @@ -99,8 +102,8 @@ public final class BukkitTest extends JavaPlugin { .setGameMode(c.get("gamemode") .orElse(GameMode.SURVIVAL))) .build()) - .command(mgr.commandBuilder("kenny") - .literal("sux") + .command(mgr.commandBuilder("kenny", "k") + .literal("sux", "s") .argument(IntegerArgument .newBuilder("perc") .withMin(PERC_MIN).withMax(PERC_MAX).build()) @@ -174,7 +177,7 @@ public final class BukkitTest extends JavaPlugin { @CommandMethod(value = "annotation|a [number]", permission = "some.permission.node") private void annotatedCommand(@Nonnull final Player player, @Argument("input") @Completions("one,two,duck") @Nonnull final String input, - @Argument("number") @Range(max = "100") final int number) { + @Argument("number") @Range(min = "10", max = "100") final int number) { player.sendMessage(ChatColor.GOLD + "Your input was: " + ChatColor.AQUA + input + ChatColor.GREEN + " (" + number + ")"); } 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 370736ac..c20de02e 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 @@ -25,7 +25,6 @@ package com.intellectualsites.commands.bukkit; import com.intellectualsites.commands.Command; import com.intellectualsites.commands.arguments.CommandArgument; -import com.intellectualsites.commands.arguments.StaticArgument; import com.intellectualsites.commands.exceptions.ArgumentParseException; import com.intellectualsites.commands.exceptions.InvalidCommandSenderException; import com.intellectualsites.commands.exceptions.InvalidSyntaxException; @@ -51,13 +50,15 @@ final class BukkitCommand extends org.bukkit.command.Command implements Plugi private final Command cloudCommand; @SuppressWarnings("unchecked") - BukkitCommand(@Nonnull final Command cloudCommand, + BukkitCommand(@Nonnull final String label, + @Nonnull final List aliases, + @Nonnull final Command cloudCommand, @Nonnull final CommandArgument command, @Nonnull final BukkitCommandManager manager) { - super(command.getName(), + super(label, cloudCommand.getCommandMeta().getOrDefault("description", ""), "", - ((StaticArgument) command).getAlternativeAliases()); + aliases); this.command = command; this.manager = manager; this.cloudCommand = cloudCommand; @@ -74,48 +75,52 @@ final class BukkitCommand extends org.bukkit.command.Command implements Plugi 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(); - } - } - })); + 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; } diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/bukkit/BukkitCommandManager.java b/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/bukkit/BukkitCommandManager.java index 35902233..ee636f9f 100644 --- a/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/bukkit/BukkitCommandManager.java +++ b/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/bukkit/BukkitCommandManager.java @@ -50,6 +50,8 @@ public class BukkitCommandManager extends CommandManager { private final Function commandSenderMapper; private final Function backwardsCommandSenderMapper; + private boolean splitAliases = false; + /** * Construct a new Bukkit command manager * @@ -113,4 +115,12 @@ public class BukkitCommandManager extends CommandManager { return this.backwardsCommandSenderMapper.apply(sender).hasPermission(permission); } + protected final void setSplitAliases(final boolean value) { + this.splitAliases = value; + } + + protected final boolean getSplitAliases() { + return this.splitAliases; + } + } diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/bukkit/BukkitPluginRegistrationHandler.java b/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/bukkit/BukkitPluginRegistrationHandler.java index cbac2f8d..b66225b6 100644 --- a/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/bukkit/BukkitPluginRegistrationHandler.java +++ b/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/bukkit/BukkitPluginRegistrationHandler.java @@ -25,6 +25,7 @@ package com.intellectualsites.commands.bukkit; import com.intellectualsites.commands.Command; import com.intellectualsites.commands.arguments.CommandArgument; +import com.intellectualsites.commands.arguments.StaticArgument; import com.intellectualsites.commands.internal.CommandRegistrationHandler; import org.bukkit.Bukkit; import org.bukkit.command.CommandMap; @@ -34,7 +35,9 @@ import org.bukkit.help.GenericCommandHelpTopic; import javax.annotation.Nonnull; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; final class BukkitPluginRegistrationHandler implements CommandRegistrationHandler { @@ -74,14 +77,37 @@ final class BukkitPluginRegistrationHandler implements CommandRegistrationHan } else { label = commandArgument.getName(); } + + @SuppressWarnings("unchecked") final List aliases = ((StaticArgument) commandArgument).getAlternativeAliases(); + @SuppressWarnings("unchecked") final BukkitCommand bukkitCommand = new BukkitCommand<>( + commandArgument.getName(), + (this.bukkitCommandManager.getSplitAliases() ? Collections.emptyList() : aliases), (Command) command, (CommandArgument) commandArgument, this.bukkitCommandManager); this.registeredCommands.put(commandArgument, bukkitCommand); this.commandMap.register(commandArgument.getName(), this.bukkitCommandManager.getOwningPlugin().getName().toLowerCase(), bukkitCommand); + + if (this.bukkitCommandManager.getSplitAliases()) { + for (final String alias : aliases) { + if (!this.bukkitCommands.containsKey(alias)) { + @SuppressWarnings("unchecked") final BukkitCommand aliasCommand = new BukkitCommand<>( + alias, + Collections.emptyList(), + (Command) command, + (CommandArgument) commandArgument, + this.bukkitCommandManager); + this.commandMap.register(alias, this.bukkitCommandManager.getOwningPlugin() + .getName().toLowerCase(), + bukkitCommand); + } + } + } + return true; } + } diff --git a/cloud-minecraft/cloud-paper/src/main/java/com/intellectualsites/commands/paper/PaperCommandManager.java b/cloud-minecraft/cloud-paper/src/main/java/com/intellectualsites/commands/paper/PaperCommandManager.java index e0fc237c..0c78a9aa 100644 --- a/cloud-minecraft/cloud-paper/src/main/java/com/intellectualsites/commands/paper/PaperCommandManager.java +++ b/cloud-minecraft/cloud-paper/src/main/java/com/intellectualsites/commands/paper/PaperCommandManager.java @@ -72,6 +72,7 @@ public class PaperCommandManager final PaperBrigadierListener brigadierListener = new PaperBrigadierListener<>(this); Bukkit.getPluginManager().registerEvents(brigadierListener, this.getOwningPlugin()); + this.setSplitAliases(true); return brigadierListener; } catch (final Throwable e) { this.getOwningPlugin().getLogger().severe("Failed to register Brigadier listener"); 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 17b43e78..048193eb 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 @@ -81,7 +81,7 @@ public class CloudVelocityTest { @CommandMethod("test [str]") private void testCommand(@Nonnull @Argument("str") final String string, @Nonnull final CommandSource source, - @Argument("num") @Range(max = "33") final int num) { + @Argument("num") @Range(min = "10", max = "33") final int num) { source.sendMessage(TextComponent.builder() .append("You wrote: ", NamedTextColor.GOLD) .append(string, NamedTextColor.LIGHT_PURPLE)