From 76bd79614ccd09c14e06b980ae7e95fcd597839a Mon Sep 17 00:00:00 2001 From: willkroboth <46540330+willkroboth@users.noreply.github.com> Date: Tue, 23 Aug 2022 13:06:42 -0400 Subject: [PATCH] Address #22 - Overhauls command definition system Change ConfigCommandsBuilder to CommandTreeBuilder Add ArgumentTreeBuilder for handling arguments Replace ConfigCommandExecutor with ExecutesBuilder for handling command execution Add FunctionLines package for handling executes parsing and running Moved InvalidExpressionCommand and its subclasses to package Exceptions.FunctionSyntax Add classes CompilerState and InterpreterState to hold parsing and execution information Change method InternalArgument#addArgument to InternalArgument#createArgument Temporarily disabled ReloadCommandHandler and BuildCommandHandler --- .../ConfigCommands/ConfigCommandsHandler.java | 9 +- .../FunctionSyntax/InvalidDoCommand.java | 7 - .../InvalidExpressionCommand.java | 9 - .../FunctionSyntax/InvalidFunctionLine.java | 9 + .../FunctionSyntax/InvalidGotoCommand.java | 2 +- .../FunctionSyntax/InvalidIfCommand.java | 2 +- .../FunctionSyntax/InvalidReturnCommand.java | 2 +- .../FunctionSyntax/InvalidRunExpression.java | 7 + .../FunctionSyntax/InvalidSetCommand.java | 7 - .../FunctionSyntax/InvalidSetVariable.java | 7 + .../Exceptions/IncorrectArgumentKey.java | 10 +- .../HelperClasses/DebuggableState.java | 5 + .../AddThisArgumentConsumer.java | 17 - .../InternalArguments/InternalArgument.java | 58 +- .../InternalArrayListArgument.java | 7 + .../InternalBooleanArgument.java | 18 +- .../InternalCommandSenderArgument.java | 6 + .../InternalIntegerArgument.java | 72 +- .../InternalStringArgument.java | 71 +- .../InternalVoidArgument.java | 7 + .../ArgumentTreeBuilder.java | 84 + .../CommandTreeBuilder.java | 164 ++ .../RegisteredCommands/CompilerState.java | 117 ++ .../ConfigCommandBuilder.java | 491 ------ .../ConfigCommandExecutor.java | 262 --- .../RegisteredCommands/ExecutesBuilder.java | 74 + .../RegisteredCommands/Expression.java | 61 +- .../FunctionLines/BranchIf.java | 104 ++ .../FunctionLines/FunctionLine.java | 59 + .../FunctionLines/Goto.java | 70 + .../FunctionLines/Return.java | 56 + .../FunctionLines/RunCommand.java | 118 ++ .../FunctionLines/RunExpression.java | 44 + .../FunctionLines/SetVariable.java | 108 ++ .../RegisteredCommands/FunctionLines/Tag.java | 38 + .../RegisteredCommands/InterpreterState.java | 179 ++ .../SystemCommands/BuildCommandHandler.java | 1536 ++++++++--------- .../SystemCommands/ReloadCommandHandler.java | 192 +-- .../SystemCommands/SystemCommandHandler.java | 4 +- .../src/main/resources/config.yml | 14 +- 40 files changed, 2284 insertions(+), 1823 deletions(-) delete mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidDoCommand.java delete mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidExpressionCommand.java create mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidFunctionLine.java create mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidRunExpression.java delete mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidSetCommand.java create mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidSetVariable.java create mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/HelperClasses/DebuggableState.java delete mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/HelperClasses/AddThisArgumentConsumer.java create mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/ArgumentTreeBuilder.java create mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/CommandTreeBuilder.java create mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/CompilerState.java delete mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/ConfigCommandBuilder.java delete mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/ConfigCommandExecutor.java create mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/ExecutesBuilder.java create mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/BranchIf.java create mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/FunctionLine.java create mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/Goto.java create mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/Return.java create mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/RunCommand.java create mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/RunExpression.java create mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/SetVariable.java create mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/Tag.java create mode 100644 ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/InterpreterState.java diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/ConfigCommandsHandler.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/ConfigCommandsHandler.java index 006abe3..777104b 100644 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/ConfigCommandsHandler.java +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/ConfigCommandsHandler.java @@ -1,11 +1,12 @@ package me.willkroboth.ConfigCommands; import me.willkroboth.ConfigCommands.HelperClasses.ConfigCommandAddOn; -import me.willkroboth.ConfigCommands.RegisteredCommands.ConfigCommandBuilder; +import me.willkroboth.ConfigCommands.HelperClasses.DebuggableState; import me.willkroboth.ConfigCommands.HelperClasses.IndentedLogger; import me.willkroboth.ConfigCommands.InternalArguments.InternalArgument; import me.willkroboth.ConfigCommands.NMS.NMS; import me.willkroboth.ConfigCommands.NMS.VersionHandler; +import me.willkroboth.ConfigCommands.RegisteredCommands.CommandTreeBuilder; import me.willkroboth.ConfigCommands.SystemCommands.SystemCommandHandler; import org.bukkit.configuration.file.FileConfiguration; @@ -71,6 +72,10 @@ public static void logDebug(boolean debugMode, String message, Object... objects logger.logDebug(debugMode, message, objects); } + public static void logDebug(DebuggableState state, String message, Object... objects) { + logger.logDebug(state.isDebug(), message, objects); + } + public static void logWarning(String message, Object... objects) { logger.warn(message, objects); } @@ -95,7 +100,7 @@ public static void enable(ConfigCommands plugin) { InternalArgument.createFunctionMaps(); - ConfigCommandBuilder.registerCommandsFromConfig(getConfigFile().getConfigurationSection("commands"), debugMode); + CommandTreeBuilder.registerCommandsFromConfig(getConfigFile().getConfigurationSection("commands"), debugMode); SystemCommandHandler.setUpCommands(plugin); diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidDoCommand.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidDoCommand.java deleted file mode 100644 index 73fbf17..0000000 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidDoCommand.java +++ /dev/null @@ -1,7 +0,0 @@ -package me.willkroboth.ConfigCommands.Exceptions.FunctionSyntax; - -public class InvalidDoCommand extends InvalidExpressionCommand { - public InvalidDoCommand(String arg, String reason) { - super("do", arg, reason); - } -} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidExpressionCommand.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidExpressionCommand.java deleted file mode 100644 index 192907b..0000000 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidExpressionCommand.java +++ /dev/null @@ -1,9 +0,0 @@ -package me.willkroboth.ConfigCommands.Exceptions.FunctionSyntax; - -import me.willkroboth.ConfigCommands.Exceptions.RegistrationException; - -public class InvalidExpressionCommand extends RegistrationException { - public InvalidExpressionCommand(String expression, String arg, String reason) { - super("Invalid " + expression + " command: \"" + arg + "\". " + reason); - } -} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidFunctionLine.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidFunctionLine.java new file mode 100644 index 0000000..1dcf096 --- /dev/null +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidFunctionLine.java @@ -0,0 +1,9 @@ +package me.willkroboth.ConfigCommands.Exceptions.FunctionSyntax; + +import me.willkroboth.ConfigCommands.Exceptions.RegistrationException; + +public class InvalidFunctionLine extends RegistrationException { + public InvalidFunctionLine(String name, String arg, String reason) { + super("Invalid " + name + " command: \"" + arg + "\". " + reason); + } +} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidGotoCommand.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidGotoCommand.java index 17fde8d..90b4e90 100644 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidGotoCommand.java +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidGotoCommand.java @@ -1,6 +1,6 @@ package me.willkroboth.ConfigCommands.Exceptions.FunctionSyntax; -public class InvalidGotoCommand extends InvalidExpressionCommand { +public class InvalidGotoCommand extends InvalidFunctionLine { public InvalidGotoCommand(String arg, String reason) { super("goto", arg, reason); } diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidIfCommand.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidIfCommand.java index 7dd06ec..ca13331 100644 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidIfCommand.java +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidIfCommand.java @@ -1,6 +1,6 @@ package me.willkroboth.ConfigCommands.Exceptions.FunctionSyntax; -public class InvalidIfCommand extends InvalidExpressionCommand { +public class InvalidIfCommand extends InvalidFunctionLine { public InvalidIfCommand(String arg, String reason) { super("if", arg, reason); } diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidReturnCommand.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidReturnCommand.java index e13edfb..311a487 100644 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidReturnCommand.java +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidReturnCommand.java @@ -1,6 +1,6 @@ package me.willkroboth.ConfigCommands.Exceptions.FunctionSyntax; -public class InvalidReturnCommand extends InvalidExpressionCommand { +public class InvalidReturnCommand extends InvalidFunctionLine { public InvalidReturnCommand(String arg, String reason) { super("return", arg, reason); } diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidRunExpression.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidRunExpression.java new file mode 100644 index 0000000..75b9598 --- /dev/null +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidRunExpression.java @@ -0,0 +1,7 @@ +package me.willkroboth.ConfigCommands.Exceptions.FunctionSyntax; + +public class InvalidRunExpression extends InvalidFunctionLine { + public InvalidRunExpression(String arg, String reason) { + super("do", arg, reason); + } +} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidSetCommand.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidSetCommand.java deleted file mode 100644 index fda581b..0000000 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidSetCommand.java +++ /dev/null @@ -1,7 +0,0 @@ -package me.willkroboth.ConfigCommands.Exceptions.FunctionSyntax; - -public class InvalidSetCommand extends InvalidExpressionCommand { - public InvalidSetCommand(String arg, String reason) { - super("set", arg, reason); - } -} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidSetVariable.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidSetVariable.java new file mode 100644 index 0000000..0f3898d --- /dev/null +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/FunctionSyntax/InvalidSetVariable.java @@ -0,0 +1,7 @@ +package me.willkroboth.ConfigCommands.Exceptions.FunctionSyntax; + +public class InvalidSetVariable extends InvalidFunctionLine { + public InvalidSetVariable(String arg, String reason) { + super("set", arg, reason); + } +} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/IncorrectArgumentKey.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/IncorrectArgumentKey.java index 72e6a88..11e7ecf 100644 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/IncorrectArgumentKey.java +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/Exceptions/IncorrectArgumentKey.java @@ -1,15 +1,7 @@ package me.willkroboth.ConfigCommands.Exceptions; public class IncorrectArgumentKey extends RegistrationException { - public IncorrectArgumentKey(String arg, String key) { - super("Command has invalid argument: " + arg + " for key \"" + key + "\"."); - } - public IncorrectArgumentKey(String arg, String key, String reason) { - super("Command has invalid argument: " + arg + " for key \"" + key + "\". " + reason); - } - - public IncorrectArgumentKey(String arg, boolean ignored, String reason){ - super("Command has invalid argument: " + arg + ". " + reason); + super("Command has invalid argument: " + arg + " with key \"" + key + "\". " + reason); } } diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/HelperClasses/DebuggableState.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/HelperClasses/DebuggableState.java new file mode 100644 index 0000000..f8f7089 --- /dev/null +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/HelperClasses/DebuggableState.java @@ -0,0 +1,5 @@ +package me.willkroboth.ConfigCommands.HelperClasses; + +public interface DebuggableState { + boolean isDebug(); +} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/HelperClasses/AddThisArgumentConsumer.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/HelperClasses/AddThisArgumentConsumer.java deleted file mode 100644 index c517a64..0000000 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/HelperClasses/AddThisArgumentConsumer.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.willkroboth.ConfigCommands.InternalArguments.HelperClasses; - -import dev.jorel.commandapi.CommandAPICommand; -import me.willkroboth.ConfigCommands.Exceptions.IncorrectArgumentKey; -import me.willkroboth.ConfigCommands.InternalArguments.InternalArgument; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -@FunctionalInterface -public interface AddThisArgumentConsumer { - void add(Map arg, CommandAPICommand command, String name, - ArrayList argument_keys, - HashMap> argument_variable_classes, - boolean debugMode) throws IncorrectArgumentKey; -} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalArgument.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalArgument.java index aba925a..312837b 100644 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalArgument.java +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalArgument.java @@ -1,6 +1,6 @@ package me.willkroboth.ConfigCommands.InternalArguments; -import dev.jorel.commandapi.CommandAPICommand; +import dev.jorel.commandapi.arguments.Argument; import me.willkroboth.ConfigCommands.ConfigCommandsHandler; import me.willkroboth.ConfigCommands.Exceptions.IncorrectArgumentKey; import me.willkroboth.ConfigCommands.Functions.Definition; @@ -8,9 +8,8 @@ import me.willkroboth.ConfigCommands.Functions.FunctionCreator; import me.willkroboth.ConfigCommands.Functions.NonGenericVarargs.*; import me.willkroboth.ConfigCommands.Functions.StaticFunction; -import me.willkroboth.ConfigCommands.RegisteredCommands.Expression; -import me.willkroboth.ConfigCommands.InternalArguments.HelperClasses.AddThisArgumentConsumer; import me.willkroboth.ConfigCommands.InternalArguments.HelperClasses.AllInternalArguments; +import me.willkroboth.ConfigCommands.RegisteredCommands.Expression; import org.reflections.Reflections; import org.reflections.util.ConfigurationBuilder; @@ -103,7 +102,7 @@ public static Map getAliases(String name, Map out = new HashMap<>(); for(Definition definition: functions.keySet()){ if(definition.getName().equals(name) || targets.contains(functions.get(definition))){ @@ -185,7 +184,7 @@ public static String getStaticParameterString(Map al } public static Set getArgumentTypes(){ - return argumentMap.keySet(); + return typeMap.keySet(); } // registering subclasses @@ -227,7 +226,7 @@ public static void registerSetOfInternalArguments(Set argumentMap = new HashMap<>(); + private static final Map typeMap = new HashMap<>(); private static void registerInternalArgument(Class clazz, String pluginName, boolean debugMode, Logger logger){ if(clazz.isAssignableFrom(InternalVoidArgument.class)) return; @@ -251,7 +250,7 @@ private static void registerInternalArgument(Class c if(type == null){ if(debugMode) logger.info(clazz + " gave null typeTag. It will not be able to be used as a command argument"); } else { - argumentMap.put(type, object::addArgument); + typeMap.put(type, object); } } @@ -336,28 +335,20 @@ public static String formatArgumentName(String name){ return name; } - public static void addArgument(Map arg, CommandAPICommand command, - ArrayList argument_keys, - HashMap> argument_variable_classes, - boolean localDebug) - throws IncorrectArgumentKey{ - String name = (String) arg.get("name"); - if(name == null) throw new IncorrectArgumentKey(arg.toString(), "name", "Key not found."); - name = formatArgumentName(name); - ConfigCommandsHandler.logDebug(localDebug, "Arg has name: " + name); - if(argument_keys.contains(name)) throw new IncorrectArgumentKey(arg.toString(), "name", "Argument with this name already exists!"); - - String type = (String) arg.get("type"); - if(type == null) throw new IncorrectArgumentKey(arg.toString(), "type", "Key not found."); - ConfigCommandsHandler.logDebug(localDebug, "Arg has type: " + type); - if(!argumentMap.containsKey(type)) throw new IncorrectArgumentKey(arg.toString(), "type", "Type \"" + type + "\" was not found"); + public static Argument convertArgumentInformation(String name, String type, + Map> argumentClasses, + Object argumentInfo, boolean localDebug) throws IncorrectArgumentKey { + if(!typeMap.containsKey(type)) + throw new IncorrectArgumentKey(name, "type", "\"" + type + "\" is not a recognized type that can be added to a command."); + InternalArgument object = typeMap.get(type); + String argumentName = formatArgumentName(name); + argumentClasses.put(argumentName, object.getClass()); + ConfigCommandsHandler.logDebug(localDebug, "Argument %s available as %s", argumentName, object.getClass().getSimpleName()); try { - argumentMap.get(type).add(arg, command, name, argument_keys, argument_variable_classes, localDebug); - } catch (IncorrectArgumentKey e){ - throw e; - } catch (Exception e){ - throw new IncorrectArgumentKey(arg.toString(), false, e.getMessage()); + return object.createArgument(name, argumentInfo, localDebug); + } catch (RuntimeException e){ + throw new IncorrectArgumentKey(name, "argumentInfo", e.getMessage()); } } @@ -377,12 +368,13 @@ public String getTypeTag(){ return getName(); } - public void addArgument(Map arg, CommandAPICommand command, String name, - ArrayList argument_keys, - HashMap> argument_variable_classes, - boolean localDebug) throws IncorrectArgumentKey{ - // default result from adding argument is to reject being added - throw new IncorrectArgumentKey(arg.toString(), "type", getName() + " cannot be an argument"); + protected T assertArgumentInfoClass(Object argumentInfo, Class clazz, String arg) throws IncorrectArgumentKey { + if (clazz.isAssignableFrom(argumentInfo.getClass())) return clazz.cast(argumentInfo); + throw new IncorrectArgumentKey(arg, "argumentInfo", "Expected argumentInfo to have class " + clazz.getSimpleName()); + } + + public Argument createArgument(String name, Object argumentInfo, boolean localDebug) throws IncorrectArgumentKey{ + throw new IncorrectArgumentKey(name, "type", getTypeTag() + " cannot be an argument"); } // manage function arrays diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalArrayListArgument.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalArrayListArgument.java index d7f4c28..9ccabc0 100644 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalArrayListArgument.java +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalArrayListArgument.java @@ -26,10 +26,12 @@ public InternalArrayListArgument(ArrayList value) { super(value); } + @Override public String getTypeTag() { return null; } + @Override public FunctionList getFunctions() { return merge(super.getFunctions(), generateGets(), @@ -129,6 +131,7 @@ private InternalArgument subList(InternalArgument target, List return new InternalArrayListArgument(getList(target).subList((int) parameters.get(0).getValue(), (int) parameters.get(1).getValue())); } + @Override public StaticFunctionList getStaticFunctions() { return staticMerge(super.getStaticFunctions(), staticExpandDefinition( @@ -142,18 +145,22 @@ public InternalArgument initialize(List parameters) { return new InternalArrayListArgument(new ArrayList<>()); } + @Override public void setValue(Object arg) { value = (ArrayList) arg; } + @Override public Object getValue() { return value; } + @Override public void setValue(InternalArgument arg) { value = getList(arg); } + @Override public String forCommand() { StringBuilder out = new StringBuilder("["); if (value.size() != 0) { diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalBooleanArgument.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalBooleanArgument.java index 95e4155..7a39bf7 100644 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalBooleanArgument.java +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalBooleanArgument.java @@ -1,16 +1,13 @@ package me.willkroboth.ConfigCommands.InternalArguments; -import dev.jorel.commandapi.CommandAPICommand; +import dev.jorel.commandapi.arguments.Argument; import dev.jorel.commandapi.arguments.BooleanArgument; import me.willkroboth.ConfigCommands.Functions.Function; import me.willkroboth.ConfigCommands.Functions.NonGenericVarargs.FunctionList; import me.willkroboth.ConfigCommands.Functions.NonGenericVarargs.StaticFunctionList; import me.willkroboth.ConfigCommands.Functions.StaticFunction; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class InternalBooleanArgument extends InternalArgument { private boolean value; @@ -22,12 +19,12 @@ public InternalBooleanArgument(boolean value) { super(value); } - public void addArgument(Map arg, CommandAPICommand command, String name, ArrayList argument_keys, HashMap> argument_variable_classes, boolean localDebug) { - command.withArguments(new BooleanArgument(name)); - argument_keys.add(name); - argument_variable_classes.put(name, InternalBooleanArgument.class); + @Override + public Argument createArgument(String name, Object argumentInfo, boolean localDebug) { + return new BooleanArgument(name); } + @Override public FunctionList getFunctions() { return merge(super.getFunctions(), expandDefinition(strings("and", "&&"), args(args(InternalBooleanArgument.class)), @@ -59,6 +56,7 @@ private InternalBooleanArgument not(InternalArgument target, List o) { return new InternalBooleanArgument(Boolean.parseBoolean(value)); } + @Override public void setValue(Object arg) { value = (boolean) arg; } + @Override public Object getValue() { return value; } + @Override public void setValue(InternalArgument arg) { value = (boolean) arg.getValue(); } + @Override public String forCommand() { return "" + value; } diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalCommandSenderArgument.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalCommandSenderArgument.java index a4b6bdc..3598844 100644 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalCommandSenderArgument.java +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalCommandSenderArgument.java @@ -25,10 +25,12 @@ public InternalCommandSenderArgument(CommandSender value) { super(value); } + @Override public String getTypeTag() { return null; } + @Override public FunctionList getFunctions() { return merge( super.getFunctions(), @@ -141,11 +143,13 @@ private InternalArgument setOp(InternalArgument target, List p return InternalVoidArgument.getInstance(); } + @Override public void setValue(Object arg) { value = (CommandSender) arg; opSender = OpSender.makeOpSender(value); } + @Override public Object getValue() { return value; } @@ -154,11 +158,13 @@ public OpSender getOpSender() { return opSender; } + @Override public void setValue(InternalArgument arg) { value = (CommandSender) arg.getValue(); opSender = OpSender.makeOpSender(value); } + @Override public String forCommand() { return value.getName(); } diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalIntegerArgument.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalIntegerArgument.java index 67651e8..a5ead5f 100644 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalIntegerArgument.java +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalIntegerArgument.java @@ -1,19 +1,17 @@ package me.willkroboth.ConfigCommands.InternalArguments; -import dev.jorel.commandapi.CommandAPICommand; +import dev.jorel.commandapi.arguments.Argument; import dev.jorel.commandapi.arguments.IntegerArgument; import me.willkroboth.ConfigCommands.ConfigCommandsHandler; import me.willkroboth.ConfigCommands.Exceptions.CommandRunException; import me.willkroboth.ConfigCommands.Exceptions.IncorrectArgumentKey; import me.willkroboth.ConfigCommands.Functions.NonGenericVarargs.StaticFunctionList; import me.willkroboth.ConfigCommands.Functions.StaticFunction; +import org.bukkit.configuration.ConfigurationSection; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; -public class InternalIntegerArgument extends InternalArgument{ +public class InternalIntegerArgument extends InternalArgument { private int value; public InternalIntegerArgument() { @@ -23,38 +21,20 @@ public InternalIntegerArgument(int value) { super(value); } - public void addArgument(Map arg, CommandAPICommand command, String name, ArrayList argument_keys, HashMap> argument_variable_classes, boolean localDebug) throws IncorrectArgumentKey { - int min; - if(arg.get("min") == null){ - min = Integer.MIN_VALUE; + @Override + public Argument createArgument(String name, Object argumentInfo, boolean localDebug) throws IncorrectArgumentKey { + int min = Integer.MIN_VALUE; + int max = Integer.MAX_VALUE; + if(argumentInfo != null) { + ConfigurationSection info = assertArgumentInfoClass(argumentInfo, ConfigurationSection.class, name); + min = info.getInt("min", Integer.MIN_VALUE); + max = info.getInt("max", Integer.MAX_VALUE); } - else { - try { - min = Integer.parseInt(arg.get("min").toString()); - } catch (NumberFormatException e){ - throw new IncorrectArgumentKey(arg.toString(), "min", "Could not be interpreted as an int."); - } - } - ConfigCommandsHandler.logDebug(localDebug, "Arg has min: %s", min); - - int max; - if(arg.get("max") == null){ - max = Integer.MAX_VALUE; - } - else { - try { - max = Integer.parseInt(arg.get("max").toString()); - } catch (NumberFormatException e){ - throw new IncorrectArgumentKey(arg.toString(), "max", "Could not be interpreted as an int."); - } - } - ConfigCommandsHandler.logDebug(localDebug, "Arg has max: %s", max); - - command.withArguments(new IntegerArgument(name, min, max)); - argument_keys.add(name); - argument_variable_classes.put(name, InternalIntegerArgument.class); + ConfigCommandsHandler.logDebug(localDebug, "Arg has min: %s, max: %s", min, max); + return new IntegerArgument(name, min, max); } + @Override public StaticFunctionList getStaticFunctions() { return staticMerge( super.getStaticFunctions(), @@ -66,12 +46,12 @@ public StaticFunctionList getStaticFunctions() { public InternalArgument initialize(List arguments) { int result = 0; - if(arguments.size() == 1){ + if (arguments.size() == 1) { InternalStringArgument arg = (InternalStringArgument) arguments.get(0); String word = (String) arg.getValue(); try { result = Integer.parseInt(word); - } catch (NumberFormatException e){ + } catch (NumberFormatException e) { throw new CommandRunException("Word: \"" + word + "\" cannot be parsed as int."); } } @@ -80,11 +60,23 @@ public InternalArgument initialize(List arguments) { } // value - public void setValue(Object arg) { value = (int) arg; } + @Override + public void setValue(Object arg) { + value = (int) arg; + } - public Object getValue() { return value; } + @Override + public Object getValue() { + return value; + } - public void setValue(InternalArgument arg) { value = (int) arg.getValue(); } + @Override + public void setValue(InternalArgument arg) { + value = (int) arg.getValue(); + } - public String forCommand() { return "" + value; } + @Override + public String forCommand() { + return "" + value; + } } diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalStringArgument.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalStringArgument.java index 0d51d79..cc77a89 100644 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalStringArgument.java +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalStringArgument.java @@ -1,6 +1,6 @@ package me.willkroboth.ConfigCommands.InternalArguments; -import dev.jorel.commandapi.CommandAPICommand; +import dev.jorel.commandapi.arguments.Argument; import dev.jorel.commandapi.arguments.GreedyStringArgument; import dev.jorel.commandapi.arguments.StringArgument; import dev.jorel.commandapi.arguments.TextArgument; @@ -11,11 +11,9 @@ import me.willkroboth.ConfigCommands.Functions.Function; import me.willkroboth.ConfigCommands.Functions.NonGenericVarargs.FunctionList; import me.willkroboth.ConfigCommands.InternalArguments.HelperClasses.AllInternalArguments; +import org.bukkit.configuration.ConfigurationSection; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class InternalStringArgument extends InternalArgument { private String value; @@ -27,22 +25,21 @@ public InternalStringArgument(String value) { super(value); } - public void addArgument(Map arg, CommandAPICommand command, String name, ArrayList argument_keys, HashMap> argument_variable_classes, boolean localDebug) throws IncorrectArgumentKey { - String type = (String) arg.get("subtype"); - ConfigCommandsHandler.logDebug(localDebug, "Arg has subtype: " + type); - command.withArguments( - type == null ? new StringArgument(name): - switch (type) { - case "string" -> new StringArgument(name); - case "text" -> new TextArgument(name); - case "greedy" -> new GreedyStringArgument(name); - default -> throw new IncorrectArgumentKey(arg.toString(), "subtype", "Did not find StringArgument subtype: \"" + type + "\""); - } - ); - argument_keys.add(name); - argument_variable_classes.put(name, InternalStringArgument.class); + @Override + public Argument createArgument(String name, Object argumentInfo, boolean localDebug) throws IncorrectArgumentKey { + ConfigurationSection info = assertArgumentInfoClass(argumentInfo, ConfigurationSection.class, name); + String type = info.getString("subtype"); + ConfigCommandsHandler.logDebug(localDebug, "Arg has subtype: %s", type); + if (type == null) return new StringArgument(name); + return switch (type) { + case "string" -> new StringArgument(name); + case "text" -> new TextArgument(name); + case "greedy" -> new GreedyStringArgument(name); + default -> throw new IncorrectArgumentKey(name, "subtype", "Did not find StringArgument subtype: \"" + type + "\""); + }; } + @Override public FunctionList getFunctions() { return merge( super.getFunctions(), @@ -92,18 +89,18 @@ public FunctionList getFunctions() { ); } - - private String getString(InternalArgument target){ + + private String getString(InternalArgument target) { return (String) target.getValue(); } - - private int getInt(InternalArgument target){ + + private int getInt(InternalArgument target) { return (int) target.getValue(); } private InternalArgument substring(InternalArgument target, List parameters) { String result; - if(parameters.size() == 1){ + if (parameters.size() == 1) { result = getString(target).substring(getInt(parameters.get(0))); } else { result = getString(target).substring(getInt(parameters.get(0)), getInt(parameters.get(1))); @@ -113,7 +110,7 @@ private InternalArgument substring(InternalArgument target, List parameters) { int result; - if(parameters.size() == 1){ + if (parameters.size() == 1) { result = getString(target).lastIndexOf(getString(parameters.get(0))); } else { result = getString(target).lastIndexOf(getString(parameters.get(0)), getInt(parameters.get(1))); @@ -123,7 +120,7 @@ private InternalArgument lastIndexOf(InternalArgument target, List parameters) { int result; - if(parameters.size() == 1){ + if (parameters.size() == 1) { result = getString(target).indexOf(getString(parameters.get(0))); } else { result = getString(target).indexOf(getString(parameters.get(0)), getInt(parameters.get(1))); @@ -171,21 +168,33 @@ public InternalIntegerArgument toInt(InternalArgument target, List parameters){ + public InternalStringArgument join(InternalArgument target, List parameters) { String arg = parameters.get(0).forCommand(); return new InternalStringArgument(target.getValue() + arg); } - public void setValue(Object arg) { value = (String) arg; } + @Override + public void setValue(Object arg) { + value = (String) arg; + } - public Object getValue() { return value; } + @Override + public Object getValue() { + return value; + } - public void setValue(InternalArgument arg) { value = (String) arg.getValue(); } + @Override + public void setValue(InternalArgument arg) { + value = (String) arg.getValue(); + } - public String forCommand() { return value; } + @Override + public String forCommand() { + return value; + } } diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalVoidArgument.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalVoidArgument.java index e0b422e..3c49932 100644 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalVoidArgument.java +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/InternalArguments/InternalVoidArgument.java @@ -13,22 +13,29 @@ public class InternalVoidArgument extends InternalArgument { public static InternalVoidArgument getInstance(){ return instance; } + @Override public String getTypeTag() { return null; } + @Override public FunctionList getFunctions() { return entries(); } + @Override public StaticFunctionList getStaticFunctions() { return staticEntries(); } // not used + @Override public void setValue(Object arg) { } + @Override public Object getValue() { return null; } + @Override public void setValue(InternalArgument arg) { } + @Override public String forCommand() { return ""; } } diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/ArgumentTreeBuilder.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/ArgumentTreeBuilder.java new file mode 100644 index 0000000..78e6509 --- /dev/null +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/ArgumentTreeBuilder.java @@ -0,0 +1,84 @@ +package me.willkroboth.ConfigCommands.RegisteredCommands; + +import dev.jorel.commandapi.ArgumentTree; +import dev.jorel.commandapi.arguments.Argument; +import dev.jorel.commandapi.arguments.LiteralArgument; +import me.willkroboth.ConfigCommands.ConfigCommandsHandler; +import me.willkroboth.ConfigCommands.Exceptions.IncorrectArgumentKey; +import me.willkroboth.ConfigCommands.Exceptions.RegistrationException; +import me.willkroboth.ConfigCommands.InternalArguments.InternalArgument; +import org.bukkit.configuration.ConfigurationSection; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class ArgumentTreeBuilder extends ArgumentTree { + private static Argument getArgument(String name, Map> argumentClasses, ConfigurationSection tree, boolean localDebug) throws IncorrectArgumentKey { + String type = tree.getString("type"); + if (type == null) { + ConfigCommandsHandler.logDebug(localDebug, "Type was not found, so this will be a LiteralArgument"); + return new LiteralArgument(name); + } + ConfigCommandsHandler.logDebug(localDebug, "Type is %s", type); + + Object argumentInfo = tree.get("argumentInfo"); + if (localDebug) { + if (argumentInfo == null) + ConfigCommandsHandler.logNormal("argumentInfo is null"); + else + ConfigCommandsHandler.logNormal("argumentInfo has class %s", argumentInfo.getClass().getSimpleName()); + } + Argument out = InternalArgument.convertArgumentInformation(name, type, argumentClasses, argumentInfo, localDebug); + ConfigCommandsHandler.logDebug(localDebug, "Argument created with class: %s", out.getClass().getSimpleName() + ); + return out; + } + + private static Argument modifyArgument(Argument argument, ConfigurationSection tree, boolean localDebug) { + // set permission + String permission = tree.getString("permission"); + if (permission != null) { + argument.withPermission(permission); + ConfigCommandsHandler.logDebug(localDebug, "Added permission \"%s\" to branch", permission); + } + + return argument; + } + + public ArgumentTreeBuilder(String name, Map> argumentClasses, + ConfigurationSection tree, boolean localDebug) throws RegistrationException { + super(modifyArgument(getArgument(name, argumentClasses, tree, localDebug), tree, localDebug)); + + ConfigCommandsHandler.logNormal("Building ArgumentTree..."); + // set executes + List executes = tree.getStringList("executes"); + if (executes.size() != 0) { + ConfigCommandsHandler.logDebug(localDebug, "Adding executes"); + ConfigCommandsHandler.increaseIndentation(); + super.executes(new ExecutesBuilder(executes, argumentClasses, localDebug)); + ConfigCommandsHandler.decreaseIndentation(); + } else { + ConfigCommandsHandler.logDebug(localDebug, "Not executable at this stage"); + } + + // set then + ConfigurationSection then = tree.getConfigurationSection("then"); + if (then == null || then.getKeys(false).size() == 0) { + ConfigCommandsHandler.logDebug(localDebug, "No branches"); + } else { + ConfigCommandsHandler.logDebug(localDebug, "Adding branches"); + ConfigCommandsHandler.increaseIndentation(); + for (String branchName : then.getKeys(false)) { + ConfigCommandsHandler.logDebug(localDebug, "Adding branch %s", branchName); + ConfigCommandsHandler.increaseIndentation(); + super.then(new ArgumentTreeBuilder( + branchName, new LinkedHashMap<>(argumentClasses), + then.getConfigurationSection(branchName), localDebug + )); + ConfigCommandsHandler.decreaseIndentation(); + } + ConfigCommandsHandler.decreaseIndentation(); + } + } +} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/CommandTreeBuilder.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/CommandTreeBuilder.java new file mode 100644 index 0000000..f05aa0f --- /dev/null +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/CommandTreeBuilder.java @@ -0,0 +1,164 @@ +package me.willkroboth.ConfigCommands.RegisteredCommands; + +import dev.jorel.commandapi.CommandTree; +import me.willkroboth.ConfigCommands.ConfigCommandsHandler; +import me.willkroboth.ConfigCommands.Exceptions.RegistrationException; +import me.willkroboth.ConfigCommands.InternalArguments.InternalArgument; +import me.willkroboth.ConfigCommands.InternalArguments.InternalCommandSenderArgument; +import me.willkroboth.ConfigCommands.InternalArguments.InternalIntegerArgument; +import org.bukkit.configuration.ConfigurationSection; + +import java.util.*; + +public class CommandTreeBuilder extends CommandTree { + public static void registerCommandsFromConfig(ConfigurationSection commands, boolean globalDebug) { + ConfigCommandsHandler.logNormal(""); + if (commands == null) { + ConfigCommandsHandler.logNormal("The configuration section for the commands was not found! Skipping"); + return; + } + + ConfigCommandsHandler.logNormal("Registering commands from %s", commands.getCurrentPath()); + if (commands.getKeys(false).size() == 0) { + ConfigCommandsHandler.logNormal("No commands found! Skipping"); + return; + } + + List failedCommands = new ArrayList<>(); + for (String key : commands.getKeys(false)) { + ConfigCommandsHandler.logNormal(""); + ConfigCommandsHandler.logNormal("Loading command %s", key); + + int indentation = ConfigCommandsHandler.getIndentation(); + try { + // vital data needed for command to work + ConfigurationSection command = commands.getConfigurationSection(key); + if (command == null) { + ConfigCommandsHandler.logError("%s has no data. Skipping.", key); + throw new RegistrationException("No data found for key " + key); + } + + new CommandTreeBuilder(key, command, globalDebug).register(); + } catch (RegistrationException e) { + ConfigCommandsHandler.logError("Error occurred while creating argument: %s", e.getMessage()); + failedCommands.add(e.getMessage()); + } finally { + ConfigCommandsHandler.setIndentation(indentation); + } + } + + ConfigCommandsHandler.logNormal(""); + // inform user of failed commands + if (failedCommands.size() == 0) { + ConfigCommandsHandler.logNormal("All commands were successfully registered."); + ConfigCommandsHandler.logNormal("Note: this does not mean they will work as you expect."); + if (globalDebug) { + ConfigCommandsHandler.logNormal("If a command does not work, check the console output to try to find the problem."); + } else { + ConfigCommandsHandler.logNormal("If a command does not work, turn on debug mode, then check the console output to try to find the problem."); + } + } else { + ConfigCommandsHandler.logNormal("%s command(s) failed while registering:", failedCommands.size()); + ConfigCommandsHandler.increaseIndentation(); + for (String message : failedCommands) { + ConfigCommandsHandler.logError(message); + } + ConfigCommandsHandler.decreaseIndentation(); + if (globalDebug) { + ConfigCommandsHandler.logNormal("Scroll up to find more information."); + } else { + ConfigCommandsHandler.logNormal("Turn on debug mode and scroll up to find more information."); + } + } + } + + public static String buildDefaultPermission(String name) { + return "configcommands." + name.toLowerCase(Locale.ROOT); + } + + public static Map> getDefaultArgs() { + return new LinkedHashMap<>(Map.of( + "", InternalCommandSenderArgument.class, + "", InternalIntegerArgument.class + )); + } + + public CommandTreeBuilder(String name, ConfigurationSection command, boolean globalDebug) throws RegistrationException { + //set name + super(name); + + // set debug variable + boolean localDebug = command.getBoolean("debug", false); + ConfigCommandsHandler.logDebug(localDebug && !globalDebug, "Debug turned on for %s", name); + localDebug = globalDebug || localDebug; + + // set help + String shortDescription = command.getString("shortDescription"); + if (shortDescription != null) { + super.withShortDescription(shortDescription); + } else { + ConfigCommandsHandler.logWarning("%s has no shortDescription. It will default to \"A Mojang provided command\".", name); + } + ConfigCommandsHandler.logDebug(localDebug, "%s has shortDescription %s", name, shortDescription); + + String fullDescription = command.getString("fullDescription"); + if (fullDescription != null) { + super.withFullDescription(fullDescription); + } else { + ConfigCommandsHandler.logWarning("%s has no fullDescription. It will default to \"A Mojang provided command\".", name); + } + ConfigCommandsHandler.logDebug(localDebug, "%s has fullDescription %s", name, fullDescription); + + // set permission + String permission = command.getString("permission"); + if (permission == null) { + permission = buildDefaultPermission(name); + ConfigCommandsHandler.logWarning("%s has no permission. It will default to \"%s\".", name, permission); + } + super.withPermission(permission); + ConfigCommandsHandler.logDebug(localDebug, "%s has permission \"%s\"", name, permission); + + // set aliases + List aliases = command.getStringList("aliases"); + ConfigCommandsHandler.logDebug(localDebug, "%s has %s alias(es): %s", name, aliases.size(), aliases); + super.withAliases(aliases.toArray(new String[0])); + + ConfigCommandsHandler.logNormal("Building CommandTree..."); + + Map> argumentClasses = getDefaultArgs(); + if (localDebug) { + ConfigCommandsHandler.logNormal("Default arguments available:"); + ConfigCommandsHandler.increaseIndentation(); + for (Map.Entry> arg : argumentClasses.entrySet()) { + ConfigCommandsHandler.logNormal("%s: %s", arg.getKey(), arg.getValue().getSimpleName()); + } + ConfigCommandsHandler.decreaseIndentation(); + } + // set executes + List executes = command.getStringList("executes"); + if (executes.size() != 0) { + ConfigCommandsHandler.logDebug(localDebug, "Adding executes"); + ConfigCommandsHandler.increaseIndentation(); + super.executes(new ExecutesBuilder(executes, argumentClasses, localDebug)); + ConfigCommandsHandler.decreaseIndentation(); + } else { + ConfigCommandsHandler.logDebug(localDebug, "Not executable at this stage"); + } + + // set then + ConfigurationSection then = command.getConfigurationSection("then"); + if (then == null || then.getKeys(false).size() == 0) { + ConfigCommandsHandler.logDebug(localDebug, "No branches"); + } else { + ConfigCommandsHandler.logDebug(localDebug, "Adding branches"); + ConfigCommandsHandler.increaseIndentation(); + for (String branchName : then.getKeys(false)) { + ConfigCommandsHandler.logDebug(localDebug, "Adding branch %s", branchName); + ConfigCommandsHandler.increaseIndentation(); + super.then(new ArgumentTreeBuilder(branchName, new LinkedHashMap<>(argumentClasses), then.getConfigurationSection(branchName), localDebug)); + ConfigCommandsHandler.decreaseIndentation(); + } + ConfigCommandsHandler.decreaseIndentation(); + } + } +} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/CompilerState.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/CompilerState.java new file mode 100644 index 0000000..e54edb5 --- /dev/null +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/CompilerState.java @@ -0,0 +1,117 @@ +package me.willkroboth.ConfigCommands.RegisteredCommands; + +import me.willkroboth.ConfigCommands.HelperClasses.DebuggableState; +import me.willkroboth.ConfigCommands.InternalArguments.InternalArgument; + +import java.util.*; + +public class CompilerState implements DebuggableState { + public CompilerState() { + commands = new ArrayList<>(); + command = null; + argumentClasses = new LinkedHashMap<>(); + tagMap = new HashMap<>(); + index = 0; + localDebug = false; + } + + private final List commands; + + public CompilerState addCommand(String command) { + commands.add(command); + if (this.command == null && commands.size() > index) this.command = commands.get(index); + return this; + } + + public CompilerState addCommands(List commands) { + this.commands.addAll(commands); + if (this.command == null && this.commands.size() > index) this.command = this.commands.get(index); + return this; + } + + public List getCommands() { + return commands; + } + + private String command; + + public boolean hasCommand() { + return command != null; + } + + public String getCommand() { + return command; + } + + private final Map> argumentClasses; + + public CompilerState addArgument(String name, Class clazz) { + argumentClasses.put(name, clazz); + return this; + } + + public CompilerState addArguments(Map> arguments) { + argumentClasses.putAll(arguments); + return this; + } + + public Map> getArgumentClasses() { + return argumentClasses; + } + + public boolean hasVariable(String name) { + return argumentClasses.containsKey(name); + } + + public Class getVariable(String name) { + return argumentClasses.get(name); + } + + private final Map tagMap; + + public CompilerState addTag(String name, int index) { + tagMap.put(name, index); + return this; + } + + public CompilerState addTags(Map tags) { + tagMap.putAll(tags); + return this; + } + + public Map getTagMap() { + return tagMap; + } + + private int index; + + public CompilerState updateIndex(int index) { + this.index = index; + if (0 <= index && index < commands.size()) { + command = commands.get(index); + } else { + command = null; + } + return this; + } + + public CompilerState increaseIndex(int amount) { + updateIndex(index + amount); + return this; + } + + public int getIndex() { + return index; + } + + private boolean localDebug; + + public CompilerState setDebug(boolean debug) { + localDebug = debug; + return this; + } + + public boolean isDebug() { + return localDebug; + } +} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/ConfigCommandBuilder.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/ConfigCommandBuilder.java deleted file mode 100644 index 0d0d842..0000000 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/ConfigCommandBuilder.java +++ /dev/null @@ -1,491 +0,0 @@ -package me.willkroboth.ConfigCommands.RegisteredCommands; - -import dev.jorel.commandapi.CommandAPICommand; -import me.willkroboth.ConfigCommands.ConfigCommandsHandler; -import me.willkroboth.ConfigCommands.Exceptions.*; -import me.willkroboth.ConfigCommands.InternalArguments.*; -import me.willkroboth.ConfigCommands.SystemCommands.ReloadCommandHandler; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.ConfigurationSection; - -import java.util.*; - -public class ConfigCommandBuilder extends CommandAPICommand { - public static void registerCommandsFromConfig(ConfigurationSection commands, boolean globalDebug) { - ConfigCommandsHandler.logNormal(""); - if(commands == null){ - ConfigCommandsHandler.logNormal("The configuration section for the commands was not found! Skipping"); - return; - } - - ConfigCommandsHandler.logNormal("Registering commands from %s", commands.getCurrentPath()); - if (commands.getKeys(false).size() == 0) { - ConfigCommandsHandler.logNormal("No commands found! Skipping"); - return; - } - - List failedCommands = new ArrayList<>(); - for (String key : commands.getKeys(false)) { - ConfigCommandsHandler.logNormal(""); - ConfigCommandsHandler.logNormal("Loading command %s", key); - - // vital data needed for command to work - ConfigurationSection command = commands.getConfigurationSection(key); - if (command == null) { - ConfigCommandsHandler.logError("%s has no data. Skipping.", key); - failedCommands.add("(key) " + key + ": No data found!"); - continue; - } - - boolean localDebug = command.getBoolean("debug", false); - ConfigCommandsHandler.logDebug(localDebug && !globalDebug, "Debug turned on for %s", key); - localDebug = globalDebug || localDebug; - - String name = (String) command.get("name"); - if (name == null) { - ConfigCommandsHandler.logError("%s has no command name. Skipping.", key); - failedCommands.add("(key) " + key + ": No name found!"); - continue; - } - - ConfigCommandsHandler.logDebug(localDebug, "%s has name %s", key, name); - - List commandsToRun = command.getStringList("commands"); - if (commandsToRun.size() == 0) { - ConfigCommandsHandler.logError("%s has no commands. Skipping.", key); - failedCommands.add("(name) " + name + ": No commands found!"); - continue; - } - - ConfigCommandsHandler.logDebug(localDebug, "%s has %s command(s): %s", key, commandsToRun.size(), commandsToRun); - - // less important, but will warn user if they don't exist - String shortDescription = command.getString("shortDescription"); - if (shortDescription == null) ConfigCommandsHandler.logWarning("%s has no shortDescription.", key); - ConfigCommandsHandler.logDebug(localDebug, "%s has shortDescription: %s", key, shortDescription); - - String fullDescription = command.getString("fullDescription"); - if (fullDescription == null) ConfigCommandsHandler.logWarning("%s has no fullDescription.", key); - ConfigCommandsHandler.logDebug(localDebug, "%s has fullDescription: %s", key, fullDescription); - - String permission = command.getString("permission"); - if (permission == null) { - permission = buildDefaultPermission(name); - ConfigCommandsHandler.logWarning("%s has no permission. Using \"%s\".", key, permission); - } - ConfigCommandsHandler.logDebug(localDebug, "%s has permission %s", key, permission); - - // Don't need to warn user about these - List> args = command.getMapList("args"); - ConfigCommandsHandler.logDebug(localDebug, key + " has args: " + args); - - List aliases = command.getStringList("aliases"); - ConfigCommandsHandler.logDebug(localDebug, "%s has %s alias(es): %s", key, aliases.size(), aliases); - - // register command - ConfigCommandsHandler.logNormal("Loading %s with name: %s", key, name); - int indentation = ConfigCommandsHandler.getIndentation(); - ConfigCommandsHandler.increaseIndentation(); - try { - ReloadCommandHandler.addCommand( - new ConfigCommandBuilder( - name, shortDescription, fullDescription, args, - aliases, permission, commandsToRun, localDebug - ), - key - ); - } catch (RegistrationException e) { - ConfigCommandsHandler.logError("Registration error: \"%s\" Skipping registration", e.getMessage()); - failedCommands.add("(name) " + name + ": Registration error: \"" + e.getMessage() + "\""); - } - // reset indentation in case of error - ConfigCommandsHandler.setIndentation(indentation); - } - - // inform user of failed commands - if (failedCommands.size() == 0) { - ConfigCommandsHandler.logNormal("All commands were successfully registered."); - ConfigCommandsHandler.logNormal("Note: this does not mean they will work as you expect."); - if (globalDebug) { - ConfigCommandsHandler.logNormal("If a command does not work, check the console output to try to find the problem."); - } else { - ConfigCommandsHandler.logNormal("If a command does not work, turn on debug mode, then check the console output to try to find the problem."); - } - } else { - ConfigCommandsHandler.logNormal("%s command(s) failed while registering:", failedCommands.size()); - ConfigCommandsHandler.increaseIndentation(); - for (String message : failedCommands) { - ConfigCommandsHandler.logError(message); - } - ConfigCommandsHandler.decreaseIndentation(); - if (globalDebug) { - ConfigCommandsHandler.logNormal("Scroll up to find more information."); - } else { - ConfigCommandsHandler.logNormal("Turn on debug mode and scroll up to find more information."); - } - } - } - - public static String buildDefaultPermission(String name){ - return "configcommands." + name.toLowerCase(Locale.ROOT); - } - - private final ArrayList argument_keys = new ArrayList<>(); - private final HashMap> argument_variable_classes = new HashMap<>(); - - private ArrayList> commands = new ArrayList<>(); - - private Map tagMap = new HashMap<>(); - - private final boolean localDebug; - - private ConfigCommandExecutor executor; - - public ConfigCommandBuilder(String name, String shortDescription, String fullDescription, List> args, - List aliases, String permission, List commands, - boolean localDebug) throws RegistrationException { - //set name - super(name); - - // set debug variable - this.localDebug = localDebug; - - // setup arguments - addDefaultArgs(); - parse_args(args); - - // set aliases - super.withAliases(aliases.toArray(new String[0])); - // set permission - super.withPermission(permission); - // set commands - parse_commands(commands); - - // set help - if(shortDescription != null) super.withShortDescription(shortDescription); - if(fullDescription != null) super.withFullDescription(fullDescription); - - super.executes(this::execute); - try { - super.register(); - } catch (Exception e){ - throw new RegistrationException("Encountered " + e.getClass().getSimpleName() + " when registering: " + e.getMessage()); - } - executor = new ConfigCommandExecutor(name, argument_keys, this.commands, tagMap, this.localDebug); - } - - private void addDefaultArgs() { - for(Map.Entry> arg: getDefaultArgs().entrySet()){ - argument_keys.add(arg.getKey()); - argument_variable_classes.put(arg.getKey(), arg.getValue()); - } - } - - public static Map> getDefaultArgs(){ - return Map.of( - "", InternalCommandSenderArgument.class, - "", InternalIntegerArgument.class - ); - } - - private void parse_args(List> args) throws RegistrationException { - // sets command to execute with arguments and sets up arguments variables - for (Map arg : args) { - ConfigCommandsHandler.logDebug(localDebug, "Adding argument: %s", arg); - ConfigCommandsHandler.increaseIndentation(); - InternalArgument.addArgument(arg, this, argument_keys, argument_variable_classes, localDebug); - ConfigCommandsHandler.decreaseIndentation(); - } - } - - // update commands to reflect new behavior from config file - public void refreshExecutor(List commands) throws RegistrationException { - // refresh relevant variables - this.commands = new ArrayList<>(); - this.tagMap = new HashMap<>(); - - // parse new commands - parse_commands(commands); - - // create new executor - executor = new ConfigCommandExecutor(getName(), argument_keys, this.commands, tagMap, localDebug); - } - - private void parse_commands(List commands) throws RegistrationException { - // Commands: - // - Run command, indicated by / - // - define and set variables, indicated by = - // - run functions, indicated by do - // - define branch target tag, indicated by tag - // - conditional branch, indicated by if - // - branch, indicated by goto - // - return value, indicated by return - int index = 0; - for (String command : commands) { - ConfigCommandsHandler.logDebug(localDebug, "Parsing command: %s", command); - - ConfigCommandsHandler.increaseIndentation(); - switch (command.charAt(0)) { - case '/' -> parse_command_to_run(command); - case '<' -> parse_set(command); - case 'd' -> parse_do(command); - case 't' -> parse_tag(command, index); - case 'i' -> parse_if(command); - case 'g' -> parse_goto(command); - case 'r' -> parse_return(command); - default -> throw new RegistrationException("Command not recognized, invalid format: \"" + command + "\""); - } - ConfigCommandsHandler.decreaseIndentation(); - index++; - } - } - - private void parse_command_to_run(String command) { - List command_sections = getCommandSections(command); - - HashMap new_command = new HashMap<>(); - new_command.put("type", "command"); - new_command.put("info", command_sections); - commands.add(new_command); - } - - private List getCommandSections(String command){ - List command_sections = new ArrayList<>(); - String[] keys = argument_keys.toArray(new String[0]); - - int previous_index = 1; //start at 1 to get rid of initial / - intPair pair = get_first_index_and_length(command, keys); - int index = pair.first; - int length = pair.last; - - while (index != -1) { - command_sections.add(command.substring(previous_index, index)); - command_sections.add(command.substring(index, index + length)); - - previous_index = index + length; - pair = get_first_index_and_length(command, keys, previous_index); - index = pair.first; - length = pair.last; - } - if (previous_index != command.length()) { - command_sections.add(command.substring(previous_index)); - } - - ConfigCommandsHandler.logDebug(localDebug, "Command has been split into: %s", command_sections); - return command_sections; - } - - private intPair get_first_index_and_length(String string, String[] keys) { - return get_first_index_and_length(string, keys, 0); - } - - private intPair get_first_index_and_length(String string, String[] keys, int from_index) { - int least = string.length(); - int length = -1; - - for (String key : keys) { - int index = string.indexOf(key, from_index); - if (index != -1 && index < least) { - least = index; - length = key.length(); - } - } - - if (least == string.length()) return new intPair(-1, -1); - return new intPair(least, length); - } - - private record intPair(int first, int last){ - } - - private void parse_set(String command) throws RegistrationException { - String[] parts = command.split(" = "); - if (parts.length != 2) throw new InvalidSetCommand(command, "Invalid format. Must contain only 1 \" = \"."); - - ConfigCommandsHandler.logDebug(localDebug, "Set split into: %s", Arrays.toString(parts)); - - String variable = parts[0]; - if (!(variable.charAt(0) == '<' && variable.charAt(variable.length() - 1) == '>')) { - throw new InvalidSetCommand(command, "Invalid variable: " + variable + ". Must be wrapped by < >."); - } - ConfigCommandsHandler.logDebug(localDebug, "Variable is " + variable); - - String rawExpression = parts[1]; - Class returnType; - HashMap info; - if (rawExpression.startsWith("/")) { - // setting a variable to a command - ConfigCommandsHandler.logDebug(localDebug, "Expression looks like a command."); - ConfigCommandsHandler.logDebug(localDebug, "Parsing \"%s\" as command.", rawExpression); - - // parse command - List command_sections = getCommandSections(rawExpression); - - info = new HashMap<>(); - info.put("variable", variable); - info.put("expressionType", "command"); - info.put("command", command_sections); - - returnType = InternalStringArgument.class; - } else { - // expression is code - Expression expression = Expression.parseExpression(rawExpression, argument_variable_classes, localDebug); - returnType = expression.getEvaluationType(argument_variable_classes); - - info = new HashMap<>(); - - info.put("variable", variable); - info.put("expressionType", "expression"); - info.put("expression", expression); - } - - if (argument_keys.contains(variable)) { - Class currentType = argument_variable_classes.get(variable); - if (!currentType.equals(returnType)) { - throw new InvalidSetCommand(command, "Wrong type. Set variable(" + variable + - ") was previously made as " + currentType.getSimpleName() + - ", but is now being set as " + returnType.getSimpleName()); - } - ConfigCommandsHandler.logDebug(localDebug, "%s already found in argument keys, and the return type matches.", variable); - } else { - argument_keys.add(variable); - argument_variable_classes.put(variable, returnType); - ConfigCommandsHandler.logDebug("%s not found in arguments keys, so it was created to match return type.", variable); - } - - HashMap new_command = new HashMap<>(); - new_command.put("type", "set"); - new_command.put("info", info); - commands.add(new_command); - } - - private void parse_do(String command) throws RegistrationException { - if (!command.startsWith("do ")) throw new InvalidDoCommand(command, "Invalid format. Must start with \"do \"."); - - command = command.substring(3); - ConfigCommandsHandler.logDebug(localDebug, "Do trimmed off to get: %s", command); - - Expression expression = Expression.parseExpression(command, argument_variable_classes, localDebug); - - HashMap info = new HashMap<>(); - - info.put("expression", expression); - - HashMap new_command = new HashMap<>(); - new_command.put("type", "do"); - new_command.put("info", info); - commands.add(new_command); - } - - private void parse_tag(String command, int index) throws RegistrationException{ - if(!command.startsWith("tag ")) throw new InvalidExpressionCommand("tag", command, "Invalid format. Must start with \"tag\""); - - String tag = command.substring(4); - ConfigCommandsHandler.logDebug(localDebug, "Tag trimmed off to get: %s", tag); - ConfigCommandsHandler.logDebug(localDebug, "Tag will have index: %s", index); - tagMap.put(tag, index); - - HashMap new_command = new HashMap<>(); - new_command.put("type", "tag"); - commands.add(new_command); - } - - private void parse_if(String command) throws RegistrationException { - if (!command.startsWith("if ")) throw new InvalidIfCommand(command, "Invalid format. Must start with \"if \""); - - command = command.substring(3); - ConfigCommandsHandler.logDebug(localDebug, "If trimmed off to get: %s", command); - - String[] parts = command.split(" goto "); - if (parts.length != 2) throw new InvalidIfCommand(command, "Invalid format. Must contain \" goto \" once."); - ConfigCommandsHandler.logDebug(localDebug, "If split into: %s", Arrays.toString(parts)); - - String booleanString = parts[0]; - ConfigCommandsHandler.logDebug(localDebug, "booleanExpression is: %s", booleanString); - Expression booleanExpression = Expression.parseExpression(booleanString, argument_variable_classes, localDebug); - ConfigCommandsHandler.logDebug(localDebug, "booleanExpression parsed to: %s", booleanExpression); - Class returnType = booleanExpression.getEvaluationType(argument_variable_classes); - if (!returnType.isAssignableFrom(InternalBooleanArgument.class)) - throw new InvalidIfCommand(command, "Invalid booleanExpression. Must return InternalBooleanArgument, but instead returns " + returnType.getSimpleName()); - ConfigCommandsHandler.logDebug(localDebug, "booleanExpression correctly returns a boolean"); - - String indexString = parts[1]; - ConfigCommandsHandler.logDebug("indexExpression is: %s", indexString); - Expression indexExpression = Expression.parseExpression(indexString, argument_variable_classes, localDebug); - ConfigCommandsHandler.logDebug(localDebug, "indexExpression parsed to: %s", indexExpression); - returnType = indexExpression.getEvaluationType(argument_variable_classes); - - HashMap info = new HashMap<>(); - if(returnType.isAssignableFrom(InternalIntegerArgument.class)){ - ConfigCommandsHandler.logDebug(localDebug, "indexExpression correctly returns an integer"); - info.put("indexType", "integer"); - } else if(returnType.isAssignableFrom(InternalStringArgument.class)){ - ConfigCommandsHandler.logDebug(localDebug, "indexExpression correctly returns a string"); - info.put("indexType", "string"); - } else { - throw new InvalidIfCommand(command, "Invalid indexExpression. Must return InternalIntegerArgument or InternalStringArgument, but instead returns " + returnType.getSimpleName()); - } - info.put("indexExpression", indexExpression); - info.put("booleanExpression", booleanExpression); - - HashMap new_command = new HashMap<>(); - new_command.put("type", "if"); - new_command.put("info", info); - commands.add(new_command); - } - - private void parse_goto(String command) throws RegistrationException { - if (!command.startsWith("goto ")) - throw new InvalidGotoCommand(command, "Invalid format. Must start with \"goto \""); - - String indexString = command.substring(5); - ConfigCommandsHandler.logDebug(localDebug, "Goto trimmed off to get: %s", indexString); - - ConfigCommandsHandler.logDebug(localDebug, "indexExpression is: %s", indexString); - Expression indexExpression = Expression.parseExpression(indexString, argument_variable_classes, localDebug); - ConfigCommandsHandler.logDebug(localDebug, "indexExpression parsed to: %s", indexExpression); - Class returnType = indexExpression.getEvaluationType(argument_variable_classes); - - HashMap info = new HashMap<>(); - if(returnType.isAssignableFrom(InternalIntegerArgument.class)){ - ConfigCommandsHandler.logDebug(localDebug, "indexExpression correctly returns an integer"); - info.put("indexType", "integer"); - } else if(returnType.isAssignableFrom(InternalStringArgument.class)){ - ConfigCommandsHandler.logDebug(localDebug, "indexExpression correctly returns a string"); - info.put("indexType", "string"); - } else { - throw new InvalidIfCommand(command, "Invalid indexExpression. Must return InternalIntegerArgument or InternalStringArgument, but instead returns " + returnType.getSimpleName()); - } - info.put("indexExpression", indexExpression); - - HashMap new_command = new HashMap<>(); - new_command.put("type", "goto"); - new_command.put("info", info); - commands.add(new_command); - } - - private void parse_return(String command) throws RegistrationException { - if (!command.startsWith("return ")) - throw new InvalidReturnCommand(command, "Invalid format. Must start with \"return \""); - - String returnString = command.substring(7); - ConfigCommandsHandler.logDebug(localDebug, "Return trimmed off to get: %s", returnString); - - ConfigCommandsHandler.logDebug(localDebug, "returnExpression is: %s", returnString); - Expression returnExpression = Expression.parseExpression(returnString, argument_variable_classes, localDebug); - ConfigCommandsHandler.logDebug(localDebug, "returnExpression parsed to: %s", returnExpression); - - HashMap info = new HashMap<>(); - - info.put("returnExpression", returnExpression); - - HashMap new_command = new HashMap<>(); - new_command.put("type", "return"); - new_command.put("info", info); - commands.add(new_command); - } - - public void execute(CommandSender sender, Object[] args) { - executor.copy(argument_variable_classes).execute(sender, args); - } -} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/ConfigCommandExecutor.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/ConfigCommandExecutor.java deleted file mode 100644 index ae42ffb..0000000 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/ConfigCommandExecutor.java +++ /dev/null @@ -1,262 +0,0 @@ -package me.willkroboth.ConfigCommands.RegisteredCommands; - -import me.willkroboth.ConfigCommands.ConfigCommandsHandler; -import me.willkroboth.ConfigCommands.InternalArguments.InternalArgument; -import me.willkroboth.ConfigCommands.InternalArguments.InternalCommandSenderArgument; -import me.willkroboth.ConfigCommands.InternalArguments.InternalStringArgument; -import me.willkroboth.ConfigCommands.Exceptions.CommandRunException; -import org.bukkit.command.CommandException; -import org.bukkit.command.CommandSender; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.*; - -public class ConfigCommandExecutor { - private final String name; - - private final ArrayList argument_keys; - private final HashMap argument_variables; - - private final ArrayList> commands; - - private final Map tagMap; - - private final boolean localDebug; - - public ConfigCommandExecutor(String name, ArrayList argument_keys, ArrayList> commands, - Map tagMap, boolean localDebug) { - this.name = name; - - this.argument_keys = argument_keys; - this.argument_variables = new HashMap<>(); - - this.commands = commands; - - this.tagMap = tagMap; - - this.localDebug = localDebug; - } - - public ConfigCommandExecutor(String name, ArrayList argument_keys, HashMap argument_variables, - ArrayList> commands, Map tagMap, boolean localDebug) { - this.name = name; - - this.argument_keys = argument_keys; - this.argument_variables = argument_variables; - - this.commands = commands; - this.tagMap = tagMap; - - this.localDebug = localDebug; - } - - public ConfigCommandExecutor copy(HashMap> argument_variable_classes) { - HashMap newArgumentVariables = new HashMap<>(); - for (String argName : argument_variable_classes.keySet()) { - InternalArgument newArg = InternalArgument.getInternalArgument(argument_variable_classes.get(argName)); - newArgumentVariables.put(argName, newArg); - } - - return new ConfigCommandExecutor(name, argument_keys, newArgumentVariables, commands, tagMap, localDebug); - } - - public void execute(CommandSender sender, Object[] args) { - int startIndentation = ConfigCommandsHandler.getIndentation(); - try { - ConfigCommandsHandler.logDebug(localDebug, "Running ConfigCommand %s with args: %s", name, Arrays.deepToString(args)); - - // setup default args - argument_variables.get("").setValue(sender); - ConfigCommandsHandler.logDebug(localDebug, " set to %s", argument_variables.get("").getValue()); - - int numDefaultArgs = ConfigCommandBuilder.getDefaultArgs().size(); - // setup variable hashmap - for (int i = 0; i < args.length; i++) { - argument_variables.get(argument_keys.get(i + numDefaultArgs)).setValue(args[i]); - ConfigCommandsHandler.logDebug(localDebug, argument_keys.get(i + numDefaultArgs) + " set to " + args[i].toString()); - } - - //run commands - if (localDebug) { - ConfigCommandsHandler.logNormal("Commands are:"); - ConfigCommandsHandler.increaseIndentation(); - for (int commandIndex = 0; commandIndex < this.commands.size(); commandIndex++) { - ConfigCommandsHandler.logNormal("%s: %s", commandIndex, this.commands.get(commandIndex)); - } - ConfigCommandsHandler.decreaseIndentation(); - } - - for (int commandIndex = 0; commandIndex < this.commands.size(); commandIndex++) { - if (commandIndex < 0) break; // may occur if a branch returns a negative value or after a return - argument_variables.get("").setValue(commandIndex); - ConfigCommandsHandler.logDebug(localDebug, " set to %s", commandIndex); - - HashMap rawCommand = this.commands.get(commandIndex); - - String type = (String) rawCommand.get("type"); - ConfigCommandsHandler.logDebug(localDebug, "Running %s", type); - - ConfigCommandsHandler.increaseIndentation(); - switch (type) { - case "command" -> run_command((List) rawCommand.get("info")); - case "set" -> run_set((HashMap) rawCommand.get("info")); - case "do" -> run_do((HashMap) rawCommand.get("info")); - case "tag" -> ConfigCommandsHandler.logDebug(localDebug, "Skipping over tag"); - case "if" -> commandIndex = run_if((HashMap) rawCommand.get("info")) - 1; - case "goto" -> commandIndex = run_goto((HashMap) rawCommand.get("info")) - 1; - case "return" -> { - run_return((HashMap) rawCommand.get("info")); - commandIndex = -2; // ends execution with negative commandIndex - } - } - ConfigCommandsHandler.decreaseIndentation(); - } - } catch (Throwable e) { - if (localDebug) { - ConfigCommandsHandler.logNormal("Error occurred while running the command: %s", e.getMessage()); - StringWriter stackTrace = new StringWriter(); - e.printStackTrace(new PrintWriter(stackTrace)); - ConfigCommandsHandler.logNormal(stackTrace.toString()); - } - sender.sendMessage("Error occurred while running the command: " + e.getMessage()); - } finally { - // always reset indentation - ConfigCommandsHandler.setIndentation(startIndentation); - } - } - - private String run_command(List parts) throws CommandRunException { - ConfigCommandsHandler.logDebug(localDebug, "Command has parts: %s", parts.toString()); - StringBuilder command = new StringBuilder(); - boolean variable_section = false; - for (String piece : parts) { - if (variable_section) { - command.append(argument_variables.get(piece).forCommand()); - } else { - command.append(piece); - } - variable_section = !variable_section; - } - ConfigCommandsHandler.logDebug(localDebug, "Command built as: %s", command); - - InternalCommandSenderArgument sender = (InternalCommandSenderArgument) argument_variables.get(""); - - List commandParameter = Collections.singletonList(new InternalStringArgument(command.toString())); - - try { - ConfigCommandsHandler.increaseIndentation(); - String result = (String) sender.runFunction("dispatchCommand", commandParameter).getValue(); - ConfigCommandsHandler.decreaseIndentation(); - ConfigCommandsHandler.logDebug(localDebug, "Command result: \"%s\"", result); - return result; - } catch (CommandException e) { - List messageParameter = Collections.singletonList(new InternalStringArgument("Invalid command: " + command)); - sender.runFunction("sendMessage", messageParameter); - throw e; - } - } - - private void run_set(HashMap info) throws CommandRunException { - String variableName = (String) info.get("variable"); - InternalArgument variable = argument_variables.get(variableName); - ConfigCommandsHandler.logDebug(localDebug, "Variable is %s", variableName); - - String expressionType = (String) info.get("expressionType"); - ConfigCommandsHandler.logDebug(localDebug, "expressionType is %s", expressionType); - - switch (expressionType) { - case "expression" -> { - Expression expression = (Expression) info.get("expression"); - ConfigCommandsHandler.logDebug(localDebug, "Expression is %s", expression); - ConfigCommandsHandler.increaseIndentation(); - InternalArgument result = expression.evaluate(argument_variables, localDebug); - ConfigCommandsHandler.decreaseIndentation(); - ConfigCommandsHandler.logDebug(localDebug, "Variable will be set to: %s", result.getValue()); - variable.setValue(result); - } - case "command" -> { - String stringResult = run_command((List) info.get("command")); - ConfigCommandsHandler.logDebug(localDebug, "Variable will be set to: %s", stringResult); - variable.setValue(stringResult); - } - } - } - - private void run_do(HashMap info) throws CommandRunException { - Expression expression = (Expression) info.get("expression"); - ConfigCommandsHandler.logDebug(localDebug, "Expression is %s", expression); - - ConfigCommandsHandler.increaseIndentation(); - expression.evaluate(argument_variables, localDebug); - ConfigCommandsHandler.decreaseIndentation(); - } - - private int run_if(HashMap info) throws CommandRunException { - Expression booleanExpression = (Expression) info.get("booleanExpression"); - ConfigCommandsHandler.logDebug(localDebug, "BooleanExpression is: %s", booleanExpression); - Expression indexExpression = (Expression) info.get("indexExpression"); - ConfigCommandsHandler.logDebug(localDebug, "IndexExpression is: %s", indexExpression); - - ConfigCommandsHandler.logDebug(localDebug, "Evaluating BooleanExpression"); - ConfigCommandsHandler.increaseIndentation(); - boolean result = (boolean) booleanExpression.evaluate(argument_variables, localDebug).getValue(); - ConfigCommandsHandler.decreaseIndentation(); - ConfigCommandsHandler.logDebug(localDebug, "Boolean evaluated to %s", result); - - int returnIndex = -1; - if (result) { - ConfigCommandsHandler.logDebug(localDebug, "Evaluating IndexExpression"); - ConfigCommandsHandler.increaseIndentation(); - Object value = indexExpression.evaluate(argument_variables, localDebug).getValue(); - switch ((String) info.get("indexType")) { - case "integer" -> returnIndex = (int) value; - case "string" -> { - String target = (String) value; - if (!tagMap.containsKey(target)) - throw new CommandRunException("Tried to jump to tag \"" + target + "\" which was not found."); - returnIndex = tagMap.get(target); - } - } - ConfigCommandsHandler.decreaseIndentation(); - } else { - returnIndex = (int) argument_variables.get("").getValue() + 1; - } - ConfigCommandsHandler.logDebug(localDebug, "Next command index is %s", returnIndex); - - return returnIndex; - } - - private int run_goto(HashMap info) throws CommandRunException { - Expression indexExpression = (Expression) info.get("indexExpression"); - ConfigCommandsHandler.logDebug(localDebug, "IndexExpression is: %s", indexExpression); - ConfigCommandsHandler.increaseIndentation(); - int returnIndex = -1; - Object value = indexExpression.evaluate(argument_variables, localDebug).getValue(); - switch ((String) info.get("indexType")) { - case "integer" -> returnIndex = (int) value; - case "string" -> { - String target = (String) value; - if (!tagMap.containsKey(target)) - throw new CommandRunException("Tried to jump to tag \"" + target + "\" which was not found."); - returnIndex = tagMap.get(target); - } - } - ConfigCommandsHandler.decreaseIndentation(); - ConfigCommandsHandler.logDebug(localDebug, "Next command index is %s", returnIndex); - - return returnIndex; - } - - private void run_return(HashMap info) throws CommandRunException { - Expression expression = (Expression) info.get("returnExpression"); - ConfigCommandsHandler.logDebug(localDebug, "Expression is " + expression); - ConfigCommandsHandler.increaseIndentation(); - String returnValue = expression.evaluate(argument_variables, localDebug).getValue().toString(); - ConfigCommandsHandler.decreaseIndentation(); - - ConfigCommandsHandler.logDebug(localDebug, "Return value is \"" + returnValue + "\""); - List messageParameter = Collections.singletonList(new InternalStringArgument(returnValue)); - argument_variables.get("").runFunction("sendMessage", messageParameter); - } -} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/ExecutesBuilder.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/ExecutesBuilder.java new file mode 100644 index 0000000..e810892 --- /dev/null +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/ExecutesBuilder.java @@ -0,0 +1,74 @@ +package me.willkroboth.ConfigCommands.RegisteredCommands; + +import dev.jorel.commandapi.executors.CommandExecutor; +import me.willkroboth.ConfigCommands.ConfigCommandsHandler; +import me.willkroboth.ConfigCommands.Exceptions.RegistrationException; +import me.willkroboth.ConfigCommands.InternalArguments.InternalArgument; +import me.willkroboth.ConfigCommands.RegisteredCommands.FunctionLines.FunctionLine; +import org.bukkit.command.CommandSender; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.*; + +public class ExecutesBuilder implements CommandExecutor { + private final InterpreterState defaultState; + private final Stack interpreterStateStack; + private InterpreterState currentState; + + public ExecutesBuilder(List executes, Map> argumentClasses, + boolean localDebug) throws RegistrationException { + defaultState = FunctionLine.parseExecutes(executes, new LinkedHashMap<>(argumentClasses), localDebug); + interpreterStateStack = new Stack<>(); + } + + @Override + public void run(CommandSender sender, Object[] args) { + interpreterStateStack.push(currentState); + currentState = defaultState.copy(); + + int startIndentation = ConfigCommandsHandler.getIndentation(); + try { + ConfigCommandsHandler.logDebug(currentState, "Running ConfigCommand with args: %s", Arrays.deepToString(args)); + + currentState.setUpVariablesMap(args); + + // setup default args + currentState.setVariable("", sender); + ConfigCommandsHandler.logDebug(currentState, " set to %s", currentState.getVariable("").getValue()); + + if (currentState.isDebug()) { + ConfigCommandsHandler.logNormal("Code lines are:"); + ConfigCommandsHandler.increaseIndentation(); + for (int lineIndex = 0; lineIndex < currentState.getLines().size(); lineIndex++) { + ConfigCommandsHandler.logNormal("%s: %s", lineIndex, currentState.getLines().get(lineIndex)); + } + ConfigCommandsHandler.decreaseIndentation(); + } + + while (currentState.hasLine()) { + currentState.setVariable("", currentState.getIndex()); + ConfigCommandsHandler.logDebug(currentState, " set to %s", currentState.getIndex()); + + FunctionLine line = currentState.getLine(); + ConfigCommandsHandler.logDebug(currentState, "Executing %s", line); + ConfigCommandsHandler.increaseIndentation(); + currentState.updateIndex(line.run(currentState)); + ConfigCommandsHandler.decreaseIndentation(); + } + } catch (Throwable e) { + if (currentState.isDebug()) { + ConfigCommandsHandler.logNormal("Error occurred while running the command:"); + StringWriter stackTrace = new StringWriter(); + e.printStackTrace(new PrintWriter(stackTrace)); + ConfigCommandsHandler.logNormal(stackTrace.toString()); + } + sender.sendMessage("Error occurred while running the command: " + e.getMessage()); + } finally { + // always reset + ConfigCommandsHandler.setIndentation(startIndentation); + + currentState = interpreterStateStack.pop(); + } + } +} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/Expression.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/Expression.java index 03b1416..f5e6da4 100644 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/Expression.java +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/Expression.java @@ -1,12 +1,11 @@ package me.willkroboth.ConfigCommands.RegisteredCommands; import me.willkroboth.ConfigCommands.ConfigCommandsHandler; -import me.willkroboth.ConfigCommands.InternalArguments.InternalArgument; -import me.willkroboth.ConfigCommands.InternalArguments.InternalStringArgument; import me.willkroboth.ConfigCommands.Exceptions.CommandRunException; import me.willkroboth.ConfigCommands.Exceptions.ParseException; -import me.willkroboth.ConfigCommands.Exceptions.RegistrationException; import me.willkroboth.ConfigCommands.Functions.NonGenericVarargs.ArgList; +import me.willkroboth.ConfigCommands.InternalArguments.InternalArgument; +import me.willkroboth.ConfigCommands.InternalArguments.InternalStringArgument; import java.util.ArrayList; import java.util.HashMap; @@ -24,8 +23,8 @@ public static Map getClassMap() { return staticClassMap; } - public static Expression parseExpression(String string, HashMap> argumentVariables, - boolean localDebug) throws RegistrationException { + public static Expression parseExpression(String string, Map> argumentClasses, + boolean localDebug) throws ParseException { if (string.charAt(0) == '"' && string.charAt(string.length() - 1) == '"') { // basic string for basic initialization return new StringConstant(string.substring(1, string.length() - 1)); @@ -96,7 +95,7 @@ public static Expression parseExpression(String string, HashMap')) throw new ParseException(string, "Target \"" + word + "\" Does not match constant class or variable format."); - if (!argumentVariables.containsKey(word)) + if (!argumentClasses.containsKey(word)) throw new ParseException(string, "Variable \"" + word + "\" dose not exist at this point. Must be declared in usage or earlier set command."); ConfigCommandsHandler.logDebug(localDebug, "Target identified as valid variable."); @@ -143,7 +142,7 @@ public static Expression parseExpression(String string, HashMap')) throw new ParseException(string, "Target \"" + word + "\" Does not match variable format."); - if (!argumentVariables.containsKey(word)) + if (!argumentClasses.containsKey(word)) throw new ParseException(string, "Variable \"" + word + "\" dose not exist at this point. Must be declared in usage or earlier set command."); ConfigCommandsHandler.logDebug(localDebug, "Expression found to be a valid variable reference"); targetExpression = new Variable(word); @@ -273,9 +272,9 @@ public static Expression parseExpression(String string, HashMap getEvaluationType(HashMap> argument_variables); + public abstract Class getEvaluationType(Map> argumentClasses); - public abstract InternalArgument evaluate(HashMap argument_variables, + public abstract InternalArgument evaluate(Map argumentVariables, boolean localDebug) throws CommandRunException; } @@ -294,23 +293,23 @@ public String toString() { return "(" + targetExpression.toString() + ")." + function + "(" + parameterExpressions.toString() + ")"; } - public Class getEvaluationType(HashMap> argument_variables){ - InternalArgument target = InternalArgument.getInternalArgument(targetExpression.getEvaluationType(argument_variables)); + public Class getEvaluationType(Map> argumentClasses){ + InternalArgument target = InternalArgument.getInternalArgument(targetExpression.getEvaluationType(argumentClasses)); ArgList parameters = new ArgList(); for(Expression parameterExpression: parameterExpressions){ - parameters.add(parameterExpression.getEvaluationType(argument_variables)); + parameters.add(parameterExpression.getEvaluationType(argumentClasses)); } return target.getReturnTypeForFunction(function, parameters); } - public InternalArgument evaluate(HashMap argument_variables, boolean localDebug) throws CommandRunException { + public InternalArgument evaluate(Map argumentVariables, boolean localDebug) throws CommandRunException { ConfigCommandsHandler.logDebug(localDebug, "Evaluating FunctionCall"); ConfigCommandsHandler.logDebug(localDebug, "Target expression is: %s", targetExpression); ConfigCommandsHandler.increaseIndentation(); - InternalArgument target = targetExpression.evaluate(argument_variables, localDebug); + InternalArgument target = targetExpression.evaluate(argumentVariables, localDebug); ConfigCommandsHandler.decreaseIndentation(); ConfigCommandsHandler.logDebug(localDebug, "Function is: " + function); @@ -319,7 +318,7 @@ public InternalArgument evaluate(HashMap argument_vari for(Expression parameterExpression: parameterExpressions){ ConfigCommandsHandler.logDebug(localDebug, "Parameter expression is: %s", parameterExpression); ConfigCommandsHandler.increaseIndentation(); - parameters.add(parameterExpression.evaluate(argument_variables, localDebug)); + parameters.add(parameterExpression.evaluate(argumentVariables, localDebug)); ConfigCommandsHandler.decreaseIndentation(); } @@ -347,16 +346,16 @@ public String toString() { return "(" + targetClass.toString() + ")." + function + "(" + parameterExpressions.toString() + ")"; } - public Class getEvaluationType(HashMap> argument_variables){ + public Class getEvaluationType(Map> argumentClasses){ ArgList parameters = new ArgList(); for(Expression parameterExpression: parameterExpressions){ - parameters.add(parameterExpression.getEvaluationType(argument_variables)); + parameters.add(parameterExpression.getEvaluationType(argumentClasses)); } return targetClass.getReturnTypeForStaticFunction(function, parameters); } - public InternalArgument evaluate(HashMap argument_variables, boolean localDebug) throws CommandRunException { + public InternalArgument evaluate(Map argumentVariables, boolean localDebug) throws CommandRunException { ConfigCommandsHandler.logDebug(localDebug, "Evaluating StaticFunctionCall"); ConfigCommandsHandler.logDebug(localDebug, "Target class is: %s", targetClass); @@ -367,7 +366,7 @@ public InternalArgument evaluate(HashMap argument_vari for(Expression parameterExpression: parameterExpressions){ ConfigCommandsHandler.logDebug(localDebug, "Parameter expression is: %s", parameterExpression); ConfigCommandsHandler.increaseIndentation(); - parameters.add(parameterExpression.evaluate(argument_variables, localDebug)); + parameters.add(parameterExpression.evaluate(argumentVariables, localDebug)); ConfigCommandsHandler.decreaseIndentation(); } @@ -387,17 +386,17 @@ class Variable extends Expression{ public String toString() { return name; } - public Class getEvaluationType(HashMap> argument_variables) { - return argument_variables.get(name); + public Class getEvaluationType(Map> argumentClasses) { + return argumentClasses.get(name); } - public InternalArgument evaluate(HashMap argument_variables, boolean localDebug) throws CommandRunException { + public InternalArgument evaluate(Map argumentVariables, boolean localDebug) throws CommandRunException { if (localDebug) { ConfigCommandsHandler.logNormal("Evaluating Variable"); ConfigCommandsHandler.logNormal("Variable name is: %s", name); - ConfigCommandsHandler.logNormal("Class %s with value %s ", argument_variables.get(name).getClass().getSimpleName(), argument_variables.get(name).forCommand()); + ConfigCommandsHandler.logNormal("Class %s with value %s ", argumentVariables.get(name).getClass().getSimpleName(), argumentVariables.get(name).forCommand()); } - return argument_variables.get(name); + return argumentVariables.get(name); } } @@ -409,11 +408,11 @@ public StringConstant(String value){ public String toString() { return "\"" + value.getValue() + "\""; } - public Class getEvaluationType(HashMap> argument_variables) { + public Class getEvaluationType(Map> argumentClasses) { return InternalStringArgument.class; } - public InternalArgument evaluate(HashMap argument_variables, boolean localDebug) throws CommandRunException { + public InternalArgument evaluate(Map argumentVariables, boolean localDebug) throws CommandRunException { ConfigCommandsHandler.logDebug(localDebug, "Evaluating Constant"); ConfigCommandsHandler.logDebug(localDebug, "Constant is %s", this); return value; diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/BranchIf.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/BranchIf.java new file mode 100644 index 0000000..3e764ab --- /dev/null +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/BranchIf.java @@ -0,0 +1,104 @@ +package me.willkroboth.ConfigCommands.RegisteredCommands.FunctionLines; + +import me.willkroboth.ConfigCommands.ConfigCommandsHandler; +import me.willkroboth.ConfigCommands.Exceptions.CommandRunException; +import me.willkroboth.ConfigCommands.Exceptions.FunctionSyntax.InvalidIfCommand; +import me.willkroboth.ConfigCommands.Exceptions.ParseException; +import me.willkroboth.ConfigCommands.InternalArguments.InternalArgument; +import me.willkroboth.ConfigCommands.InternalArguments.InternalBooleanArgument; +import me.willkroboth.ConfigCommands.InternalArguments.InternalIntegerArgument; +import me.willkroboth.ConfigCommands.InternalArguments.InternalStringArgument; +import me.willkroboth.ConfigCommands.RegisteredCommands.CompilerState; +import me.willkroboth.ConfigCommands.RegisteredCommands.Expression; +import me.willkroboth.ConfigCommands.RegisteredCommands.InterpreterState; + +import java.util.Arrays; + +class BranchIf extends FunctionLine { + public static FunctionLine parse(CompilerState compilerState) throws InvalidIfCommand, ParseException { + if (!compilerState.getCommand().startsWith("if ")) + throw new InvalidIfCommand(compilerState.getCommand(), "Invalid format. Must start with \"if \""); + + String command = compilerState.getCommand().substring(3); + ConfigCommandsHandler.logDebug(compilerState, "If trimmed off to get: %s", command); + + String[] parts = command.split(" goto "); + if (parts.length != 2) throw new InvalidIfCommand(command, "Invalid format. Must contain \" goto \" once."); + ConfigCommandsHandler.logDebug(compilerState, "If split into: %s", Arrays.toString(parts)); + + String booleanString = parts[0]; + ConfigCommandsHandler.logDebug(compilerState, "booleanExpression is: %s", booleanString); + Expression booleanExpression = + Expression.parseExpression(booleanString, compilerState.getArgumentClasses(), compilerState.isDebug()); + ConfigCommandsHandler.logDebug(compilerState, "booleanExpression parsed to: %s", booleanExpression); + Class returnType = booleanExpression.getEvaluationType(compilerState.getArgumentClasses()); + if (!returnType.isAssignableFrom(InternalBooleanArgument.class)) + throw new InvalidIfCommand(command, "Invalid booleanExpression. Must return InternalBooleanArgument, but instead returns " + returnType.getSimpleName()); + ConfigCommandsHandler.logDebug(compilerState, "booleanExpression correctly returns a boolean"); + + String indexString = parts[1]; + ConfigCommandsHandler.logDebug("indexExpression is: %s", indexString); + Expression indexExpression = + Expression.parseExpression(indexString, compilerState.getArgumentClasses(), compilerState.isDebug()); + ConfigCommandsHandler.logDebug(compilerState, "indexExpression parsed to: %s", indexExpression); + returnType = indexExpression.getEvaluationType(compilerState.getArgumentClasses()); + + if (returnType.isAssignableFrom(InternalIntegerArgument.class)) { + ConfigCommandsHandler.logDebug(compilerState, "indexExpression correctly returns an integer"); + } else if (returnType.isAssignableFrom(InternalStringArgument.class)) { + ConfigCommandsHandler.logDebug(compilerState, "indexExpression correctly returns a string"); + } else { + throw new InvalidIfCommand(command, "Invalid indexExpression. Must return InternalIntegerArgument or InternalStringArgument, but instead returns " + returnType.getSimpleName()); + } + + return new BranchIf(booleanExpression, indexExpression); + } + + private final Expression booleanExpression; + private final Expression indexExpression; + + private BranchIf(Expression booleanExpression, Expression indexExpression) { + this.booleanExpression = booleanExpression; + this.indexExpression = indexExpression; + } + + @Override + public String toString() { + return "if(" + booleanExpression + ") goto (" + indexExpression + ")"; + } + + @Override + public int run(InterpreterState interpreterState) { + ConfigCommandsHandler.logDebug(interpreterState, "BooleanExpression is: %s", booleanExpression); + ConfigCommandsHandler.logDebug(interpreterState, "IndexExpression is: %s", indexExpression); + + ConfigCommandsHandler.logDebug(interpreterState, "Evaluating BooleanExpression"); + ConfigCommandsHandler.increaseIndentation(); + boolean result = (boolean) + booleanExpression.evaluate(interpreterState.getArgumentVariables(), interpreterState.isDebug()).getValue(); + ConfigCommandsHandler.decreaseIndentation(); + ConfigCommandsHandler.logDebug(interpreterState, "Boolean evaluated to %s", result); + + int returnIndex; + if (result) { + ConfigCommandsHandler.logDebug(interpreterState, "Evaluating IndexExpression"); + ConfigCommandsHandler.increaseIndentation(); + Object value = + indexExpression.evaluate(interpreterState.getArgumentVariables(), interpreterState.isDebug()).getValue(); + if (value instanceof Integer i) { + returnIndex = i; + } else { + String target = (String) value; + if (!interpreterState.hasTag(target)) + throw new CommandRunException("Tried to jump to tag \"" + target + "\" which was not found."); + returnIndex = interpreterState.getTag(target); + } + ConfigCommandsHandler.decreaseIndentation(); + } else { + returnIndex = interpreterState.nextIndex(); + } + ConfigCommandsHandler.logDebug(interpreterState, "Next command index is %s", returnIndex); + + return returnIndex; + } +} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/FunctionLine.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/FunctionLine.java new file mode 100644 index 0000000..77c83fc --- /dev/null +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/FunctionLine.java @@ -0,0 +1,59 @@ +package me.willkroboth.ConfigCommands.RegisteredCommands.FunctionLines; + +import me.willkroboth.ConfigCommands.ConfigCommandsHandler; +import me.willkroboth.ConfigCommands.Exceptions.RegistrationException; +import me.willkroboth.ConfigCommands.InternalArguments.InternalArgument; +import me.willkroboth.ConfigCommands.RegisteredCommands.CompilerState; +import me.willkroboth.ConfigCommands.RegisteredCommands.InterpreterState; + +import java.util.List; +import java.util.Map; + +public abstract class FunctionLine { + public static InterpreterState parseExecutes(List executes, Map> argumentClasses, boolean localDebug) throws RegistrationException { + CompilerState compilerState = new CompilerState().addCommands(executes).addArguments(argumentClasses).setDebug(localDebug); + InterpreterState out = new InterpreterState().setDebug(localDebug); + for (String command : executes) { + ConfigCommandsHandler.logDebug(localDebug, "Parsing command: %s", command); + + ConfigCommandsHandler.increaseIndentation(); + + out.addLine(parseByCharacter.getOrDefault( + command.charAt(0), + (s) -> {throw new RegistrationException("Command not recognized, invalid format: \"" + command + "\"");} + ).parse(compilerState)); + + ConfigCommandsHandler.decreaseIndentation(); + compilerState.increaseIndex(1); + } + out.addTags(compilerState.getTagMap()).setArgumentClasses(compilerState.getArgumentClasses()); + return out; + } + + @FunctionalInterface + private interface ParseRule{ + FunctionLine parse(CompilerState state) throws RegistrationException; + } + + // Commands: + // - Run command, indicated by / + // - define and set variables, indicated by = + // - run functions, indicated by do + // - define branch target tag, indicated by tag + // - conditional branch, indicated by if + // - branch, indicated by goto + // - return value, indicated by return + private static final Map parseByCharacter = Map.of( + '/', RunCommand::parse, + '<', SetVariable::parse, + 'd', RunExpression::parse, + 't', Tag::parse, + 'i', BranchIf::parse, + 'g', Goto::parse, + 'r', Return::parse + ); + + public abstract String toString(); + + public abstract int run(InterpreterState interpreterState); +} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/Goto.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/Goto.java new file mode 100644 index 0000000..49eb768 --- /dev/null +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/Goto.java @@ -0,0 +1,70 @@ +package me.willkroboth.ConfigCommands.RegisteredCommands.FunctionLines; + +import me.willkroboth.ConfigCommands.ConfigCommandsHandler; +import me.willkroboth.ConfigCommands.Exceptions.CommandRunException; +import me.willkroboth.ConfigCommands.Exceptions.FunctionSyntax.InvalidGotoCommand; +import me.willkroboth.ConfigCommands.Exceptions.ParseException; +import me.willkroboth.ConfigCommands.InternalArguments.InternalArgument; +import me.willkroboth.ConfigCommands.InternalArguments.InternalIntegerArgument; +import me.willkroboth.ConfigCommands.InternalArguments.InternalStringArgument; +import me.willkroboth.ConfigCommands.RegisteredCommands.CompilerState; +import me.willkroboth.ConfigCommands.RegisteredCommands.Expression; +import me.willkroboth.ConfigCommands.RegisteredCommands.InterpreterState; + +class Goto extends FunctionLine { + public static FunctionLine parse(CompilerState compilerState) throws InvalidGotoCommand, ParseException { + if (!compilerState.getCommand().startsWith("goto ")) + throw new InvalidGotoCommand(compilerState.getCommand(), "Invalid format. Must start with \"goto \""); + + String indexString = compilerState.getCommand().substring(5); + ConfigCommandsHandler.logDebug(compilerState, "Goto trimmed off to get: %s", indexString); + + ConfigCommandsHandler.logDebug(compilerState, "indexExpression is: %s", indexString); + Expression indexExpression = + Expression.parseExpression(indexString, compilerState.getArgumentClasses(), compilerState.isDebug()); + ConfigCommandsHandler.logDebug(compilerState, "indexExpression parsed to: %s", indexExpression); + Class returnType = indexExpression.getEvaluationType(compilerState.getArgumentClasses()); + + if (returnType.isAssignableFrom(InternalIntegerArgument.class)) { + ConfigCommandsHandler.logDebug(compilerState, "indexExpression correctly returns an integer"); + } else if (returnType.isAssignableFrom(InternalStringArgument.class)) { + ConfigCommandsHandler.logDebug(compilerState, "indexExpression correctly returns a string"); + } else { + throw new InvalidGotoCommand(compilerState.getCommand(), "Invalid indexExpression. Must return InternalIntegerArgument or InternalStringArgument, but instead returns " + returnType.getSimpleName()); + } + + return new Goto(indexExpression); + } + + private final Expression indexExpression; + + private Goto(Expression indexExpression) { + this.indexExpression = indexExpression; + } + + @Override + public String toString() { + return "goto " + indexExpression; + } + + @Override + public int run(InterpreterState interpreterState) { + ConfigCommandsHandler.logDebug(interpreterState, "IndexExpression is: %s", indexExpression); + ConfigCommandsHandler.increaseIndentation(); + Object value = indexExpression.evaluate(interpreterState.getArgumentVariables(), interpreterState.isDebug()).getValue(); + + int returnIndex; + if (value instanceof Integer i) { + returnIndex = i; + } else { + String target = (String) value; + if (!interpreterState.hasTag(target)) + throw new CommandRunException("Tried to jump to tag \"" + target + "\" which was not found."); + returnIndex = interpreterState.getTag(target); + } + ConfigCommandsHandler.decreaseIndentation(); + ConfigCommandsHandler.logDebug(interpreterState, "Next command index is %s", returnIndex); + + return returnIndex; + } +} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/Return.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/Return.java new file mode 100644 index 0000000..f8f14e2 --- /dev/null +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/Return.java @@ -0,0 +1,56 @@ +package me.willkroboth.ConfigCommands.RegisteredCommands.FunctionLines; + +import me.willkroboth.ConfigCommands.ConfigCommandsHandler; +import me.willkroboth.ConfigCommands.Exceptions.FunctionSyntax.InvalidReturnCommand; +import me.willkroboth.ConfigCommands.Exceptions.ParseException; +import me.willkroboth.ConfigCommands.InternalArguments.InternalArgument; +import me.willkroboth.ConfigCommands.InternalArguments.InternalStringArgument; +import me.willkroboth.ConfigCommands.RegisteredCommands.CompilerState; +import me.willkroboth.ConfigCommands.RegisteredCommands.Expression; +import me.willkroboth.ConfigCommands.RegisteredCommands.InterpreterState; + +import java.util.Collections; +import java.util.List; + +class Return extends FunctionLine { + public static FunctionLine parse(CompilerState compilerState) throws InvalidReturnCommand, ParseException { + if (!compilerState.getCommand().startsWith("return ")) + throw new InvalidReturnCommand(compilerState.getCommand(), "Invalid format. Must start with \"return \""); + + String returnString = compilerState.getCommand().substring(7); + ConfigCommandsHandler.logDebug(compilerState, "Return trimmed off to get: %s", returnString); + + ConfigCommandsHandler.logDebug(compilerState, "returnExpression is: %s", returnString); + Expression returnExpression = + Expression.parseExpression(returnString, compilerState.getArgumentClasses(), compilerState.isDebug()); + ConfigCommandsHandler.logDebug(compilerState, "returnExpression parsed to: %s", returnExpression); + + return new Return(returnExpression); + } + + private final Expression returnExpression; + + private Return(Expression returnExpression) { + this.returnExpression = returnExpression; + } + + @Override + public String toString() { + return "return " + returnExpression; + } + + @Override + public int run(InterpreterState interpreterState) { + ConfigCommandsHandler.logDebug(interpreterState, "Expression is " + returnExpression); + ConfigCommandsHandler.increaseIndentation(); + String returnValue = + returnExpression.evaluate(interpreterState.getArgumentVariables(), interpreterState.isDebug()).getValue().toString(); + ConfigCommandsHandler.decreaseIndentation(); + + ConfigCommandsHandler.logDebug(interpreterState, "Return value is \"" + returnValue + "\""); + List messageParameter = Collections.singletonList(new InternalStringArgument(returnValue)); + interpreterState.getVariable("").runFunction("sendMessage", messageParameter); + + return -1; + } +} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/RunCommand.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/RunCommand.java new file mode 100644 index 0000000..3cb6031 --- /dev/null +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/RunCommand.java @@ -0,0 +1,118 @@ +package me.willkroboth.ConfigCommands.RegisteredCommands.FunctionLines; + +import me.willkroboth.ConfigCommands.ConfigCommandsHandler; +import me.willkroboth.ConfigCommands.InternalArguments.InternalArgument; +import me.willkroboth.ConfigCommands.InternalArguments.InternalCommandSenderArgument; +import me.willkroboth.ConfigCommands.InternalArguments.InternalStringArgument; +import me.willkroboth.ConfigCommands.RegisteredCommands.CompilerState; +import me.willkroboth.ConfigCommands.RegisteredCommands.InterpreterState; +import org.bukkit.command.CommandException; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +class RunCommand extends FunctionLine { + public static FunctionLine parse(CompilerState compilerState) { + List commandSections = getCommandSections(compilerState.getCommand(), compilerState); + + return new RunCommand(commandSections); + } + + public static List getCommandSections(String command, CompilerState compilerState) { + List command_sections = new ArrayList<>(); + String[] keys = compilerState.getArgumentClasses().keySet().toArray(new String[0]); + + int previous_index = 1; //start at 1 to get rid of initial / + intPair pair = get_first_index_and_length(command, keys); + int index = pair.first; + int length = pair.last; + + while (index != -1) { + command_sections.add(command.substring(previous_index, index)); + command_sections.add(command.substring(index, index + length)); + + previous_index = index + length; + pair = get_first_index_and_length(command, keys, previous_index); + index = pair.first; + length = pair.last; + } + if (previous_index != command.length()) { + command_sections.add(command.substring(previous_index)); + } + + ConfigCommandsHandler.logDebug(compilerState, "Command has been split into: %s", command_sections); + return command_sections; + } + + private static intPair get_first_index_and_length(String string, String[] keys) { + return get_first_index_and_length(string, keys, 0); + } + + private static intPair get_first_index_and_length(String string, String[] keys, int from_index) { + int least = string.length(); + int length = -1; + + for (String key : keys) { + int index = string.indexOf(key, from_index); + if (index != -1 && index < least) { + least = index; + length = key.length(); + } + } + + if (least == string.length()) return new intPair(-1, -1); + return new intPair(least, length); + } + + private record intPair(int first, int last) { + } + + private final List commandSections; + + private RunCommand(List commandSections) { + this.commandSections = commandSections; + } + + @Override + public String toString() { + return "/" + commandSections; + } + + @Override + public int run(InterpreterState interpreterState) { + runCommandGetResult(commandSections, interpreterState); + + return interpreterState.nextIndex(); + } + + public static String runCommandGetResult(List commandSections, InterpreterState interpreterState) { + ConfigCommandsHandler.logDebug(interpreterState, "Command has parts: %s", commandSections); + + StringBuilder command = new StringBuilder(); + boolean variable_section = false; + for (String section : commandSections) { + if (variable_section) { + command.append(interpreterState.getVariable(section).forCommand()); + } else { + command.append(section); + } + variable_section = !variable_section; + } + ConfigCommandsHandler.logDebug(interpreterState, "Command built as: %s", command); + + InternalCommandSenderArgument sender = (InternalCommandSenderArgument) interpreterState.getVariable(""); + List commandParameter = Collections.singletonList(new InternalStringArgument(command.toString())); + try { + ConfigCommandsHandler.increaseIndentation(); + String result = (String) sender.runFunction("dispatchCommand", commandParameter).getValue(); + ConfigCommandsHandler.decreaseIndentation(); + ConfigCommandsHandler.logDebug(interpreterState, "Command result: \"%s\"", result); + return result; + } catch (CommandException e) { + List messageParameter = Collections.singletonList(new InternalStringArgument("Invalid command: " + command)); + sender.runFunction("sendMessage", messageParameter); + throw e; + } + } +} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/RunExpression.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/RunExpression.java new file mode 100644 index 0000000..ceb4bd4 --- /dev/null +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/RunExpression.java @@ -0,0 +1,44 @@ +package me.willkroboth.ConfigCommands.RegisteredCommands.FunctionLines; + +import me.willkroboth.ConfigCommands.ConfigCommandsHandler; +import me.willkroboth.ConfigCommands.Exceptions.FunctionSyntax.InvalidRunExpression; +import me.willkroboth.ConfigCommands.Exceptions.ParseException; +import me.willkroboth.ConfigCommands.RegisteredCommands.CompilerState; +import me.willkroboth.ConfigCommands.RegisteredCommands.Expression; +import me.willkroboth.ConfigCommands.RegisteredCommands.InterpreterState; + +class RunExpression extends FunctionLine { + public static FunctionLine parse(CompilerState compilerState) throws InvalidRunExpression, ParseException { + if (!compilerState.getCommand().startsWith("do ")) + throw new InvalidRunExpression(compilerState.getCommand(), "Invalid format. Must start with \"do \"."); + + String command = compilerState.getCommand().substring(3); + ConfigCommandsHandler.logDebug(compilerState, "Do trimmed off to get: %s", command); + + Expression expression = Expression.parseExpression(command, compilerState.getArgumentClasses(), compilerState.isDebug()); + + return new RunExpression(expression); + } + + private final Expression expression; + + private RunExpression(Expression expression) { + this.expression = expression; + } + + @Override + public String toString() { + return "do " + expression; + } + + @Override + public int run(InterpreterState interpreterState) { + ConfigCommandsHandler.logDebug(interpreterState, "Expression is %s", expression); + + ConfigCommandsHandler.increaseIndentation(); + expression.evaluate(interpreterState.getArgumentVariables(), interpreterState.isDebug()); + ConfigCommandsHandler.decreaseIndentation(); + + return interpreterState.nextIndex(); + } +} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/SetVariable.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/SetVariable.java new file mode 100644 index 0000000..9628db4 --- /dev/null +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/SetVariable.java @@ -0,0 +1,108 @@ +package me.willkroboth.ConfigCommands.RegisteredCommands.FunctionLines; + +import me.willkroboth.ConfigCommands.ConfigCommandsHandler; +import me.willkroboth.ConfigCommands.Exceptions.FunctionSyntax.InvalidSetVariable; +import me.willkroboth.ConfigCommands.Exceptions.ParseException; +import me.willkroboth.ConfigCommands.InternalArguments.InternalArgument; +import me.willkroboth.ConfigCommands.InternalArguments.InternalStringArgument; +import me.willkroboth.ConfigCommands.RegisteredCommands.CompilerState; +import me.willkroboth.ConfigCommands.RegisteredCommands.Expression; +import me.willkroboth.ConfigCommands.RegisteredCommands.InterpreterState; + +import java.util.Arrays; +import java.util.List; + +class SetVariable extends FunctionLine { + public static FunctionLine parse(CompilerState compilerState) throws InvalidSetVariable, ParseException { + String[] parts = compilerState.getCommand().split(" = "); + if (parts.length != 2) + throw new InvalidSetVariable(compilerState.getCommand(), "Invalid format. Must contain only one \" = \"."); + + ConfigCommandsHandler.logDebug(compilerState, "Set split into: %s", Arrays.toString(parts)); + + String variable = parts[0]; + if (!(variable.charAt(0) == '<' && variable.charAt(variable.length() - 1) == '>')) { + throw new InvalidSetVariable(compilerState.getCommand(), "Invalid variable: " + variable + ". Must be wrapped by < >."); + } + ConfigCommandsHandler.logDebug(compilerState, "Variable is " + variable); + + String rawExpression = parts[1]; + Class returnType; + boolean usingExpression = !rawExpression.startsWith("/"); + Object value; + if (usingExpression) { + // expression is code + ConfigCommandsHandler.logDebug(compilerState, "Parsing \"%s\" as expression.", rawExpression); + Expression expression = Expression.parseExpression(rawExpression, compilerState.getArgumentClasses(), compilerState.isDebug()); + returnType = expression.getEvaluationType(compilerState.getArgumentClasses()); + + value = expression; + } else { + // expression is command + ConfigCommandsHandler.logDebug(compilerState, "Expression looks like a command."); + ConfigCommandsHandler.logDebug(compilerState, "Parsing \"%s\" as command.", rawExpression); + + // parse command + List commandSections = RunCommand.getCommandSections(rawExpression, compilerState); + returnType = InternalStringArgument.class; + + value = commandSections; + } + + if (compilerState.hasVariable(variable)) { + Class currentType = compilerState.getVariable(variable); + if (!returnType.isAssignableFrom(currentType)) { + throw new InvalidSetVariable(compilerState.getCommand(), "Wrong type. Set variable(" + variable + + ") was previously made as " + currentType.getSimpleName() + + ", but is now being set as " + returnType.getSimpleName()); + } + ConfigCommandsHandler.logDebug(compilerState, "%s already found in argument keys, and the return type matches.", variable); + } else { + compilerState.addArgument(variable, returnType); + ConfigCommandsHandler.logDebug("%s not found in arguments keys, so it was created to match return type.", variable); + } + + return new SetVariable(variable, usingExpression, value); + } + + private final String variableName; + private final boolean usingExpression; + private final Object value; + + private SetVariable(String variableName, boolean usingExpression, Object value) { + this.variableName = variableName; + this.usingExpression = usingExpression; + this.value = value; + } + + @Override + public String toString() { + return variableName + " = " + value.toString(); + } + + @Override + public int run(InterpreterState interpreterState) { + ConfigCommandsHandler.logDebug(interpreterState, "Variable is %s", variableName); + ConfigCommandsHandler.logDebug(interpreterState, "expressionType is %s", usingExpression ? "expression" : "command"); + + if (usingExpression) { + Expression expression = (Expression) value; + ConfigCommandsHandler.logDebug(interpreterState, "Expression is %s", expression); + + ConfigCommandsHandler.increaseIndentation(); + InternalArgument result = expression.evaluate(interpreterState.getArgumentVariables(), interpreterState.isDebug()); + ConfigCommandsHandler.decreaseIndentation(); + + ConfigCommandsHandler.logDebug(interpreterState, "Variable will be set to: %s", result.getValue()); + interpreterState.setVariable(variableName, result); + } else { + @SuppressWarnings("unchecked") + String stringResult = RunCommand.runCommandGetResult((List) value, interpreterState); + + ConfigCommandsHandler.logDebug(interpreterState, "Variable will be set to: %s", stringResult); + interpreterState.setVariable(variableName, stringResult); + } + + return interpreterState.nextIndex(); + } +} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/Tag.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/Tag.java new file mode 100644 index 0000000..afe511a --- /dev/null +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/FunctionLines/Tag.java @@ -0,0 +1,38 @@ +package me.willkroboth.ConfigCommands.RegisteredCommands.FunctionLines; + +import me.willkroboth.ConfigCommands.ConfigCommandsHandler; +import me.willkroboth.ConfigCommands.Exceptions.FunctionSyntax.InvalidFunctionLine; +import me.willkroboth.ConfigCommands.RegisteredCommands.CompilerState; +import me.willkroboth.ConfigCommands.RegisteredCommands.InterpreterState; + +class Tag extends FunctionLine { + public static FunctionLine parse(CompilerState compilerState) throws InvalidFunctionLine { + if (!compilerState.getCommand().startsWith("tag ")) + throw new InvalidFunctionLine("tag", compilerState.getCommand(), "Invalid format. Must start with \"tag \""); + + String tag = compilerState.getCommand().substring(4); + ConfigCommandsHandler.logDebug(compilerState, "Tag trimmed off to get: %s", tag); + ConfigCommandsHandler.logDebug(compilerState, "Tag will have index: %s", compilerState.getIndex()); + compilerState.addTag(tag, compilerState.getIndex()); + + return new Tag(tag); + } + + private final String name; + + private Tag(String name) { + this.name = name; + } + + @Override + public String toString() { + return "tag " + name; + } + + @Override + public int run(InterpreterState interpreterState) { + ConfigCommandsHandler.logDebug(interpreterState, "Skipping over tag"); + + return interpreterState.nextIndex(); + } +} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/InterpreterState.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/InterpreterState.java new file mode 100644 index 0000000..16267dc --- /dev/null +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/RegisteredCommands/InterpreterState.java @@ -0,0 +1,179 @@ +package me.willkroboth.ConfigCommands.RegisteredCommands; + +import me.willkroboth.ConfigCommands.ConfigCommandsHandler; +import me.willkroboth.ConfigCommands.HelperClasses.DebuggableState; +import me.willkroboth.ConfigCommands.InternalArguments.InternalArgument; +import me.willkroboth.ConfigCommands.RegisteredCommands.FunctionLines.FunctionLine; + +import java.util.*; + +public class InterpreterState implements DebuggableState { + public InterpreterState() { + lines = new ArrayList<>(); + line = null; + argumentClasses = new HashMap<>(); + argumentVariables = new LinkedHashMap<>(); + tagMap = new LinkedHashMap<>(); + index = 0; + localDebug = false; + } + + public InterpreterState copy() { + return new InterpreterState(this); + } + + private InterpreterState(InterpreterState toCopy) { + this.lines = toCopy.lines; + this.line = toCopy.line; + this.argumentClasses = toCopy.argumentClasses; + this.argumentVariables = new HashMap<>(toCopy.argumentVariables); + this.tagMap = toCopy.tagMap; + this.index = toCopy.index; + this.localDebug = toCopy.localDebug; + } + + private final List lines; + + public InterpreterState addLine(FunctionLine line) { + lines.add(line); + if (this.line == null && lines.size() > index) this.line = lines.get(index); + return this; + } + + public InterpreterState addLines(List lines) { + this.lines.addAll(lines); + if (line == null && this.lines.size() > index) line = this.lines.get(index); + return this; + } + + public List getLines() { + return lines; + } + + private FunctionLine line; + + public boolean hasLine() { + return line != null; + } + + public FunctionLine getLine() { + return line; + } + + private final Map argumentVariables; + private Map> argumentClasses; + + public InterpreterState setArgumentClasses(Map> argumentClasses){ + this.argumentClasses = argumentClasses; + return this; + } + + public InterpreterState setUpVariablesMap(Object[] args) { + int i = 0; + int numDefaultArgs = CommandTreeBuilder.getDefaultArgs().size(); + for (Map.Entry> toAdd : argumentClasses.entrySet()) { + argumentVariables.put(toAdd.getKey(), InternalArgument.getInternalArgument(toAdd.getValue())); + + ConfigCommandsHandler.logDebug(localDebug, "Added argument %s with class %s", toAdd.getKey(), toAdd.getValue().getSimpleName()); + + if (i >= numDefaultArgs && i - numDefaultArgs < args.length) { + argumentVariables.get(toAdd.getKey()).setValue(args[i - numDefaultArgs]); + ConfigCommandsHandler.logDebug(localDebug, "%s set to %s", toAdd.getKey(), args[i - numDefaultArgs]); + } + i++; + } + return this; + } + + public InterpreterState addArgument(String name, InternalArgument object) { + argumentVariables.put(name, object); + return this; + } + + public InterpreterState addArguments(Map arguments) { + argumentVariables.putAll(arguments); + return this; + } + + public InterpreterState setVariable(String name, InternalArgument value) { + argumentVariables.get(name).setValue(value); + return this; + } + + public InterpreterState setVariable(String name, Object value) { + argumentVariables.get(name).setValue(value); + return this; + } + + public Map getArgumentVariables() { + return argumentVariables; + } + + public boolean hasVariable(String name) { + return argumentVariables.containsKey(name); + } + + public InternalArgument getVariable(String name) { + return argumentVariables.get(name); + } + + private final Map tagMap; + + public InterpreterState addTag(String name, int index) { + tagMap.put(name, index); + return this; + } + + public InterpreterState addTags(Map tags) { + tagMap.putAll(tags); + return this; + } + + public Map getTagMap() { + return tagMap; + } + + public boolean hasTag(String tag) { + return tagMap.containsKey(tag); + } + + public Integer getTag(String tag) { + return tagMap.get(tag); + } + + private int index; + + public InterpreterState updateIndex(int index) { + this.index = index; + if (0 <= index && index < lines.size()) { + line = lines.get(index); + } else { + line = null; + } + return this; + } + + public InterpreterState increaseIndex(int amount) { + updateIndex(index + amount); + return this; + } + + public int getIndex() { + return index; + } + + public int nextIndex() { + return index + 1; + } + + private boolean localDebug; + + public InterpreterState setDebug(boolean debug) { + localDebug = debug; + return this; + } + + public boolean isDebug() { + return localDebug; + } +} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/SystemCommands/BuildCommandHandler.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/SystemCommands/BuildCommandHandler.java index 6b5a35d..ea8b5a7 100644 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/SystemCommands/BuildCommandHandler.java +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/SystemCommands/BuildCommandHandler.java @@ -1,768 +1,768 @@ -package me.willkroboth.ConfigCommands.SystemCommands; - -import dev.jorel.commandapi.ArgumentTree; -import dev.jorel.commandapi.CommandAPICommand; -import dev.jorel.commandapi.arguments.Argument; -import dev.jorel.commandapi.executors.ExecutorType; -import me.willkroboth.ConfigCommands.ConfigCommandsHandler; -import me.willkroboth.ConfigCommands.Exceptions.IncorrectArgumentKey; -import me.willkroboth.ConfigCommands.RegisteredCommands.ConfigCommandBuilder; -import me.willkroboth.ConfigCommands.InternalArguments.InternalArgument; -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.AsyncPlayerChatEvent; -import org.bukkit.event.player.PlayerCommandPreprocessEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.event.server.ServerCommandEvent; - -import java.util.*; - -public class BuildCommandHandler extends SystemCommandHandler implements Listener { - // command configuration - protected ArgumentTree getArgumentTree() { - return super.getArgumentTree().executes(BuildCommandHandler::addUser, ExecutorType.CONSOLE, ExecutorType.PLAYER); - } - - private static final String[] helpMessages = new String[]{ - "Opens a menu that guides users through creating a new command", - "Enables creating, editing, and deleting commands in-game", - "Usage:", - "\t/configcommands build" - }; - - protected String[] getHelpMessages() { - return helpMessages; - } - - - // command functions - private static final Map activeUsers = new HashMap<>(); - private static final Map keysBeingEditing = new HashMap<>(); - private static final List passToFunctionCommand = new ArrayList<>(); - - private static void addUser(CommandSender sender, Object[] ignored) { - sender.sendMessage("Welcome to the ConfigCommand build menu!"); - sender.sendMessage("Enter ## at any time to cancel."); - sender.sendMessage("Type back to return to previous step."); - ConfigCommandsHandler.reloadConfigFile(); - activeUsers.put(sender, new CommandContext(null, "", BuildCommandHandler::chooseCommand)); - handleMessage(sender, "", null); - } - - private static CommandContext setContext(CommandSender sender, CommandContext previousContext, Object previousChoice, CommandStep nextStep) { - CommandContext newContext = new CommandContext(previousContext, previousChoice, nextStep); - activeUsers.put(sender, newContext); - return newContext; - } - - private static CommandContext goBack(CommandSender sender, int steps, CommandContext currentContext) { - CommandContext newContext = currentContext; - for (int i = 0; i < steps; i++) { - newContext = newContext.getPreviousContext(); - if (newContext == null) break; - } - activeUsers.put(sender, newContext); - return newContext; - } - - private static void goBackStep(CommandSender sender, String message, CommandContext context) { - handleMessage(sender, "back", null); - } - - // events - @EventHandler - public void onChatSent(AsyncPlayerChatEvent event) { - handleMessage(event.getPlayer(), event.getMessage(), event); - } - - @EventHandler - public void playerCommandPreprocess(PlayerCommandPreprocessEvent event) { - handleMessage(event.getPlayer(), event.getMessage(), event); - } - - @EventHandler - public void onPlayerQuit(PlayerQuitEvent event) { - Player player = event.getPlayer(); - activeUsers.remove(player); - keysBeingEditing.remove(player); - } - - @EventHandler - public void onConsoleSent(ServerCommandEvent event) { - handleMessage(event.getSender(), event.getCommand(), event); - } - - private static void handleMessage(CommandSender sender, String message, Cancellable event) { - if (activeUsers.containsKey(sender)) { - if (passToFunctionCommand.contains(sender)) { - if (message.equals("##")) { - // just closed function menu - // don't cancel message b/c FunctionCommandHandler will cancel it - passToFunctionCommand.remove(sender); - activeUsers.get(sender).doNextStep(sender, ""); - } - } else { - if (event != null) event.setCancelled(true); - if (sender instanceof Player) sender.sendMessage(""); - if (message.equals("##")) { - sender.sendMessage("Closing the ConfigCommand build menu."); - sender.sendMessage("All command changes will take effect once server restarts."); - sender.sendMessage("If you changed the commands of a registered command, you can update it using /configcommands reload"); - activeUsers.remove(sender); - keysBeingEditing.remove(sender); - } else if (message.equalsIgnoreCase("back")) { - CommandContext previous = activeUsers.get(sender).getPreviousContext(); - if (previous == null) { - sender.sendMessage("No step to go back to."); - } else { - activeUsers.put(sender, previous); - activeUsers.get(sender).doNextStep(sender, ""); - } - } else { - activeUsers.get(sender).doNextStep(sender, message); - } - } - } - } - - // Build menu steps - private static void chooseCommand(CommandSender sender, String message, CommandContext context) { - keysBeingEditing.remove(sender); - - FileConfiguration config = ConfigCommandsHandler.getConfigFile(); - ConfigurationSection commands = config.getConfigurationSection("commands"); - - if (commands == null) { - config.createSection("commands"); - commands = config.getConfigurationSection("commands"); - } - assert commands != null; - Set keys = commands.getKeys(false); - - if (message.isBlank()) { - if (keys.size() != 0) { - sender.sendMessage("Found " + keys.size() + " command" + (keys.size() == 1 ? "" : "s") + " to edit"); - sender.sendMessage("Type one of the following keys to edit:"); - for (String key : keys) { - sender.sendMessage(" " + key); - } - sender.sendMessage("Or type \"create\" to make a new command"); - } else { - sender.sendMessage("No commands found"); - sender.sendMessage("Type \"create\" to make a new command"); - } - } else { - if (keys.contains(message)) { - if (keysBeingEditing.containsValue(message)) { - sender.sendMessage("Someone else is currently editing that command!"); - } else { - keysBeingEditing.put(sender, message); - context = setContext(sender, context, message, BuildCommandHandler::editCommand); - context.doNextStep(sender, ""); - } - } else if (message.equals("create")) { - context = setContext(sender, context, "", BuildCommandHandler::createCommand); - context.doNextStep(sender, ""); - } else { - sender.sendMessage(message + " is not recognized as an existing command"); - } - } - } - - private static void createCommand(CommandSender sender, String message, CommandContext context) { - if (message.isBlank()) { - sender.sendMessage("What key should the command be stored under?"); - } else { - FileConfiguration config = ConfigCommandsHandler.getConfigFile(); - ConfigurationSection commands = config.getConfigurationSection("commands"); - assert commands != null; - Set keys = commands.getKeys(false); - if (!keys.contains(message)) { - commands.createSection(message); - - context = goBack(sender, 1, context); - context = setContext(sender, context, message, BuildCommandHandler::editCommand); - context.doNextStep(sender, ""); - } else { - sender.sendMessage("That key is already in use!"); - } - } - } - - private static void editCommand(CommandSender sender, String message, CommandContext context) { - String key = (String) context.getPreviousChoice(); - if (message.isBlank()) { - sender.sendMessage("Editing command with key \"" + key + "\""); - sender.sendMessage("Select one of the following options using its number to continue:"); - sender.sendMessage(" 1. See current info"); - sender.sendMessage(" 2. Change key in config.yml"); - sender.sendMessage(" 3. Change name"); - sender.sendMessage(" 4. Edit arguments"); - sender.sendMessage(" 5. Change short description"); - sender.sendMessage(" 6. Change full description"); - sender.sendMessage(" 7. Change permission"); - sender.sendMessage(" 8. Edit aliases"); - sender.sendMessage(" 9. Edit commands"); - sender.sendMessage(" 10. Delete entire command"); - } else { - CommandStep nextStep = switch (message) { - case "1" -> BuildCommandHandler::seeInfo; - case "2" -> BuildCommandHandler::changeKey; - case "3" -> BuildCommandHandler::changeName; - case "4" -> BuildCommandHandler::editArguments; - case "5" -> BuildCommandHandler::changeShortDescription; - case "6" -> BuildCommandHandler::changeFullDescription; - case "7" -> BuildCommandHandler::changePermission; - case "8" -> BuildCommandHandler::editAliases; - case "9" -> BuildCommandHandler::editCommands; - case "10" -> BuildCommandHandler::deleteCommand; - default -> null; - }; - if (nextStep == null) { - sender.sendMessage("Message \"" + message + "\" is not a number from 1 to 10"); - return; - } - context = setContext(sender, context, key, nextStep); - context.doNextStep(sender, ""); - } - } - - private static void deleteCommand(CommandSender sender, String message, CommandContext context) { - String key = (String) context.getPreviousChoice(); - if (message.isBlank()) { - sender.sendMessage("Are you sure you want to delete command: \"" + key + "\"?"); - sender.sendMessage(ChatColor.YELLOW + "THIS ACTION CANNOT BE UNDONE"); - sender.sendMessage("Type \"yes\" to confirm or anything else to go back."); - } else { - if (message.equals("yes")) { - FileConfiguration config = ConfigCommandsHandler.getConfigFile(); - ConfigurationSection commands = config.getConfigurationSection("commands"); - assert commands != null; - commands.set(key, null); - ConfigCommandsHandler.saveConfigFile(); - sender.sendMessage("Deleted command \"" + key + "\""); - - context = goBack(sender, 2, context); - context.doNextStep(sender, ""); - } else { - sender.sendMessage("Not deleting command \"" + key + "\""); - - context = goBack(sender, 1, context); - context.doNextStep(sender, ""); - } - } - } - - private static void editCommands(CommandSender sender, String message, CommandContext context) { - String key = (String) context.getPreviousChoice(); - FileConfiguration config = ConfigCommandsHandler.getConfigFile(); - ConfigurationSection commands = config.getConfigurationSection("commands"); - assert commands != null; - ConfigurationSection command = commands.getConfigurationSection(key); - assert command != null; - List commandList = command.getStringList("commands"); - - if (message.isBlank()) { - if (commandList.size() == 0) { - sender.sendMessage("No commands"); - sender.sendMessage("Type a new command"); - } else { - sender.sendMessage("Current commands:"); - for (int i = 0; i < commandList.size(); i++) { - sender.sendMessage(" " + (i) + ". " + commandList.get(i)); - } - sender.sendMessage("Type a number to delete the corresponding command"); - sender.sendMessage("Type anything else to add it as a new command"); - } - sender.sendMessage("Type '?' for help with the command format."); - sender.sendMessage("Type \"functions\" to use /configcommands functions to get help with functions"); - } else { - if (message.matches("[0-9]+")) { - int target = Integer.parseInt(message); - if (0 <= target && target < commandList.size()) { - sender.sendMessage("Deleting command \"" + commandList.get(target) + "\""); - commandList.remove(target); - command.set("commands", commandList); - ConfigCommandsHandler.saveConfigFile(); - - context.doNextStep(sender, ""); - } else { - sender.sendMessage("Given number is not in range 0 to " + (commandList.size() - 1)); - } - } else if (message.equals("?")) { - sender.sendMessage("Options for commands:"); - sender.sendMessage(" Commands:"); - sender.sendMessage(" Regular command - \"/say Hello World\""); - sender.sendMessage(" Command referencing variables - \"/tp \""); - sender.sendMessage(" Set variable:"); - sender.sendMessage(" To result of function - \" = Integer.new(\"10\")\""); - sender.sendMessage(" To result of command - \" = /data get entity @p Health\""); - sender.sendMessage(" Run function:"); - sender.sendMessage(" do .dispatchCommand()"); - sender.sendMessage(" Define branch tag:"); - sender.sendMessage(" tag Option 1"); - sender.sendMessage(" Branch conditionally:"); - sender.sendMessage(" if .equals(\"1\") goto \"Option 1\""); - sender.sendMessage(" Jump:"); - sender.sendMessage(" Jump to line # - \"goto Integer.(\"4\")\""); - sender.sendMessage(" Jump to tag - \"goto \"Option 1\"\""); - sender.sendMessage(" End execution - \"goto Integer.(\"-1\")\""); - sender.sendMessage(" Output result as string:"); - sender.sendMessage(" return "); - } else if (message.equals("functions")) { - FunctionsCommandHandler.addUser(sender, null); - passToFunctionCommand.add(sender); - } else { - context = setContext(sender, context, message, BuildCommandHandler::addCommand); - context.doNextStep(sender, ""); - } - } - } - - private static void addCommand(CommandSender sender, String message, CommandContext context) { - String key = (String) context.getPreviousContext().getPreviousChoice(); - FileConfiguration config = ConfigCommandsHandler.getConfigFile(); - ConfigurationSection commands = config.getConfigurationSection("commands"); - assert commands != null; - ConfigurationSection command = commands.getConfigurationSection(key); - assert command != null; - List commandList = command.getStringList("commands"); - - String newCommand = (String) context.getPreviousChoice(); - - if (message.isBlank()) { - if (commandList.size() == 0) { - commandList.add(newCommand); - command.set("commands", commandList); - ConfigCommandsHandler.saveConfigFile(); - - context = goBack(sender, 1, context); - context.doNextStep(sender, ""); - } else { - sender.sendMessage("Current commands:"); - for (int i = 0; i < commandList.size(); i++) { - sender.sendMessage(" " + (i) + ". " + commandList.get(i)); - } - sender.sendMessage("Type an index to place the new command at"); - } - } else { - if (message.matches("[0-9]+")) { - int target = Integer.parseInt(message); - if (0 <= target && target <= commandList.size()) { - commandList.add(target, newCommand); - command.set("commands", commandList); - ConfigCommandsHandler.saveConfigFile(); - - context = goBack(sender, 1, context); - context.doNextStep(sender, ""); - } else { - sender.sendMessage("Given number is not in range 0 to " + commandList.size()); - } - } else { - sender.sendMessage("Cannot recognize message \"" + message + "\" as number"); - } - } - } - - private static void editArguments(CommandSender sender, String message, CommandContext context) { - String key = (String) context.getPreviousChoice(); - FileConfiguration config = ConfigCommandsHandler.getConfigFile(); - ConfigurationSection commands = config.getConfigurationSection("commands"); - assert commands != null; - ConfigurationSection command = commands.getConfigurationSection(key); - assert command != null; - List> args = command.getMapList("args"); - - if (message.isBlank()) { - if (args.size() == 0) { - sender.sendMessage("No arguments"); - sender.sendMessage("Type anything to start creating an argument with that name"); - } else { - sender.sendMessage("Current arguments:"); - for (int i = 0; i < args.size(); i++) { - sender.sendMessage(" " + (i + 1) + ". " + args.get(i)); - } - sender.sendMessage("Type a number to edit the corresponding argument"); - sender.sendMessage("Type anything else to start creating an argument with that name"); - } - } else { - if (message.matches("[0-9]+")) { - int target = Integer.parseInt(message); - if (0 < target && target <= args.size()) { - // skip step that chooses type - context = setContext(sender, context, args.get(target - 1), BuildCommandHandler::goBackStep); - context = setContext(sender, context, args.get(target - 1), BuildCommandHandler::addParametersToArgument); - context.doNextStep(sender, ""); - } else { - sender.sendMessage("Given number is not in range 1 to " + args.size()); - } - } else { - message = InternalArgument.formatArgumentName(message); - boolean nameUsedBefore = false; - for (Map arg : args) { - String name = (String) arg.get("name"); - if (name != null && message.equals(InternalArgument.formatArgumentName(name))) { - nameUsedBefore = true; - break; - } - } - if (nameUsedBefore) { - sender.sendMessage("Name " + message + " is already in use!"); - } else { - sender.sendMessage("Creating argument with name: \"" + message + "\""); - Map arg = new HashMap<>(); - arg.put("name", message); - context = setContext(sender, context, arg, BuildCommandHandler::chooseTypeForArgument); - - context.doNextStep(sender, ""); - } - } - } - } - - private static void chooseTypeForArgument(CommandSender sender, String message, CommandContext context) { - if (message.isBlank()) { - sender.sendMessage("What will the argument type be?"); - sender.sendMessage("Type '?' for a list of valid argument types"); - } else if (message.equals("?")) { - sender.sendMessage("Argument types:"); - sender.sendMessage(InternalArgument.getArgumentTypes().toString()); - } else if (InternalArgument.getArgumentTypes().contains(message)) { - Map arg = (Map) context.getPreviousChoice(); - arg.put("type", message); - - context = setContext(sender, context, arg, BuildCommandHandler::addParametersToArgument); - - context.doNextStep(sender, ""); - } else { - sender.sendMessage("Type \"" + message + "\" not found."); - } - } - - private static void addParametersToArgument(CommandSender sender, String message, CommandContext context) { - String key = (String) context.getPreviousContext().getPreviousContext().getPreviousChoice(); - FileConfiguration config = ConfigCommandsHandler.getConfigFile(); - ConfigurationSection commands = config.getConfigurationSection("commands"); - assert commands != null; - ConfigurationSection command = commands.getConfigurationSection(key); - assert command != null; - List> args = command.getMapList("args"); - - Map arg = (Map) context.getPreviousChoice(); - - - if (message.isBlank()) { - sender.sendMessage("Current argument: " + arg.toString()); - sender.sendMessage(testArgument(arg, args)); - sender.sendMessage("Create a new key or overwrite an old one by typing \"key:value\""); - sender.sendMessage("Delete a key by typing \"key:\""); - sender.sendMessage("Delete the argument by typing \"delete\""); - sender.sendMessage("Finish adding the argument by typing \"confirm\""); - } else if (message.equals("confirm")) { - context = setContext(sender, context, key, BuildCommandHandler::addArgument); - - context.doNextStep(sender, ""); - } else if (message.equals("delete")) { - args.remove(arg); - command.set("args", args); - ConfigCommandsHandler.saveConfigFile(); - - context = goBack(sender, 2, context); - context.doNextStep(sender, ""); - } else { - String[] parts = message.split(":", 2); - if (parts.length != 2) { - sender.sendMessage("Unknown \"key:value\" format."); - } else { - String argKey = parts[0]; - if (argKey.isBlank()) { - sender.sendMessage("key cannot be blank"); - return; - } - String argValue = parts[1]; - if (argValue.isBlank()) { - arg.remove(argKey); - sender.sendMessage("Removed key: " + argKey); - } else { - arg.put(argKey, argValue); - sender.sendMessage("Added " + message); - } - context.doNextStep(sender, ""); - } - } - } - - private static String testArgument(Map arg, List> previousArgs) { - CommandAPICommand dummyCommand = new CommandAPICommand("dummy"); - ArrayList argument_keys = new ArrayList<>(); - HashMap> argument_variable_classes = new HashMap<>(); - for (Map.Entry> preArg : ConfigCommandBuilder.getDefaultArgs().entrySet()) { - argument_keys.add(preArg.getKey()); - argument_variable_classes.put(preArg.getKey(), preArg.getValue()); - } - for (Map preArg : previousArgs) { - if (!preArg.equals(arg)) { - argument_keys.add((String) preArg.get("name")); - argument_variable_classes.put((String) preArg.get("name"), InternalArgument.class); - } - } - boolean debugMode = false; - try { - InternalArgument.addArgument(arg, dummyCommand, argument_keys, argument_variable_classes, debugMode); - Argument argument = dummyCommand.getArguments().get(0); - return "Argument adds without problem, producing a " + argument.getClass().getSimpleName() + " with rawType: " + argument.getRawType().toString(); - } catch (IncorrectArgumentKey e) { - return "Attempting to add argument throws error: " + e.getMessage(); - } - } - - private static void addArgument(CommandSender sender, String message, CommandContext context) { - String key = (String) context.getPreviousChoice(); - FileConfiguration config = ConfigCommandsHandler.getConfigFile(); - ConfigurationSection commands = config.getConfigurationSection("commands"); - assert commands != null; - ConfigurationSection command = commands.getConfigurationSection(key); - assert command != null; - List> args = command.getMapList("args"); - - Map arg = (Map) context.getPreviousContext().getPreviousChoice(); - - args.remove(arg); - - if (message.isBlank()) { - if (args.size() == 0) { - sender.sendMessage("Added argument: " + arg); - args.add(arg); - command.set("args", args); - ConfigCommandsHandler.saveConfigFile(); - - context = goBack(sender, 3, context); - context.doNextStep(sender, ""); - } else { - sender.sendMessage("Current arguments:"); - for (int i = 0; i < args.size(); i++) { - sender.sendMessage(" " + (i + 1) + ". " + args.get(i)); - } - sender.sendMessage("Adding argument: " + arg); - sender.sendMessage("Type an index to place the new argument at"); - } - } else { - if (message.matches("[0-9]+")) { - int target = Integer.parseInt(message); - if (0 < target && target <= args.size() + 1) { - args.add(target - 1, arg); - command.set("args", args); - ConfigCommandsHandler.saveConfigFile(); - - context = goBack(sender, 3, context); - context.doNextStep(sender, ""); - } else { - sender.sendMessage("Given number is not in range 1 to " + (args.size() + 1)); - } - } else { - sender.sendMessage("Cannot recognize message \"" + message + "\" as number"); - } - } - } - - private static void editAliases(CommandSender sender, String message, CommandContext context) { - String key = (String) context.getPreviousChoice(); - FileConfiguration config = ConfigCommandsHandler.getConfigFile(); - ConfigurationSection commands = config.getConfigurationSection("commands"); - assert commands != null; - ConfigurationSection command = commands.getConfigurationSection(key); - assert command != null; - List aliases = command.getStringList("aliases"); - - if (message.isBlank()) { - if (aliases.size() == 0) { - sender.sendMessage("No aliases"); - sender.sendMessage("Type anything to add it as an alias"); - } else { - sender.sendMessage("Current aliases:"); - for (int i = 0; i < aliases.size(); i++) { - sender.sendMessage(" " + (i + 1) + ". " + aliases.get(i)); - } - sender.sendMessage("Type a number to delete the corresponding alias"); - sender.sendMessage("Type anything else to add it as an alias"); - } - } else { - if (message.matches("[0-9]+")) { - int target = Integer.parseInt(message); - if (0 < target && target <= aliases.size()) { - sender.sendMessage("Deleting alias \"" + aliases.get(target - 1) + "\""); - aliases.remove(target - 1); - command.set("aliases", aliases); - ConfigCommandsHandler.saveConfigFile(); - - context.doNextStep(sender, ""); - } else { - sender.sendMessage("Given number is not in range 1 to " + aliases.size()); - } - } else { - sender.sendMessage("Adding alias \"" + message + "\""); - - aliases.add(message); - command.set("aliases", aliases); - ConfigCommandsHandler.saveConfigFile(); - - context.doNextStep(sender, ""); - } - } - } - - private static void changePermission(CommandSender sender, String message, CommandContext context) { - String key = (String) context.getPreviousChoice(); - - FileConfiguration config = ConfigCommandsHandler.getConfigFile(); - ConfigurationSection commands = config.getConfigurationSection("commands"); - assert commands != null; - ConfigurationSection command = commands.getConfigurationSection(key); - assert command != null; - - if (message.isBlank()) { - String permission = command.getString("permission"); - if (permission == null) { - sender.sendMessage("Current permission is null"); - String name = command.getString("name"); - sender.sendMessage("Default permission is \"" + - ConfigCommandBuilder.buildDefaultPermission(name == null ? key : name) + "\"" - ); - } else { - sender.sendMessage("Current permission: \"" + permission + "\""); - } - sender.sendMessage("Please type the permission you would like to use or back to go back."); - } else { - command.set("permission", message); - ConfigCommandsHandler.saveConfigFile(); - - context = goBack(sender, 1, context); - context.doNextStep(sender, ""); - } - } - - private static void handleSimpleChange(CommandSender sender, String message, CommandContext context, String section) { - String key = (String) context.getPreviousChoice(); - - FileConfiguration config = ConfigCommandsHandler.getConfigFile(); - ConfigurationSection commands = config.getConfigurationSection("commands"); - assert commands != null; - ConfigurationSection command = commands.getConfigurationSection(key); - assert command != null; - - if (message.isBlank()) { - String value = command.getString(section); - if (value == null) { - sender.sendMessage("Current " + section + " is null"); - } else { - sender.sendMessage("Current " + section + ": \"" + value + "\""); - } - sender.sendMessage("Please type the " + section + " you would like to use or back to go back."); - } else { - command.set(section, message); - ConfigCommandsHandler.saveConfigFile(); - - context = goBack(sender, 1, context); - context.doNextStep(sender, ""); - } - } - - private static void changeFullDescription(CommandSender sender, String message, CommandContext context) { - handleSimpleChange(sender, message, context, "fullDescription"); - } - - private static void changeShortDescription(CommandSender sender, String message, CommandContext context) { - handleSimpleChange(sender, message, context, "shortDescription"); - } - - private static void changeName(CommandSender sender, String message, CommandContext context) { - handleSimpleChange(sender, message, context, "name"); - } - - private static void changeKey(CommandSender sender, String message, CommandContext context) { - String key = (String) context.getPreviousChoice(); - if (message.isBlank()) { - sender.sendMessage("Current key: " + key); - sender.sendMessage("What would you like the new key to be?"); - } else { - FileConfiguration config = ConfigCommandsHandler.getConfigFile(); - ConfigurationSection commands = config.getConfigurationSection("commands"); - assert commands != null; - Set keys = commands.getKeys(false); - if (!keys.contains(message)) { - commands.set(message, commands.get(key)); - keysBeingEditing.put(sender, message); - - commands.set(key, null); - ConfigCommandsHandler.saveConfigFile(); - ReloadCommandHandler.updateKey(key, message); - - context = goBack(sender, 2, context); - context = setContext(sender, context, message, BuildCommandHandler::editCommand); - context.doNextStep(sender, ""); - } else { - sender.sendMessage("That key is already in use!"); - } - } - } - - private static void seeInfo(CommandSender sender, String message, CommandContext context) { - if (message.isBlank()) { - String key = (String) context.getPreviousChoice(); - - FileConfiguration config = ConfigCommandsHandler.getConfigFile(); - ConfigurationSection commands = config.getConfigurationSection("commands"); - assert commands != null; - ConfigurationSection command = commands.getConfigurationSection(key); - assert command != null; - - sender.sendMessage("Information for command " + key); - sender.sendMessage(" Name: \"" + command.getString("name") + "\""); - - List aliases = command.getStringList("aliases"); - if (aliases.size() == 0) { - sender.sendMessage(" No Aliases"); - } else { - sender.sendMessage(" Aliases:"); - for (String alias : aliases) { - sender.sendMessage(" " + alias); - } - } - - List> args = command.getMapList("args"); - if (args.size() == 0) { - sender.sendMessage(" No Arguments"); - } else { - sender.sendMessage(" Arguments:"); - for (Map arg : args) { - sender.sendMessage(" " + arg.toString()); - } - } - - sender.sendMessage(" Permission: \"" + command.getString("permission") + "\""); - sender.sendMessage(" Short Description: \"" + command.getString("shortDescription") + "\""); - sender.sendMessage(" Full Description: \"" + command.getString("fullDescription") + "\""); - - List commandsToRun = command.getStringList("commands"); - if (commandsToRun.size() == 0) { - sender.sendMessage(" No Commands"); - } else { - sender.sendMessage(" Commands:"); - for (int i = 0; i < commandsToRun.size(); i++) { - sender.sendMessage(" " + (i) + ". " + commandsToRun.get(i)); - } - } - - sender.sendMessage("Type anything to continue"); - } else { - context = goBack(sender, 1, context); - context.doNextStep(sender, ""); - } - } -} +//package me.willkroboth.ConfigCommands.SystemCommands; +// +//import dev.jorel.commandapi.ArgumentTree; +//import dev.jorel.commandapi.CommandAPICommand; +//import dev.jorel.commandapi.arguments.Argument; +//import dev.jorel.commandapi.executors.ExecutorType; +//import me.willkroboth.ConfigCommands.ConfigCommandsHandler; +//import me.willkroboth.ConfigCommands.Exceptions.IncorrectArgumentKey; +//import me.willkroboth.ConfigCommands.RegisteredCommands.CommandTreeBuilder; +//import me.willkroboth.ConfigCommands.InternalArguments.InternalArgument; +//import org.bukkit.ChatColor; +//import org.bukkit.command.CommandSender; +//import org.bukkit.configuration.ConfigurationSection; +//import org.bukkit.configuration.file.FileConfiguration; +//import org.bukkit.entity.Player; +//import org.bukkit.event.Cancellable; +//import org.bukkit.event.EventHandler; +//import org.bukkit.event.Listener; +//import org.bukkit.event.player.AsyncPlayerChatEvent; +//import org.bukkit.event.player.PlayerCommandPreprocessEvent; +//import org.bukkit.event.player.PlayerQuitEvent; +//import org.bukkit.event.server.ServerCommandEvent; +// +//import java.util.*; +// +//public class BuildCommandHandler extends SystemCommandHandler implements Listener { +// // command configuration +// protected ArgumentTree getArgumentTree() { +// return super.getArgumentTree().executes(BuildCommandHandler::addUser, ExecutorType.CONSOLE, ExecutorType.PLAYER); +// } +// +// private static final String[] helpMessages = new String[]{ +// "Opens a menu that guides users through creating a new command", +// "Enables creating, editing, and deleting commands in-game", +// "Usage:", +// "\t/configcommands build" +// }; +// +// protected String[] getHelpMessages() { +// return helpMessages; +// } +// +// +// // command functions +// private static final Map activeUsers = new HashMap<>(); +// private static final Map keysBeingEditing = new HashMap<>(); +// private static final List passToFunctionCommand = new ArrayList<>(); +// +// private static void addUser(CommandSender sender, Object[] ignored) { +// sender.sendMessage("Welcome to the ConfigCommand build menu!"); +// sender.sendMessage("Enter ## at any time to cancel."); +// sender.sendMessage("Type back to return to previous step."); +// ConfigCommandsHandler.reloadConfigFile(); +// activeUsers.put(sender, new CommandContext(null, "", BuildCommandHandler::chooseCommand)); +// handleMessage(sender, "", null); +// } +// +// private static CommandContext setContext(CommandSender sender, CommandContext previousContext, Object previousChoice, CommandStep nextStep) { +// CommandContext newContext = new CommandContext(previousContext, previousChoice, nextStep); +// activeUsers.put(sender, newContext); +// return newContext; +// } +// +// private static CommandContext goBack(CommandSender sender, int steps, CommandContext currentContext) { +// CommandContext newContext = currentContext; +// for (int i = 0; i < steps; i++) { +// newContext = newContext.getPreviousContext(); +// if (newContext == null) break; +// } +// activeUsers.put(sender, newContext); +// return newContext; +// } +// +// private static void goBackStep(CommandSender sender, String message, CommandContext context) { +// handleMessage(sender, "back", null); +// } +// +// // events +// @EventHandler +// public void onChatSent(AsyncPlayerChatEvent event) { +// handleMessage(event.getPlayer(), event.getMessage(), event); +// } +// +// @EventHandler +// public void playerCommandPreprocess(PlayerCommandPreprocessEvent event) { +// handleMessage(event.getPlayer(), event.getMessage(), event); +// } +// +// @EventHandler +// public void onPlayerQuit(PlayerQuitEvent event) { +// Player player = event.getPlayer(); +// activeUsers.remove(player); +// keysBeingEditing.remove(player); +// } +// +// @EventHandler +// public void onConsoleSent(ServerCommandEvent event) { +// handleMessage(event.getSender(), event.getCommand(), event); +// } +// +// private static void handleMessage(CommandSender sender, String message, Cancellable event) { +// if (activeUsers.containsKey(sender)) { +// if (passToFunctionCommand.contains(sender)) { +// if (message.equals("##")) { +// // just closed function menu +// // don't cancel message b/c FunctionCommandHandler will cancel it +// passToFunctionCommand.remove(sender); +// activeUsers.get(sender).doNextStep(sender, ""); +// } +// } else { +// if (event != null) event.setCancelled(true); +// if (sender instanceof Player) sender.sendMessage(""); +// if (message.equals("##")) { +// sender.sendMessage("Closing the ConfigCommand build menu."); +// sender.sendMessage("All command changes will take effect once server restarts."); +// sender.sendMessage("If you changed the commands of a registered command, you can update it using /configcommands reload"); +// activeUsers.remove(sender); +// keysBeingEditing.remove(sender); +// } else if (message.equalsIgnoreCase("back")) { +// CommandContext previous = activeUsers.get(sender).getPreviousContext(); +// if (previous == null) { +// sender.sendMessage("No step to go back to."); +// } else { +// activeUsers.put(sender, previous); +// activeUsers.get(sender).doNextStep(sender, ""); +// } +// } else { +// activeUsers.get(sender).doNextStep(sender, message); +// } +// } +// } +// } +// +// // Build menu steps +// private static void chooseCommand(CommandSender sender, String message, CommandContext context) { +// keysBeingEditing.remove(sender); +// +// FileConfiguration config = ConfigCommandsHandler.getConfigFile(); +// ConfigurationSection commands = config.getConfigurationSection("commands"); +// +// if (commands == null) { +// config.createSection("commands"); +// commands = config.getConfigurationSection("commands"); +// } +// assert commands != null; +// Set keys = commands.getKeys(false); +// +// if (message.isBlank()) { +// if (keys.size() != 0) { +// sender.sendMessage("Found " + keys.size() + " command" + (keys.size() == 1 ? "" : "s") + " to edit"); +// sender.sendMessage("Type one of the following keys to edit:"); +// for (String key : keys) { +// sender.sendMessage(" " + key); +// } +// sender.sendMessage("Or type \"create\" to make a new command"); +// } else { +// sender.sendMessage("No commands found"); +// sender.sendMessage("Type \"create\" to make a new command"); +// } +// } else { +// if (keys.contains(message)) { +// if (keysBeingEditing.containsValue(message)) { +// sender.sendMessage("Someone else is currently editing that command!"); +// } else { +// keysBeingEditing.put(sender, message); +// context = setContext(sender, context, message, BuildCommandHandler::editCommand); +// context.doNextStep(sender, ""); +// } +// } else if (message.equals("create")) { +// context = setContext(sender, context, "", BuildCommandHandler::createCommand); +// context.doNextStep(sender, ""); +// } else { +// sender.sendMessage(message + " is not recognized as an existing command"); +// } +// } +// } +// +// private static void createCommand(CommandSender sender, String message, CommandContext context) { +// if (message.isBlank()) { +// sender.sendMessage("What key should the command be stored under?"); +// } else { +// FileConfiguration config = ConfigCommandsHandler.getConfigFile(); +// ConfigurationSection commands = config.getConfigurationSection("commands"); +// assert commands != null; +// Set keys = commands.getKeys(false); +// if (!keys.contains(message)) { +// commands.createSection(message); +// +// context = goBack(sender, 1, context); +// context = setContext(sender, context, message, BuildCommandHandler::editCommand); +// context.doNextStep(sender, ""); +// } else { +// sender.sendMessage("That key is already in use!"); +// } +// } +// } +// +// private static void editCommand(CommandSender sender, String message, CommandContext context) { +// String key = (String) context.getPreviousChoice(); +// if (message.isBlank()) { +// sender.sendMessage("Editing command with key \"" + key + "\""); +// sender.sendMessage("Select one of the following options using its number to continue:"); +// sender.sendMessage(" 1. See current info"); +// sender.sendMessage(" 2. Change key in config.yml"); +// sender.sendMessage(" 3. Change name"); +// sender.sendMessage(" 4. Edit arguments"); +// sender.sendMessage(" 5. Change short description"); +// sender.sendMessage(" 6. Change full description"); +// sender.sendMessage(" 7. Change permission"); +// sender.sendMessage(" 8. Edit aliases"); +// sender.sendMessage(" 9. Edit commands"); +// sender.sendMessage(" 10. Delete entire command"); +// } else { +// CommandStep nextStep = switch (message) { +// case "1" -> BuildCommandHandler::seeInfo; +// case "2" -> BuildCommandHandler::changeKey; +// case "3" -> BuildCommandHandler::changeName; +// case "4" -> BuildCommandHandler::editArguments; +// case "5" -> BuildCommandHandler::changeShortDescription; +// case "6" -> BuildCommandHandler::changeFullDescription; +// case "7" -> BuildCommandHandler::changePermission; +// case "8" -> BuildCommandHandler::editAliases; +// case "9" -> BuildCommandHandler::editCommands; +// case "10" -> BuildCommandHandler::deleteCommand; +// default -> null; +// }; +// if (nextStep == null) { +// sender.sendMessage("Message \"" + message + "\" is not a number from 1 to 10"); +// return; +// } +// context = setContext(sender, context, key, nextStep); +// context.doNextStep(sender, ""); +// } +// } +// +// private static void deleteCommand(CommandSender sender, String message, CommandContext context) { +// String key = (String) context.getPreviousChoice(); +// if (message.isBlank()) { +// sender.sendMessage("Are you sure you want to delete command: \"" + key + "\"?"); +// sender.sendMessage(ChatColor.YELLOW + "THIS ACTION CANNOT BE UNDONE"); +// sender.sendMessage("Type \"yes\" to confirm or anything else to go back."); +// } else { +// if (message.equals("yes")) { +// FileConfiguration config = ConfigCommandsHandler.getConfigFile(); +// ConfigurationSection commands = config.getConfigurationSection("commands"); +// assert commands != null; +// commands.set(key, null); +// ConfigCommandsHandler.saveConfigFile(); +// sender.sendMessage("Deleted command \"" + key + "\""); +// +// context = goBack(sender, 2, context); +// context.doNextStep(sender, ""); +// } else { +// sender.sendMessage("Not deleting command \"" + key + "\""); +// +// context = goBack(sender, 1, context); +// context.doNextStep(sender, ""); +// } +// } +// } +// +// private static void editCommands(CommandSender sender, String message, CommandContext context) { +// String key = (String) context.getPreviousChoice(); +// FileConfiguration config = ConfigCommandsHandler.getConfigFile(); +// ConfigurationSection commands = config.getConfigurationSection("commands"); +// assert commands != null; +// ConfigurationSection command = commands.getConfigurationSection(key); +// assert command != null; +// List commandList = command.getStringList("commands"); +// +// if (message.isBlank()) { +// if (commandList.size() == 0) { +// sender.sendMessage("No commands"); +// sender.sendMessage("Type a new command"); +// } else { +// sender.sendMessage("Current commands:"); +// for (int i = 0; i < commandList.size(); i++) { +// sender.sendMessage(" " + (i) + ". " + commandList.get(i)); +// } +// sender.sendMessage("Type a number to delete the corresponding command"); +// sender.sendMessage("Type anything else to add it as a new command"); +// } +// sender.sendMessage("Type '?' for help with the command format."); +// sender.sendMessage("Type \"functions\" to use /configcommands functions to get help with functions"); +// } else { +// if (message.matches("[0-9]+")) { +// int target = Integer.parseInt(message); +// if (0 <= target && target < commandList.size()) { +// sender.sendMessage("Deleting command \"" + commandList.get(target) + "\""); +// commandList.remove(target); +// command.set("commands", commandList); +// ConfigCommandsHandler.saveConfigFile(); +// +// context.doNextStep(sender, ""); +// } else { +// sender.sendMessage("Given number is not in range 0 to " + (commandList.size() - 1)); +// } +// } else if (message.equals("?")) { +// sender.sendMessage("Options for commands:"); +// sender.sendMessage(" Commands:"); +// sender.sendMessage(" Regular command - \"/say Hello World\""); +// sender.sendMessage(" Command referencing variables - \"/tp \""); +// sender.sendMessage(" Set variable:"); +// sender.sendMessage(" To result of function - \" = Integer.new(\"10\")\""); +// sender.sendMessage(" To result of command - \" = /data get entity @p Health\""); +// sender.sendMessage(" Run function:"); +// sender.sendMessage(" do .dispatchCommand()"); +// sender.sendMessage(" Define branch tag:"); +// sender.sendMessage(" tag Option 1"); +// sender.sendMessage(" Branch conditionally:"); +// sender.sendMessage(" if .equals(\"1\") goto \"Option 1\""); +// sender.sendMessage(" Jump:"); +// sender.sendMessage(" Jump to line # - \"goto Integer.(\"4\")\""); +// sender.sendMessage(" Jump to tag - \"goto \"Option 1\"\""); +// sender.sendMessage(" End execution - \"goto Integer.(\"-1\")\""); +// sender.sendMessage(" Output result as string:"); +// sender.sendMessage(" return "); +// } else if (message.equals("functions")) { +// FunctionsCommandHandler.addUser(sender, null); +// passToFunctionCommand.add(sender); +// } else { +// context = setContext(sender, context, message, BuildCommandHandler::addCommand); +// context.doNextStep(sender, ""); +// } +// } +// } +// +// private static void addCommand(CommandSender sender, String message, CommandContext context) { +// String key = (String) context.getPreviousContext().getPreviousChoice(); +// FileConfiguration config = ConfigCommandsHandler.getConfigFile(); +// ConfigurationSection commands = config.getConfigurationSection("commands"); +// assert commands != null; +// ConfigurationSection command = commands.getConfigurationSection(key); +// assert command != null; +// List commandList = command.getStringList("commands"); +// +// String newCommand = (String) context.getPreviousChoice(); +// +// if (message.isBlank()) { +// if (commandList.size() == 0) { +// commandList.add(newCommand); +// command.set("commands", commandList); +// ConfigCommandsHandler.saveConfigFile(); +// +// context = goBack(sender, 1, context); +// context.doNextStep(sender, ""); +// } else { +// sender.sendMessage("Current commands:"); +// for (int i = 0; i < commandList.size(); i++) { +// sender.sendMessage(" " + (i) + ". " + commandList.get(i)); +// } +// sender.sendMessage("Type an index to place the new command at"); +// } +// } else { +// if (message.matches("[0-9]+")) { +// int target = Integer.parseInt(message); +// if (0 <= target && target <= commandList.size()) { +// commandList.add(target, newCommand); +// command.set("commands", commandList); +// ConfigCommandsHandler.saveConfigFile(); +// +// context = goBack(sender, 1, context); +// context.doNextStep(sender, ""); +// } else { +// sender.sendMessage("Given number is not in range 0 to " + commandList.size()); +// } +// } else { +// sender.sendMessage("Cannot recognize message \"" + message + "\" as number"); +// } +// } +// } +// +// private static void editArguments(CommandSender sender, String message, CommandContext context) { +// String key = (String) context.getPreviousChoice(); +// FileConfiguration config = ConfigCommandsHandler.getConfigFile(); +// ConfigurationSection commands = config.getConfigurationSection("commands"); +// assert commands != null; +// ConfigurationSection command = commands.getConfigurationSection(key); +// assert command != null; +// List> args = command.getMapList("args"); +// +// if (message.isBlank()) { +// if (args.size() == 0) { +// sender.sendMessage("No arguments"); +// sender.sendMessage("Type anything to start creating an argument with that name"); +// } else { +// sender.sendMessage("Current arguments:"); +// for (int i = 0; i < args.size(); i++) { +// sender.sendMessage(" " + (i + 1) + ". " + args.get(i)); +// } +// sender.sendMessage("Type a number to edit the corresponding argument"); +// sender.sendMessage("Type anything else to start creating an argument with that name"); +// } +// } else { +// if (message.matches("[0-9]+")) { +// int target = Integer.parseInt(message); +// if (0 < target && target <= args.size()) { +// // skip step that chooses type +// context = setContext(sender, context, args.get(target - 1), BuildCommandHandler::goBackStep); +// context = setContext(sender, context, args.get(target - 1), BuildCommandHandler::addParametersToArgument); +// context.doNextStep(sender, ""); +// } else { +// sender.sendMessage("Given number is not in range 1 to " + args.size()); +// } +// } else { +// message = InternalArgument.formatArgumentName(message); +// boolean nameUsedBefore = false; +// for (Map arg : args) { +// String name = (String) arg.get("name"); +// if (name != null && message.equals(InternalArgument.formatArgumentName(name))) { +// nameUsedBefore = true; +// break; +// } +// } +// if (nameUsedBefore) { +// sender.sendMessage("Name " + message + " is already in use!"); +// } else { +// sender.sendMessage("Creating argument with name: \"" + message + "\""); +// Map arg = new HashMap<>(); +// arg.put("name", message); +// context = setContext(sender, context, arg, BuildCommandHandler::chooseTypeForArgument); +// +// context.doNextStep(sender, ""); +// } +// } +// } +// } +// +// private static void chooseTypeForArgument(CommandSender sender, String message, CommandContext context) { +// if (message.isBlank()) { +// sender.sendMessage("What will the argument type be?"); +// sender.sendMessage("Type '?' for a list of valid argument types"); +// } else if (message.equals("?")) { +// sender.sendMessage("Argument types:"); +// sender.sendMessage(InternalArgument.getArgumentTypes().toString()); +// } else if (InternalArgument.getArgumentTypes().contains(message)) { +// Map arg = (Map) context.getPreviousChoice(); +// arg.put("type", message); +// +// context = setContext(sender, context, arg, BuildCommandHandler::addParametersToArgument); +// +// context.doNextStep(sender, ""); +// } else { +// sender.sendMessage("Type \"" + message + "\" not found."); +// } +// } +// +// private static void addParametersToArgument(CommandSender sender, String message, CommandContext context) { +// String key = (String) context.getPreviousContext().getPreviousContext().getPreviousChoice(); +// FileConfiguration config = ConfigCommandsHandler.getConfigFile(); +// ConfigurationSection commands = config.getConfigurationSection("commands"); +// assert commands != null; +// ConfigurationSection command = commands.getConfigurationSection(key); +// assert command != null; +// List> args = command.getMapList("args"); +// +// Map arg = (Map) context.getPreviousChoice(); +// +// +// if (message.isBlank()) { +// sender.sendMessage("Current argument: " + arg.toString()); +// sender.sendMessage(testArgument(arg, args)); +// sender.sendMessage("Create a new key or overwrite an old one by typing \"key:value\""); +// sender.sendMessage("Delete a key by typing \"key:\""); +// sender.sendMessage("Delete the argument by typing \"delete\""); +// sender.sendMessage("Finish adding the argument by typing \"confirm\""); +// } else if (message.equals("confirm")) { +// context = setContext(sender, context, key, BuildCommandHandler::addArgument); +// +// context.doNextStep(sender, ""); +// } else if (message.equals("delete")) { +// args.remove(arg); +// command.set("args", args); +// ConfigCommandsHandler.saveConfigFile(); +// +// context = goBack(sender, 2, context); +// context.doNextStep(sender, ""); +// } else { +// String[] parts = message.split(":", 2); +// if (parts.length != 2) { +// sender.sendMessage("Unknown \"key:value\" format."); +// } else { +// String argKey = parts[0]; +// if (argKey.isBlank()) { +// sender.sendMessage("key cannot be blank"); +// return; +// } +// String argValue = parts[1]; +// if (argValue.isBlank()) { +// arg.remove(argKey); +// sender.sendMessage("Removed key: " + argKey); +// } else { +// arg.put(argKey, argValue); +// sender.sendMessage("Added " + message); +// } +// context.doNextStep(sender, ""); +// } +// } +// } +// +// private static String testArgument(Map arg, List> previousArgs) { +// CommandAPICommand dummyCommand = new CommandAPICommand("dummy"); +// ArrayList argument_keys = new ArrayList<>(); +// HashMap> argument_variable_classes = new HashMap<>(); +// for (Map.Entry> preArg : CommandTreeBuilder.getDefaultArgs().entrySet()) { +// argument_keys.add(preArg.getKey()); +// argument_variable_classes.put(preArg.getKey(), preArg.getValue()); +// } +// for (Map preArg : previousArgs) { +// if (!preArg.equals(arg)) { +// argument_keys.add((String) preArg.get("name")); +// argument_variable_classes.put((String) preArg.get("name"), InternalArgument.class); +// } +// } +// boolean debugMode = false; +// try { +// InternalArgument.addArgument(arg, dummyCommand, argument_keys, argument_variable_classes, debugMode); +// Argument argument = dummyCommand.getArguments().get(0); +// return "Argument adds without problem, producing a " + argument.getClass().getSimpleName() + " with rawType: " + argument.getRawType().toString(); +// } catch (IncorrectArgumentKey e) { +// return "Attempting to add argument throws error: " + e.getMessage(); +// } +// } +// +// private static void addArgument(CommandSender sender, String message, CommandContext context) { +// String key = (String) context.getPreviousChoice(); +// FileConfiguration config = ConfigCommandsHandler.getConfigFile(); +// ConfigurationSection commands = config.getConfigurationSection("commands"); +// assert commands != null; +// ConfigurationSection command = commands.getConfigurationSection(key); +// assert command != null; +// List> args = command.getMapList("args"); +// +// Map arg = (Map) context.getPreviousContext().getPreviousChoice(); +// +// args.remove(arg); +// +// if (message.isBlank()) { +// if (args.size() == 0) { +// sender.sendMessage("Added argument: " + arg); +// args.add(arg); +// command.set("args", args); +// ConfigCommandsHandler.saveConfigFile(); +// +// context = goBack(sender, 3, context); +// context.doNextStep(sender, ""); +// } else { +// sender.sendMessage("Current arguments:"); +// for (int i = 0; i < args.size(); i++) { +// sender.sendMessage(" " + (i + 1) + ". " + args.get(i)); +// } +// sender.sendMessage("Adding argument: " + arg); +// sender.sendMessage("Type an index to place the new argument at"); +// } +// } else { +// if (message.matches("[0-9]+")) { +// int target = Integer.parseInt(message); +// if (0 < target && target <= args.size() + 1) { +// args.add(target - 1, arg); +// command.set("args", args); +// ConfigCommandsHandler.saveConfigFile(); +// +// context = goBack(sender, 3, context); +// context.doNextStep(sender, ""); +// } else { +// sender.sendMessage("Given number is not in range 1 to " + (args.size() + 1)); +// } +// } else { +// sender.sendMessage("Cannot recognize message \"" + message + "\" as number"); +// } +// } +// } +// +// private static void editAliases(CommandSender sender, String message, CommandContext context) { +// String key = (String) context.getPreviousChoice(); +// FileConfiguration config = ConfigCommandsHandler.getConfigFile(); +// ConfigurationSection commands = config.getConfigurationSection("commands"); +// assert commands != null; +// ConfigurationSection command = commands.getConfigurationSection(key); +// assert command != null; +// List aliases = command.getStringList("aliases"); +// +// if (message.isBlank()) { +// if (aliases.size() == 0) { +// sender.sendMessage("No aliases"); +// sender.sendMessage("Type anything to add it as an alias"); +// } else { +// sender.sendMessage("Current aliases:"); +// for (int i = 0; i < aliases.size(); i++) { +// sender.sendMessage(" " + (i + 1) + ". " + aliases.get(i)); +// } +// sender.sendMessage("Type a number to delete the corresponding alias"); +// sender.sendMessage("Type anything else to add it as an alias"); +// } +// } else { +// if (message.matches("[0-9]+")) { +// int target = Integer.parseInt(message); +// if (0 < target && target <= aliases.size()) { +// sender.sendMessage("Deleting alias \"" + aliases.get(target - 1) + "\""); +// aliases.remove(target - 1); +// command.set("aliases", aliases); +// ConfigCommandsHandler.saveConfigFile(); +// +// context.doNextStep(sender, ""); +// } else { +// sender.sendMessage("Given number is not in range 1 to " + aliases.size()); +// } +// } else { +// sender.sendMessage("Adding alias \"" + message + "\""); +// +// aliases.add(message); +// command.set("aliases", aliases); +// ConfigCommandsHandler.saveConfigFile(); +// +// context.doNextStep(sender, ""); +// } +// } +// } +// +// private static void changePermission(CommandSender sender, String message, CommandContext context) { +// String key = (String) context.getPreviousChoice(); +// +// FileConfiguration config = ConfigCommandsHandler.getConfigFile(); +// ConfigurationSection commands = config.getConfigurationSection("commands"); +// assert commands != null; +// ConfigurationSection command = commands.getConfigurationSection(key); +// assert command != null; +// +// if (message.isBlank()) { +// String permission = command.getString("permission"); +// if (permission == null) { +// sender.sendMessage("Current permission is null"); +// String name = command.getString("name"); +// sender.sendMessage("Default permission is \"" + +// CommandTreeBuilder.buildDefaultPermission(name == null ? key : name) + "\"" +// ); +// } else { +// sender.sendMessage("Current permission: \"" + permission + "\""); +// } +// sender.sendMessage("Please type the permission you would like to use or back to go back."); +// } else { +// command.set("permission", message); +// ConfigCommandsHandler.saveConfigFile(); +// +// context = goBack(sender, 1, context); +// context.doNextStep(sender, ""); +// } +// } +// +// private static void handleSimpleChange(CommandSender sender, String message, CommandContext context, String section) { +// String key = (String) context.getPreviousChoice(); +// +// FileConfiguration config = ConfigCommandsHandler.getConfigFile(); +// ConfigurationSection commands = config.getConfigurationSection("commands"); +// assert commands != null; +// ConfigurationSection command = commands.getConfigurationSection(key); +// assert command != null; +// +// if (message.isBlank()) { +// String value = command.getString(section); +// if (value == null) { +// sender.sendMessage("Current " + section + " is null"); +// } else { +// sender.sendMessage("Current " + section + ": \"" + value + "\""); +// } +// sender.sendMessage("Please type the " + section + " you would like to use or back to go back."); +// } else { +// command.set(section, message); +// ConfigCommandsHandler.saveConfigFile(); +// +// context = goBack(sender, 1, context); +// context.doNextStep(sender, ""); +// } +// } +// +// private static void changeFullDescription(CommandSender sender, String message, CommandContext context) { +// handleSimpleChange(sender, message, context, "fullDescription"); +// } +// +// private static void changeShortDescription(CommandSender sender, String message, CommandContext context) { +// handleSimpleChange(sender, message, context, "shortDescription"); +// } +// +// private static void changeName(CommandSender sender, String message, CommandContext context) { +// handleSimpleChange(sender, message, context, "name"); +// } +// +// private static void changeKey(CommandSender sender, String message, CommandContext context) { +// String key = (String) context.getPreviousChoice(); +// if (message.isBlank()) { +// sender.sendMessage("Current key: " + key); +// sender.sendMessage("What would you like the new key to be?"); +// } else { +// FileConfiguration config = ConfigCommandsHandler.getConfigFile(); +// ConfigurationSection commands = config.getConfigurationSection("commands"); +// assert commands != null; +// Set keys = commands.getKeys(false); +// if (!keys.contains(message)) { +// commands.set(message, commands.get(key)); +// keysBeingEditing.put(sender, message); +// +// commands.set(key, null); +// ConfigCommandsHandler.saveConfigFile(); +// ReloadCommandHandler.updateKey(key, message); +// +// context = goBack(sender, 2, context); +// context = setContext(sender, context, message, BuildCommandHandler::editCommand); +// context.doNextStep(sender, ""); +// } else { +// sender.sendMessage("That key is already in use!"); +// } +// } +// } +// +// private static void seeInfo(CommandSender sender, String message, CommandContext context) { +// if (message.isBlank()) { +// String key = (String) context.getPreviousChoice(); +// +// FileConfiguration config = ConfigCommandsHandler.getConfigFile(); +// ConfigurationSection commands = config.getConfigurationSection("commands"); +// assert commands != null; +// ConfigurationSection command = commands.getConfigurationSection(key); +// assert command != null; +// +// sender.sendMessage("Information for command " + key); +// sender.sendMessage(" Name: \"" + command.getString("name") + "\""); +// +// List aliases = command.getStringList("aliases"); +// if (aliases.size() == 0) { +// sender.sendMessage(" No Aliases"); +// } else { +// sender.sendMessage(" Aliases:"); +// for (String alias : aliases) { +// sender.sendMessage(" " + alias); +// } +// } +// +// List> args = command.getMapList("args"); +// if (args.size() == 0) { +// sender.sendMessage(" No Arguments"); +// } else { +// sender.sendMessage(" Arguments:"); +// for (Map arg : args) { +// sender.sendMessage(" " + arg.toString()); +// } +// } +// +// sender.sendMessage(" Permission: \"" + command.getString("permission") + "\""); +// sender.sendMessage(" Short Description: \"" + command.getString("shortDescription") + "\""); +// sender.sendMessage(" Full Description: \"" + command.getString("fullDescription") + "\""); +// +// List commandsToRun = command.getStringList("commands"); +// if (commandsToRun.size() == 0) { +// sender.sendMessage(" No Commands"); +// } else { +// sender.sendMessage(" Commands:"); +// for (int i = 0; i < commandsToRun.size(); i++) { +// sender.sendMessage(" " + (i) + ". " + commandsToRun.get(i)); +// } +// } +// +// sender.sendMessage("Type anything to continue"); +// } else { +// context = goBack(sender, 1, context); +// context.doNextStep(sender, ""); +// } +// } +//} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/SystemCommands/ReloadCommandHandler.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/SystemCommands/ReloadCommandHandler.java index d66d38c..8a174b9 100644 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/SystemCommands/ReloadCommandHandler.java +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/SystemCommands/ReloadCommandHandler.java @@ -1,96 +1,96 @@ -package me.willkroboth.ConfigCommands.SystemCommands; - -import dev.jorel.commandapi.ArgumentTree; -import dev.jorel.commandapi.CommandAPI; -import dev.jorel.commandapi.SuggestionInfo; -import dev.jorel.commandapi.arguments.ArgumentSuggestions; -import dev.jorel.commandapi.arguments.StringArgument; -import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; -import me.willkroboth.ConfigCommands.ConfigCommandsHandler; -import me.willkroboth.ConfigCommands.Exceptions.RegistrationException; -import me.willkroboth.ConfigCommands.RegisteredCommands.ConfigCommandBuilder; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class ReloadCommandHandler extends SystemCommandHandler { - // command configuration - protected ArgumentTree getArgumentTree() { - return super.getArgumentTree() - .then(new StringArgument("command") - .replaceSuggestions(ArgumentSuggestions.strings(ReloadCommandHandler::getCommandNames)) - .executes(ReloadCommandHandler::reloadCommand) - ); - } - - private static final String[] helpMessages = new String[]{ - "Reloads a command's code from the config.yml, allowing its behavior to change without restarting the server.", - "Usage:", - "\t/configcommands reload " - }; - - protected String[] getHelpMessages() { - return helpMessages; - } - - // command functions - private static final Map commands = new HashMap<>(); - private static final Map nameToKey = new HashMap<>(); - private static final Map keyToName = new HashMap<>(); - - // accessed by ConfigCommandHandler - public static void addCommand(ConfigCommandBuilder configCommandBuilder, String key) { - commands.put(configCommandBuilder.getName(), configCommandBuilder); - nameToKey.put(configCommandBuilder.getName(), key); - keyToName.put(key, configCommandBuilder.getName()); - } - - // accessed by BuildCommandHandler - protected static void updateKey(String oldKey, String newKey) { - String name = keyToName.get(oldKey); - nameToKey.put(name, newKey); - keyToName.remove(oldKey); - keyToName.put(newKey, name); - } - - private static String[] getCommandNames(SuggestionInfo suggestionInfo) { - return commands.keySet().toArray(new String[0]); - } - - private static void reloadCommand(CommandSender sender, Object[] args) throws WrapperCommandSyntaxException { - String name = (String) args[0]; - if (!commands.containsKey(name)) { - throw CommandAPI.fail("Command: \"" + name + "\" was not created by ConfigCommands."); - } - ConfigCommandsHandler.reloadConfigFile(); - FileConfiguration config = ConfigCommandsHandler.getConfigFile(); - ConfigurationSection commandSection = config.getConfigurationSection("commands"); - - if (commandSection == null || commandSection.getKeys(false).size() == 0) { - throw CommandAPI.fail("No commands found in config.yml"); - } - - String key = nameToKey.get(name); - ConfigurationSection command = commandSection.getConfigurationSection(key); - if (command == null) { - throw CommandAPI.fail("No data was found for the command"); - } - - List commandsToRun = command.getStringList("commands"); - if (commandsToRun.size() == 0) { - throw CommandAPI.fail(key + " has no commands. Skipping."); - } - - try { - commands.get(name).refreshExecutor(commandsToRun); - } catch (RegistrationException e) { - throw CommandAPI.fail("Could not apply new commands: " + e.getMessage()); - } - - sender.sendMessage("Command successfully updated!"); - } -} +//package me.willkroboth.ConfigCommands.SystemCommands; +// +//import dev.jorel.commandapi.ArgumentTree; +//import dev.jorel.commandapi.CommandAPI; +//import dev.jorel.commandapi.SuggestionInfo; +//import dev.jorel.commandapi.arguments.ArgumentSuggestions; +//import dev.jorel.commandapi.arguments.StringArgument; +//import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; +//import me.willkroboth.ConfigCommands.ConfigCommandsHandler; +//import me.willkroboth.ConfigCommands.Exceptions.RegistrationException; +//import me.willkroboth.ConfigCommands.RegisteredCommands.CommandTreeBuilder; +//import org.bukkit.command.CommandSender; +//import org.bukkit.configuration.ConfigurationSection; +//import org.bukkit.configuration.file.FileConfiguration; +// +//import java.util.HashMap; +//import java.util.List; +//import java.util.Map; +// +//public class ReloadCommandHandler extends SystemCommandHandler { +// // command configuration +// protected ArgumentTree getArgumentTree() { +// return super.getArgumentTree() +// .then(new StringArgument("command") +// .replaceSuggestions(ArgumentSuggestions.strings(ReloadCommandHandler::getCommandNames)) +// .executes(ReloadCommandHandler::reloadCommand) +// ); +// } +// +// private static final String[] helpMessages = new String[]{ +// "Reloads a command's code from the config.yml, allowing its behavior to change without restarting the server.", +// "Usage:", +// "\t/configcommands reload " +// }; +// +// protected String[] getHelpMessages() { +// return helpMessages; +// } +// +// // command functions +// private static final Map commands = new HashMap<>(); +// private static final Map nameToKey = new HashMap<>(); +// private static final Map keyToName = new HashMap<>(); +// +// // accessed by ConfigCommandHandler +// public static void addCommand(CommandTreeBuilder commandTreeBuilder, String key) { +// commands.put(commandTreeBuilder.getName(), commandTreeBuilder); +// nameToKey.put(commandTreeBuilder.getName(), key); +// keyToName.put(key, commandTreeBuilder.getName()); +// } +// +// // accessed by BuildCommandHandler +// protected static void updateKey(String oldKey, String newKey) { +// String name = keyToName.get(oldKey); +// nameToKey.put(name, newKey); +// keyToName.remove(oldKey); +// keyToName.put(newKey, name); +// } +// +// private static String[] getCommandNames(SuggestionInfo suggestionInfo) { +// return commands.keySet().toArray(new String[0]); +// } +// +// private static void reloadCommand(CommandSender sender, Object[] args) throws WrapperCommandSyntaxException { +// String name = (String) args[0]; +// if (!commands.containsKey(name)) { +// throw CommandAPI.fail("Command: \"" + name + "\" was not created by ConfigCommands."); +// } +// ConfigCommandsHandler.reloadConfigFile(); +// FileConfiguration config = ConfigCommandsHandler.getConfigFile(); +// ConfigurationSection commandSection = config.getConfigurationSection("commands"); +// +// if (commandSection == null || commandSection.getKeys(false).size() == 0) { +// throw CommandAPI.fail("No commands found in config.yml"); +// } +// +// String key = nameToKey.get(name); +// ConfigurationSection command = commandSection.getConfigurationSection(key); +// if (command == null) { +// throw CommandAPI.fail("No data was found for the command"); +// } +// +// List commandsToRun = command.getStringList("commands"); +// if (commandsToRun.size() == 0) { +// throw CommandAPI.fail(key + " has no commands. Skipping."); +// } +// +// try { +// commands.get(name).refreshExecutor(commandsToRun); +// } catch (RegistrationException e) { +// throw CommandAPI.fail("Could not apply new commands: " + e.getMessage()); +// } +// +// sender.sendMessage("Command successfully updated!"); +// } +//} diff --git a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/SystemCommands/SystemCommandHandler.java b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/SystemCommands/SystemCommandHandler.java index cc09009..84b5944 100644 --- a/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/SystemCommands/SystemCommandHandler.java +++ b/ConfigCommands-core/src/main/java/me/willkroboth/ConfigCommands/SystemCommands/SystemCommandHandler.java @@ -23,8 +23,8 @@ public static void setUpCommands(ConfigCommands plugin) { commands.addAll(List.of( new HelpCommandHandler(), new FunctionsCommandHandler(), - new BuildCommandHandler(), - new ReloadCommandHandler(), +// new BuildCommandHandler(), +// new ReloadCommandHandler(), new DebugCommandHandler() )); diff --git a/ConfigCommands-plugin/src/main/resources/config.yml b/ConfigCommands-plugin/src/main/resources/config.yml index 0c78e2d..c401aee 100644 --- a/ConfigCommands-plugin/src/main/resources/config.yml +++ b/ConfigCommands-plugin/src/main/resources/config.yml @@ -1,15 +1,15 @@ debug: false commands: echo: - name: echo - args: - - name: - type: String - subtype: greedy shortDescription: Echos input back to you. fullDescription: Takes in a string and sends it back to you. aliases: - cat permission: configcommands.echo - commands: - - do .sendMessage() \ No newline at end of file + then: + string: + type: String + argumentInfo: + subtype: greedy + executes: + - do .sendMessage() \ No newline at end of file