aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/cc/polyfrost/oneconfig/utils/commands/CommandManager.java
diff options
context:
space:
mode:
authornextdaydelivery <79922345+nxtdaydelivery@users.noreply.github.com>2022-06-05 10:39:49 +0100
committernextdaydelivery <79922345+nxtdaydelivery@users.noreply.github.com>2022-06-05 10:39:49 +0100
commit17826161c67f6adf5976d7993ac0a229193e2eb6 (patch)
treef4172013d2db0986f0bb123040be1dc5b5823b3d /src/main/java/cc/polyfrost/oneconfig/utils/commands/CommandManager.java
parent087f5404658a1543834f16a89e3436f8399297f6 (diff)
parent72c024213e7c61411ce12f6032f8ef0659408c3a (diff)
downloadOneConfig-17826161c67f6adf5976d7993ac0a229193e2eb6.tar.gz
OneConfig-17826161c67f6adf5976d7993ac0a229193e2eb6.tar.bz2
OneConfig-17826161c67f6adf5976d7993ac0a229193e2eb6.zip
Merge remote-tracking branch 'origin/master'
# Conflicts: # src/main/java/cc/polyfrost/oneconfig/gui/OneConfigGui.java # src/main/java/cc/polyfrost/oneconfig/gui/animations/EaseInOutQuad.java # src/main/java/cc/polyfrost/oneconfig/gui/elements/BasicButton.java # src/main/java/cc/polyfrost/oneconfig/gui/elements/BasicElement.java # src/main/java/cc/polyfrost/oneconfig/gui/elements/ModCard.java # src/main/java/cc/polyfrost/oneconfig/gui/elements/text/NumberInputField.java # src/main/java/cc/polyfrost/oneconfig/lwjgl/image/ImageLoader.java # src/main/java/cc/polyfrost/oneconfig/utils/GuiUtils.java # src/main/java/cc/polyfrost/oneconfig/utils/commands/annotations/Command.java # src/main/java/cc/polyfrost/oneconfig/utils/commands/arguments/ArgumentParser.java
Diffstat (limited to 'src/main/java/cc/polyfrost/oneconfig/utils/commands/CommandManager.java')
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/utils/commands/CommandManager.java288
1 files changed, 168 insertions, 120 deletions
diff --git a/src/main/java/cc/polyfrost/oneconfig/utils/commands/CommandManager.java b/src/main/java/cc/polyfrost/oneconfig/utils/commands/CommandManager.java
index 4a008d3..32bbf5d 100644
--- a/src/main/java/cc/polyfrost/oneconfig/utils/commands/CommandManager.java
+++ b/src/main/java/cc/polyfrost/oneconfig/utils/commands/CommandManager.java
@@ -1,9 +1,12 @@
package cc.polyfrost.oneconfig.utils.commands;
-import cc.polyfrost.oneconfig.libs.universal.ChatColor;
-import cc.polyfrost.oneconfig.libs.universal.UChat;
-import cc.polyfrost.oneconfig.utils.commands.annotations.*;
+import cc.polyfrost.oneconfig.utils.commands.annotations.Command;
+import cc.polyfrost.oneconfig.utils.commands.annotations.Greedy;
+import cc.polyfrost.oneconfig.utils.commands.annotations.Main;
+import cc.polyfrost.oneconfig.utils.commands.annotations.SubCommand;
import cc.polyfrost.oneconfig.utils.commands.arguments.*;
+import gg.essential.universal.ChatColor;
+import gg.essential.universal.UChat;
import net.minecraft.command.CommandBase;
import net.minecraft.command.ICommandSender;
import net.minecraftforge.client.ClientCommandHandler;
@@ -13,7 +16,6 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.util.*;
-import java.util.stream.Collectors;
/**
* Handles the registration of OneConfig commands.
@@ -22,9 +24,9 @@ import java.util.stream.Collectors;
*/
public class CommandManager {
public static final CommandManager INSTANCE = new CommandManager();
- private final HashMap<Class<?>, ArgumentParser<?>> parsers = new HashMap<>();
private static final String NOT_FOUND_TEXT = "Command not found! Type /@ROOT_COMMAND@ help for help.";
private static final String METHOD_RUN_ERROR = "Error while running @ROOT_COMMAND@ method! Please report this to the developer.";
+ private final HashMap<Class<?>, ArgumentParser<?>> parsers = new HashMap<>();
private CommandManager() {
addParser(new StringParser());
@@ -60,22 +62,19 @@ public class CommandManager {
/**
* Registers the provided command.
*
- * @param command The command to register.
+ * @param clazz The command to register as a class.
*/
- public void registerCommand(Object command) {
- Class<?> clazz = command.getClass();
+ public void registerCommand(Class<?> clazz) {
if (clazz.isAnnotationPresent(Command.class)) {
final Command annotation = clazz.getAnnotation(Command.class);
- ArrayList<InternalCommand.InternalCommandInvoker> mainCommandFuncs = new ArrayList<>();
+ final InternalCommand root = new InternalCommand(annotation.value(), annotation.aliases(), annotation.description().trim().isEmpty() ? "Main command for " + annotation.value() : annotation.description(), null);
for (Method method : clazz.getDeclaredMethods()) {
if (method.isAnnotationPresent(Main.class) && method.getParameterCount() == 0) {
- mainCommandFuncs.add(new InternalCommand.InternalCommandInvoker(annotation.value(), annotation.aliases(), method));
+ root.invokers.add(new InternalCommand.InternalCommandInvoker(annotation.value(), annotation.aliases(), method, root));
break;
}
}
-
- final InternalCommand root = new InternalCommand(annotation.value(), annotation.aliases(), annotation.description().trim().isEmpty() ? "Main command for " + annotation.value() : annotation.description(), mainCommandFuncs);
addToInvokers(clazz.getDeclaredClasses(), root);
ClientCommandHandler.instance.registerCommand(new CommandBase() {
@Override
@@ -93,26 +92,57 @@ public class CommandManager {
if (args.length == 0) {
if (!root.invokers.isEmpty()) {
try {
- root.invokers.stream().findFirst().get().method.invoke(null);
+ root.invokers.get(0).method.invoke(null);
} catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException |
ExceptionInInitializerError e) {
+ e.printStackTrace();
UChat.chat(ChatColor.RED.toString() + ChatColor.BOLD + METHOD_RUN_ERROR);
}
}
} else {
if (annotation.helpCommand() && args[0].equalsIgnoreCase("help")) {
- UChat.chat(sendHelpCommand(root));
+ //UChat.chat(sendHelpCommand(root));
} else {
+ List<InternalCommand.InternalCommandInvoker> commands = new ArrayList<>();
+ int depth = 0;
for (InternalCommand command : root.children) {
- String result = runThroughCommands(command, 0, args);
- if (result == null) {
- return;
- } else if (!result.equals(NOT_FOUND_TEXT)) {
- UChat.chat(ChatColor.RED.toString() + ChatColor.BOLD + result.replace("@ROOT_COMMAND@", getCommandName()));
- return;
+ int newDepth = loopThroughCommands(commands, 0, command, args, true);
+ if (newDepth != -1) {
+ depth = newDepth;
+ break;
+ }
+ }
+ System.out.println(depth);
+ System.out.println(commands);
+ if (commands.isEmpty()) {
+ UChat.chat(ChatColor.RED.toString() + ChatColor.BOLD + NOT_FOUND_TEXT.replace("@ROOT_COMMAND@", annotation.value()));
+ } else {
+ List<CustomError> errors = new ArrayList<>();
+ for (InternalCommand.InternalCommandInvoker invoker : commands) {
+ try {
+ List<Object> params = getParametersForInvoker(invoker, depth, args);
+ if (params.size() == 1) {
+ Object first = params.get(0);
+ if (first instanceof CustomError) {
+ errors.add((CustomError) first);
+ continue;
+ }
+ }
+ invoker.method.invoke(null, params.toArray());
+ return;
+ } catch (Exception e) {
+ e.printStackTrace();
+ UChat.chat(ChatColor.RED.toString() + ChatColor.BOLD + METHOD_RUN_ERROR);
+ return;
+ }
+ }
+ if (!errors.isEmpty()) {
+ UChat.chat(ChatColor.RED.toString() + ChatColor.BOLD + "Multiple errors occurred:");
+ for (CustomError error : errors) {
+ UChat.chat(" " + ChatColor.RED + ChatColor.BOLD + error.message);
+ }
}
}
- UChat.chat(ChatColor.RED.toString() + ChatColor.BOLD + NOT_FOUND_TEXT.replace("@ROOT_COMMAND@", getCommandName()));
}
}
}
@@ -121,146 +151,142 @@ public class CommandManager {
public int getRequiredPermissionLevel() {
return -1;
}
- });
- }
- }
- private String sendHelpCommand(InternalCommand root) {
- StringBuilder builder = new StringBuilder();
- builder.append(ChatColor.GOLD.toString() + "Help for " + ChatColor.BOLD + root.name + ChatColor.RESET + ChatColor.GOLD + ":\n");
- builder.append("\n");
- for (InternalCommand command : root.children) {
- runThroughCommandsHelp(root.name, root, builder);
- }
- builder.append("\n" + ChatColor.GOLD + "Aliases: " + ChatColor.BOLD);
- int index = 0;
- for (String alias : root.aliases) {
- ++index;
- builder.append(alias + (index < root.aliases.length ? ", " : ""));
- }
- builder.append("\n");
- return builder.toString();
- }
+ /*/
+ @Override
+ public List<String> addTabCompletionOptions(ICommandSender sender, String[] args, BlockPos pos) {
+ List<InternalCommand.InternalCommandInvoker> commands = new ArrayList<>();
+ int depth = 0;
+ for (InternalCommand command : root.children) {
+ int newDepth = loopThroughCommands(commands, 0, command, args, false);
+ if (newDepth != -1) {
+ depth = newDepth;
+ break;
+ }
+ }
+ System.out.println(depth);
+ System.out.println(commands);
+ if (!commands.isEmpty()) {
+ for (InternalCommand.InternalCommandInvoker invoker : commands) {
+ try {
+ List<Object> params = getParametersForInvoker(invoker, depth, args);
+ invoker.method.invoke(null, params.toArray());
+ return;
+ } catch (Exception ignored) {
- private void runThroughCommandsHelp(String append, InternalCommand command, StringBuilder builder) {
- for (InternalCommand.InternalCommandInvoker invoker : command.invokers) {
- builder.append("\n" + ChatColor.GOLD + "/" + append + " " + command.name);
- for (Parameter parameter : invoker.method.getParameters()) {
- String name = parameter.getName();
- if (parameter.isAnnotationPresent(Name.class)) {
- name = parameter.getAnnotation(Name.class).value();
+ }
+ }
+ }
}
- builder.append(" <" + name + ">");
- }
- if (!command.description.trim().isEmpty()) {
- builder.append(": " + ChatColor.BOLD + command.description);
- }
- }
- for (InternalCommand subCommand : command.children) {
- runThroughCommandsHelp(append + " " + command.name, subCommand, builder);
+
+ */
+ });
}
}
- private String runThroughCommands(InternalCommand command, int layer, String[] args) {
- int newLayer = layer + 1;
- if (command.isEqual(args[layer]) && !command.invokers.isEmpty()) {
- Set<InternalCommand.InternalCommandInvoker> invokers = command.invokers.stream().filter(invoker -> newLayer == args.length - invoker.parameterTypes.length).sorted(Comparator.comparingInt((a) -> a.method.getAnnotation(Main.class).priority())).collect(Collectors.toSet());
- if (!invokers.isEmpty()) {
- for (InternalCommand.InternalCommandInvoker invoker : invokers) {
- try {
- String a = tryInvoker(invoker, newLayer, args);
- if (a == null) {
- return null;
- } else if (a.contains(METHOD_RUN_ERROR)) {
- return a;
- }
- } catch (Exception ignored) {
-
- }
- }
- } else {
- for (InternalCommand subCommand : command.children) {
- String result = runThroughCommands(subCommand, newLayer, args);
- if (result == null) {
- return null;
- } else if (!result.equals(NOT_FOUND_TEXT)) {
- return result;
+ private List<Object> getParametersForInvoker(InternalCommand.InternalCommandInvoker invoker, int depth, String[] args) {
+ List<Object> parameters = new ArrayList<>();
+ int processed = depth;
+ int currentParam = 0;
+ while (processed < args.length) {
+ Parameter param = invoker.method.getParameters()[currentParam];
+ if (param.isAnnotationPresent(Greedy.class) && currentParam + 1 != invoker.method.getParameterCount()) {
+ return Collections.singletonList(new CustomError("Parsing failed: Greedy parameter must be the last one."));
+ }
+ ArgumentParser<?> parser = parsers.get(param.getType());
+ if (parser == null) {
+ return Collections.singletonList(new CustomError("No parser for " + invoker.method.getParameterTypes()[currentParam].getSimpleName() + "! Please report this to the mod author."));
+ }
+ try {
+ Arguments arguments = new Arguments(Arrays.copyOfRange(args, processed, args.length), param.isAnnotationPresent(Greedy.class));
+ try {
+ Object a = parser.parse(arguments);
+ if (a != null) {
+ parameters.add(a);
+ processed += arguments.getPosition();
+ currentParam++;
+ } else {
+ return Collections.singletonList(new CustomError("Failed to parse " + param.getType().getSimpleName() + "! Please report this to the mod author."));
}
+ } catch (Exception e) {
+ return Collections.singletonList(new CustomError("A " + e.getClass().getSimpleName() + " has occured while try to parse " + param.getType().getSimpleName() + "! Please report this to the mod author."));
}
+ } catch (Exception e) {
+ return Collections.singletonList(new CustomError("A " + e.getClass().getSimpleName() + " has occured while try to parse " + param.getType().getSimpleName() + "! Please report this to the mod author."));
}
}
- return NOT_FOUND_TEXT;
+ return parameters;
}
- private String tryInvoker(InternalCommand.InternalCommandInvoker invoker, int newLayer, String[] args) {
- try {
- ArrayList<Object> params = new ArrayList<>();
- int processed = newLayer;
- int currentParam = 0;
- while (processed < args.length) {
- Parameter param = invoker.method.getParameters()[currentParam];
- if (param.isAnnotationPresent(Greedy.class) && currentParam + 1 != invoker.method.getParameterCount()) {
- return "Parsing failed: Greedy parameter must be the last one.";
+ private int loopThroughCommands(List<InternalCommand.InternalCommandInvoker> commands, int depth, InternalCommand command, String[] args, boolean checkParams) {
+ int nextDepth = depth + 1;
+ if (command.isEqual(args[depth])) {
+ for (InternalCommand child : command.children) {
+ if (args.length > nextDepth && child.isEqual(args[nextDepth])) {
+ int result = loopThroughCommands(commands, nextDepth, child, args, checkParams);
+ if (result != -1) {
+ return result;
+ }
}
- ArgumentParser<?> parser = parsers.get(param.getType());
- if (parser == null) {
- return "No parser for " + invoker.method.getParameterTypes()[currentParam].getSimpleName() + "! Please report this to the mod author.";
+ }
+ boolean added = false;
+ for (InternalCommand.InternalCommandInvoker invoker : command.invokers) {
+ if (!checkParams || args.length - nextDepth == invoker.method.getParameterCount()) {
+ commands.add(invoker);
+ added = true;
}
- try {
- Arguments arguments = new Arguments(Arrays.copyOfRange(args, processed, args.length), param.isAnnotationPresent(Greedy.class));
- try {
- Object a = parser.parse(arguments);
- if (a != null) {
- params.add(a);
- processed += arguments.getPosition();
- currentParam++;
- } else {
- return "Failed to parse " + param.getType().getSimpleName() + "! Please report this to the mod author.";
- }
- } catch (Exception e) {
- return "A " + e.getClass().getSimpleName() + " has occured while try to parse " + param.getType().getSimpleName() + "! Please report this to the mod author.";
- }
- } catch (Exception e) {
- return "A " + e.getClass().getSimpleName() + " has occured while try to parse " + param.getType().getSimpleName() + "! Please report this to the mod author.";
+ }
+ if (added) {
+ return nextDepth;
+ }
+ } else {
+ for (InternalCommand child : command.children) {
+ int childDepth = loopThroughCommands(commands, nextDepth, child, args, checkParams);
+ if (childDepth != -1) {
+ return childDepth;
}
}
- invoker.method.invoke(null, params.toArray());
- return null;
- } catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException |
- ExceptionInInitializerError e) {
- return ChatColor.RED.toString() + ChatColor.BOLD + METHOD_RUN_ERROR;
}
+ return -1;
}
private void addToInvokers(Class<?>[] classes, InternalCommand parent) {
for (Class<?> clazz : classes) {
if (clazz.isAnnotationPresent(SubCommand.class)) {
SubCommand annotation = clazz.getAnnotation(SubCommand.class);
- ArrayList<InternalCommand.InternalCommandInvoker> mainMethods = new ArrayList<>();
+ InternalCommand command = new InternalCommand(annotation.value(), annotation.aliases(), annotation.description(), parent);
for (Method method : clazz.getDeclaredMethods()) {
if (method.isAnnotationPresent(Main.class)) {
- mainMethods.add(new InternalCommand.InternalCommandInvoker(annotation.value(), annotation.aliases(), method));
+ command.invokers.add(new InternalCommand.InternalCommandInvoker(annotation.value(), annotation.aliases(), method, command));
}
}
- InternalCommand command = new InternalCommand(annotation.value(), annotation.aliases(), annotation.description(), mainMethods);
parent.children.add(command);
addToInvokers(clazz.getDeclaredClasses(), command);
}
}
}
+ private static class CustomError {
+ public String message;
+
+ public CustomError(String message) {
+ this.message = message;
+ }
+ }
+
private static class InternalCommand {
public final String name;
public final String[] aliases;
public final String description;
- public final ArrayList<InternalCommandInvoker> invokers;
+ public final ArrayList<InternalCommandInvoker> invokers = new ArrayList<>();
+ public final InternalCommand parent;
public final ArrayList<InternalCommand> children = new ArrayList<>();
- public InternalCommand(String name, String[] aliases, String description, ArrayList<InternalCommandInvoker> invokers) {
+ public InternalCommand(String name, String[] aliases, String description, InternalCommand parent) {
this.name = name;
this.aliases = aliases;
- this.invokers = invokers;
this.description = description;
+ this.parent = parent;
}
public boolean isEqual(String name) {
@@ -276,13 +302,24 @@ public class CommandManager {
return false;
}
+ @Override
+ public String toString() {
+ return "InternalCommand{" +
+ "name='" + name + '\'' +
+ ", aliases=" + Arrays.toString(aliases) +
+ ", description='" + description + '\'' +
+ ", invokers=" + invokers +
+ '}';
+ }
+
public static class InternalCommandInvoker {
public final String name;
public final String[] aliases;
public final Method method;
public final Parameter[] parameterTypes;
+ public final InternalCommand parent;
- public InternalCommandInvoker(String name, String[] aliases, Method method) {
+ public InternalCommandInvoker(String name, String[] aliases, Method method, InternalCommand parent) {
if (!Modifier.isStatic(method.getModifiers())) {
throw new IllegalArgumentException("All command methods must be static!");
}
@@ -290,10 +327,21 @@ public class CommandManager {
this.aliases = aliases;
this.method = method;
this.parameterTypes = method.getParameters().clone();
+ this.parent = parent;
if (Modifier.isPrivate(method.getModifiers()) || Modifier.isProtected(method.getModifiers())) {
method.setAccessible(true);
}
}
+
+ @Override
+ public String toString() {
+ return "InternalCommandInvoker{" +
+ "name='" + name + '\'' +
+ ", aliases=" + Arrays.toString(aliases) +
+ ", method=" + method +
+ ", parameterTypes=" + Arrays.toString(parameterTypes) +
+ '}';
+ }
}
}
}