From 7b0238cad9c371c1cd87400837778b33b80e96f0 Mon Sep 17 00:00:00 2001 From: Fern <15272073+Fernthedev@users.noreply.github.com> Date: Fri, 6 Dec 2019 21:32:04 -0400 Subject: [PATCH] - Version Bump to Beta 2 - UniversalCommand argument API now added (Argument category not tested yet) --- .../modules/com.github.fernthedev.FernAPI.iml | 2 +- .../com.github.fernthedev.FernAPI.main.iml | 72 ++++---- .../com.github.fernthedev.FernAPI.test.iml | 2 +- build.gradle | 2 +- .../universal/api/UniversalCommand.java | 170 +++++++++++++++++- 5 files changed, 204 insertions(+), 44 deletions(-) diff --git a/.idea/modules/com.github.fernthedev.FernAPI.iml b/.idea/modules/com.github.fernthedev.FernAPI.iml index 1eebf09..680d9b3 100644 --- a/.idea/modules/com.github.fernthedev.FernAPI.iml +++ b/.idea/modules/com.github.fernthedev.FernAPI.iml @@ -1,5 +1,5 @@ - + diff --git a/.idea/modules/com.github.fernthedev.FernAPI.main.iml b/.idea/modules/com.github.fernthedev.FernAPI.main.iml index 648e86c..3e6d03b 100644 --- a/.idea/modules/com.github.fernthedev.FernAPI.main.iml +++ b/.idea/modules/com.github.fernthedev.FernAPI.main.iml @@ -1,5 +1,5 @@ - + @@ -27,52 +27,52 @@ - - - - - - - - - - - - - - - + + + - - - - - - - + + + + + + + + + + + + - + + + + - - - - - + + + + + + - + + + - - - + + + - - - + + + + \ No newline at end of file diff --git a/.idea/modules/com.github.fernthedev.FernAPI.test.iml b/.idea/modules/com.github.fernthedev.FernAPI.test.iml index 1f53fd0..0cc1e29 100644 --- a/.idea/modules/com.github.fernthedev.FernAPI.test.iml +++ b/.idea/modules/com.github.fernthedev.FernAPI.test.iml @@ -1,5 +1,5 @@ - + diff --git a/build.gradle b/build.gradle index 6d045ff..f96e446 100644 --- a/build.gradle +++ b/build.gradle @@ -55,7 +55,7 @@ repositories { group = 'com.github.fernthedev' -version = '1.9b1' +version = '1.9b2' def developer = "FernTheDev" def MCVersion = "1.14.4" archivesBaseName = "FernAPI" diff --git a/src/main/java/com/github/fernthedev/fernapi/universal/api/UniversalCommand.java b/src/main/java/com/github/fernthedev/fernapi/universal/api/UniversalCommand.java index 6ed8e66..d68f69f 100644 --- a/src/main/java/com/github/fernthedev/fernapi/universal/api/UniversalCommand.java +++ b/src/main/java/com/github/fernthedev/fernapi/universal/api/UniversalCommand.java @@ -5,11 +5,12 @@ import com.github.fernthedev.fernapi.universal.data.chat.ChatColor; import com.github.fernthedev.fernapi.universal.data.chat.TextMessage; import com.google.common.base.Preconditions; -import lombok.AccessLevel; -import lombok.Data; -import lombok.RequiredArgsConstructor; +import lombok.*; +import javax.annotation.Nullable; +import java.security.PrivilegedActionException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.logging.Logger; @Data @@ -22,6 +23,18 @@ public abstract class UniversalCommand { private final String[] aliases; + protected List arguments = new ArrayList<>(); + + protected void addArgument(Argument argument, Argument... argumentsArg) { + arguments.add(argument); + arguments.addAll(Arrays.asList(argumentsArg)); + } + + protected void removeArgument(Argument argument) { + arguments.remove(argument); + } + + /** * Construct a new command with no permissions or aliases. * @@ -29,7 +42,7 @@ public abstract class UniversalCommand { */ public UniversalCommand(String name) { - this( name, null ); + this( name, null); } /** @@ -80,7 +93,7 @@ public List suggest(CommandSender source, String[] currentArgs) { * @param possibilities All of the possibilities * @return The auto-complete possibilities */ - public List search(String arg, List possibilities) { + public static List search(String arg, List possibilities) { List newPos = new ArrayList<>(); possibilities.forEach(s -> { if(s.startsWith(arg) || s.contains(arg)) { @@ -90,10 +103,157 @@ public List search(String arg, List possibilities) { return newPos; } + /** + * A shortcut to {@link #handleArguments(CommandSender, List, String[])} for instances + */ + protected ArgumentRunnable handleArguments(CommandSender sender, String[] args) { + return handleArguments(sender, arguments, args); + } + + /** + * + * @param sender The sender to check + * @param arguments The valid arguments to use + * @param args The arguments provided by the sender + * @return The argument runnable that follows the specific criteria: {name of argument, permission if any required} + * + * @throws ArgumentNotFoundException Thrown when the argument from args in index 0 is not matched + * to any arguments in the arguments list. + */ + protected static ArgumentRunnable handleArguments(CommandSender sender, List arguments, String[] args) { + for (Argument argument : arguments) { + if (argument.name.equalsIgnoreCase(args[0]) && + (argument.permission == null || sender.hasPermission(argument.permission) /* If there is a permission required, it will check if sender has it */)) { + return argument.getArgumentRunnable(); + } + } + throw new ArgumentNotFoundException("The argument {" + args[0] + "} could not be found in the list of legal arguments: " + arguments); + } + /** * Called when executing the command * @param sender The source * @param args The arguments provided */ public abstract void execute(CommandSender sender, String[] args); + + @FunctionalInterface + public interface ArgumentRunnable { + void run(CommandSender sender, String[] args); + } + + @Getter + public static class Argument { + + private final String name; + private final ArgumentRunnable argumentRunnable; + private final List innerArguments; + + @Setter + private String permission = null; + + /** + * Used only if ArgumentRunnable is null + * Is used to allow usage of argument as categories into other argument runnables + * + * Example: + * - main + * - foo + * - bar + * - thing + * - another + * - another2 + * - other + * - misc + * + * + * It can also be used as an example to have a hybrid category/argument style + * + * Such as: + * main -> "foo" + * main bar -> "bar" + */ + private static ArgumentRunnable defaultArgument(List argumentRunnables) { + return (sender, args) -> { + String[] argsCopy = new String[args.length - 1]; + + System.arraycopy(args, 1, argsCopy, 0, args.length - 1); + handleArguments(sender, argumentRunnables, args).run(sender, argsCopy); + }; + } + + + /** + * + * @param name The name of the argument + * @param argumentRunnable The code ran when the argument is used + * @param innerArguments Any inner arguments if you wish to use the argument as a category + */ + public Argument(@NonNull String name, @Nullable ArgumentRunnable argumentRunnable, @Nullable Argument... innerArguments) { + this.name = name; + this.innerArguments = Arrays.asList(innerArguments); + + if(argumentRunnable == null) this.argumentRunnable = defaultArgument(this.innerArguments); + else this.argumentRunnable = argumentRunnable; + + } + } + + public static class ArgumentNotFoundException extends IllegalArgumentException { + /** + * Constructs an IllegalArgumentException with no + * detail message. + */ + public ArgumentNotFoundException() { + super(); + } + + /** + * Constructs an IllegalArgumentException with the + * specified detail message. + * + * @param s the detail message. + */ + public ArgumentNotFoundException(String s) { + super(s); + } + + /** + * Constructs a new exception with the specified detail message and + * cause. + * + *

Note that the detail message associated with cause is + * not automatically incorporated in this exception's detail + * message. + * + * @param message the detail message (which is saved for later retrieval + * by the {@link Throwable#getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link Throwable#getCause()} method). (A {@code null} value + * is permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 1.5 + */ + public ArgumentNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + /** + * Constructs a new exception with the specified cause and a detail + * message of {@code (cause==null ? null : cause.toString())} (which + * typically contains the class and detail message of {@code cause}). + * This constructor is useful for exceptions that are little more than + * wrappers for other throwables (for example, {@link + * PrivilegedActionException}). + * + * @param cause the cause (which is saved for later retrieval by the + * {@link Throwable#getCause()} method). (A {@code null} value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 1.5 + */ + public ArgumentNotFoundException(Throwable cause) { + super(cause); + } + } }