summaryrefslogtreecommitdiff
path: root/dicore3/command/src/main/java/io/dico/dicore
diff options
context:
space:
mode:
Diffstat (limited to 'dicore3/command/src/main/java/io/dico/dicore')
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/ChildCommandAddress.java16
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/Command.java48
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/CommandBuilder.java11
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/CommandResult.java23
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/ExecutionContext.java243
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/ExtendedCommand.java3
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/ICommandAddress.java33
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/ICommandReceiver.java22
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/ModifiableCommandAddress.java17
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/PermissionContextFilter.java27
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/RootCommandAddress.java37
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/annotation/PreprocessArgs.java1
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageBuilder.java3
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/HelpComponentInserter.java2
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentBuffer.java71
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentMergingPreProcessor.java43
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/ContextParser.java32
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/IArgumentPreProcessor.java20
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/ParameterList.java16
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/EnumParameterType.java6
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterType.java52
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/predef/DefaultGroupCommand.java4
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ICommandInterceptor.java36
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ICommandReceiver.java5
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveCommand.java30
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveRegistration.java42
26 files changed, 472 insertions, 371 deletions
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/ChildCommandAddress.java b/dicore3/command/src/main/java/io/dico/dicore/command/ChildCommandAddress.java
index 022904e..9a26f61 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/ChildCommandAddress.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/ChildCommandAddress.java
@@ -10,6 +10,7 @@ public class ChildCommandAddress extends ModifiableCommandAddress {
final List<String> namesModifiable = new ArrayList<>(4);
List<String> names = namesModifiable;
Command command;
+ boolean isCommandTrailing;
public ChildCommandAddress() {
}
@@ -89,7 +90,7 @@ public class ChildCommandAddress extends ModifiableCommandAddress {
}
public void finalizeNames() {
- if (names instanceof ArrayList) {
+ if (names == namesModifiable) {
names = Collections.unmodifiableList(namesModifiable);
}
}
@@ -103,4 +104,17 @@ public class ChildCommandAddress extends ModifiableCommandAddress {
this.parent = parent;
}
+ @Override
+ public boolean isCommandTrailing() {
+ return isCommandTrailing;
+ }
+
+ @Override
+ public void setCommandTrailing(boolean trailing) {
+ if (hasChildren()) {
+ throw new IllegalStateException("Address already has children, this property can't be modified");
+ }
+ isCommandTrailing = trailing;
+ }
+
}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/Command.java b/dicore3/command/src/main/java/io/dico/dicore/command/Command.java
index 53e5821..894e74e 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/Command.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/Command.java
@@ -70,10 +70,11 @@ public abstract class Command {
return this;
}
+ /*
public Command preprocessArguments(IArgumentPreProcessor processor) {
parameterList.setArgumentPreProcessor(processor);
return this;
- }
+ }*/
public final ParameterList getParameterList() {
return parameterList;
@@ -133,56 +134,23 @@ public abstract class Command {
// ---- EXECUTION ----
- public void execute(CommandSender sender, ICommandAddress caller, ArgumentBuffer buffer) {
- ExecutionContext executionContext = new ExecutionContext(sender, caller, this, buffer, false);
-
- try {
- executeWithContext(executionContext);
- } catch (Throwable t) {
- caller.getChatHandler().handleException(sender, executionContext, t);
- }
- }
-
- public void executeWithContext(ExecutionContext context) throws CommandException {
- //System.out.println("In Command.execute(sender, caller, buffer)#try{");
+ public void initializeAndFilterContext(ExecutionContext context) throws CommandException {
int i, n;
for (i = 0, n = contextFilters.size() - postParameterFilterCount; i < n; i++) {
contextFilters.get(i).filterContext(context);
}
- context.parseParameters();
+ context.parse(parameterList);
- for (n = contextFilters.size(); i < n; i++) {
- contextFilters.get(i).filterContext(context);
+ if (!context.isTabComplete()) {
+ for (n = contextFilters.size(); i < n; i++) {
+ contextFilters.get(i).filterContext(context);
+ }
}
-
- //System.out.println("Post-contextfilters");
-
- String message = execute(context.getSender(), context);
- context.sendMessage(EMessageType.RESULT, message);
}
public abstract String execute(CommandSender sender, ExecutionContext context) throws CommandException;
- public List<String> tabComplete(CommandSender sender, ICommandAddress caller, Location location, ArgumentBuffer buffer) {
- ExecutionContext executionContext = new ExecutionContext(sender, caller, this, buffer, true);
- try {
- return tabCompleteWithContext(executionContext, location);
- } catch (CommandException ex) {
- return Collections.emptyList();
- }
- }
-
- public List<String> tabCompleteWithContext(ExecutionContext context, Location location) throws CommandException {
- int i, n;
- for (i = 0, n = contextFilters.size() - postParameterFilterCount; i < n; i++) {
- contextFilters.get(i).filterContext(context);
- }
-
- context.parseParametersQuietly();
- return tabComplete(context.getSender(), context, location);
- }
-
public List<String> tabComplete(CommandSender sender, ExecutionContext context, Location location) {
return context.getSuggestedCompletions(location);
}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/CommandBuilder.java b/dicore3/command/src/main/java/io/dico/dicore/command/CommandBuilder.java
index 63628d3..e527f27 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/CommandBuilder.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/CommandBuilder.java
@@ -265,11 +265,20 @@ public final class CommandBuilder {
* @return this
* @throws IllegalStateException if the current group has no command
*/
- public CommandBuilder addRequiredPermission(String permission) {
+ public CommandBuilder addPermission(String permission) {
return addContextFilter(IContextFilter.permission(permission));
}
/**
+ * Add a required permission to the command of the current group, which can be inherited
+ * @return this
+ * @throws IllegalStateException if the current group has no command
+ */
+ public CommandBuilder addInheritablePermission(String permission) {
+ return addContextFilter(IContextFilter.inheritablePermission(permission));
+ }
+
+ /**
* Jump up a level in the address
*
* @return this
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/CommandResult.java b/dicore3/command/src/main/java/io/dico/dicore/command/CommandResult.java
deleted file mode 100644
index 7c4a891..0000000
--- a/dicore3/command/src/main/java/io/dico/dicore/command/CommandResult.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package io.dico.dicore.command;
-
-/**
- * This enum is intended to provide some constants for default messages.
- * Can be returned by a reflective command.
- * Currently, no constants have an actual message.
- * Prone to removal in the future because of lack of usefullness.
- */
-public enum CommandResult {
- SUCCESS(null),
- QUIET_ERROR(null);
-
- private final String message;
-
- CommandResult(String message) {
- this.message = message;
- }
-
- public String getMessage() {
- return message;
- }
-
-}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/ExecutionContext.java b/dicore3/command/src/main/java/io/dico/dicore/command/ExecutionContext.java
index 2a074e1..a329f40 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/ExecutionContext.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/ExecutionContext.java
@@ -17,27 +17,32 @@ import java.util.*;
* It is also responsible for keeping track of the parameter to complete in the case of a tab completion.
*/
public class ExecutionContext {
- private CommandSender sender;
+ // Sender of the command
+ private final CommandSender sender;
+ // Address while parsing parameters with ContextParser
private ICommandAddress address;
+ // Command to execute
private Command command;
- private ArgumentBuffer originalBuffer;
- private ArgumentBuffer processedBuffer;
+ // if this flag is set, this execution is only for completion purposes.
+ private boolean tabComplete;
+
+ private final ArgumentBuffer buffer;
+ // private ArgumentBuffer processedBuffer;
// caches the buffer's cursor before parsing. This is needed to provide the original input of the player.
private int cursorStart;
// when the context starts parsing parameters, this flag is set, and any subsequent calls to #parseParameters() throw an IllegalStateException.
- private boolean attemptedToParse;
+ //private boolean attemptedToParse;
// The parsed parameter values, mapped by parameter name.
// This also includes default values. All parameters from the parameter list are present if parsing was successful.
- private Map<String, Object> parameterValueMap;
+ private Map<String, Object> parameterValueMap = new HashMap<>();
// this set contains the names of the parameters that were present in the command, and not given a default value.
- private Set<String> parsedParameters;
+ private Set<String> parsedParameters = new HashSet<>();
+
- // if this flag is set, this execution is only for completion purposes.
- private boolean tabComplete;
// these fields store information required to provide completions.
// the parameter to complete is the parameter that threw an exception when it was parsing.
// the exception's message was discarded because it is a completion.
@@ -48,37 +53,11 @@ public class ExecutionContext {
// if this flag is set, any messages sent through the sendMessage methods are discarded.
private boolean muted;
- public ExecutionContext(CommandSender sender, boolean tabComplete) {
+ public ExecutionContext(CommandSender sender, ArgumentBuffer buffer, boolean tabComplete) {
this.sender = Objects.requireNonNull(sender);
+ this.buffer = Objects.requireNonNull(buffer);
this.muted = tabComplete;
this.tabComplete = tabComplete;
- }
-
- /**
- * Construct an execution context that is ready to parse the parameter values.
- *
- * @param sender the sender
- * @param address the address
- * @param buffer the arguments
- * @param tabComplete true if this execution is a tab-completion
- */
- public ExecutionContext(CommandSender sender, ICommandAddress address, Command command, ArgumentBuffer buffer, boolean tabComplete) {
- this(sender, tabComplete);
- targetAcquired(address, command, buffer);
- }
-
- void requireAddressPresent(boolean present) {
- //noinspection DoubleNegation
- if ((address != null) != present) {
- throw new IllegalStateException();
- }
- }
-
- void targetAcquired(ICommandAddress address, Command command, ArgumentBuffer buffer) {
- requireAddressPresent(false);
-
- this.address = Objects.requireNonNull(address);
- this.command = Objects.requireNonNull(command);
// If its tab completing, keep the empty element that might be at the end of the buffer
// due to a space at the end of the command.
@@ -86,65 +65,21 @@ public class ExecutionContext {
if (!tabComplete) {
buffer.dropTrailingEmptyElements();
}
-
- this.originalBuffer = buffer;
- this.processedBuffer = buffer.preprocessArguments(getParameterList().getArgumentPreProcessor());
- this.cursorStart = buffer.getCursor();
}
/**
- * Parse the parameters. If no exception is thrown, they were parsed successfully, and the command may continue post-parameter execution.
+ * Construct an execution context that is ready to parse the parameter values.
*
- * @throws CommandException if an error occurs while parsing the parameters.
- */
- synchronized void parseParameters() throws CommandException {
- requireAddressPresent(true);
- if (attemptedToParse) {
- throw new IllegalStateException();
- }
-
- attemptedToParse = true;
-
- ContextParser parser = new ContextParser(this);
-
- parameterValueMap = parser.getValueMap();
- parsedParameters = parser.getParsedKeys();
-
- parser.parse();
- }
-
-
- /**
- * Attempts to parse parameters, without throwing an exception or sending any message.
- * This method is typically used by tab completions.
- * After calling this method, the context is ready to provide completions.
+ * @param sender the sender
+ * @param address the address
+ * @param command the command
+ * @param buffer the arguments
+ * @param tabComplete true if this execution is a tab-completion
*/
- synchronized void parseParametersQuietly() {
- requireAddressPresent(true);
- if (attemptedToParse) {
- throw new IllegalStateException();
- }
-
- attemptedToParse = true;
-
- boolean before = muted;
- muted = true;
- try {
- ContextParser parser = new ContextParser(this);
-
- parameterValueMap = parser.getValueMap();
- parsedParameters = parser.getParsedKeys();
-
- parser.parse();
-
- parameterToComplete = parser.getCompletionTarget();
- parameterToCompleteCursor = parser.getCompletionCursor();
-
- } catch (CommandException ignored) {
-
- } finally {
- muted = before;
- }
+ public ExecutionContext(CommandSender sender, ICommandAddress address, Command command, ArgumentBuffer buffer, boolean tabComplete) {
+ this(sender, buffer, tabComplete);
+ setAddress(address);
+ setCommand(command);
}
/**
@@ -157,6 +92,13 @@ public class ExecutionContext {
}
/**
+ * @return the buffer of arguments
+ */
+ public ArgumentBuffer getBuffer() {
+ return buffer;
+ }
+
+ /**
* Command's address
*
* @return the command's address
@@ -166,6 +108,15 @@ public class ExecutionContext {
}
/**
+ * Set the address
+ *
+ * @param address the new address
+ */
+ public void setAddress(ICommandAddress address) {
+ this.address = address;
+ }
+
+ /**
* The command
*
* @return the command
@@ -175,12 +126,59 @@ public class ExecutionContext {
}
/**
+ * Set the command
+ *
+ * @param command the new command
+ */
+ public void setCommand(Command command) {
+ this.command = command;
+ }
+
+ /**
+ * @return true if this context is for a tab completion.
+ */
+ public boolean isTabComplete() {
+ return tabComplete;
+ }
+
+ /**
+ * @return true if this context is muted.
+ */
+ public boolean isMuted() {
+ return muted;
+ }
+
+ /**
+ * Parse parameters from the given parameter list,
+ * adding their values to the cache of this context.
+ *
+ * @param parameterList the parameterList
+ * @throws CommandException if the arguments are not valid
+ */
+ public void parse(ParameterList parameterList) throws CommandException {
+ cursorStart = buffer.getCursor();
+
+ ContextParser parser = new ContextParser(this, parameterList, parameterValueMap, parsedParameters);
+
+ try {
+ parser.parse();
+ } finally {
+ if (tabComplete) {
+ parameterToComplete = parser.getCompletionTarget();
+ parameterToCompleteCursor = parser.getCompletionCursor();
+ }
+ }
+
+ }
+
+ /**
* The command's parameter definition.
*
* @return the parameter list
*/
+ @Deprecated
public ParameterList getParameterList() {
- return command.getParameterList();
+ return null;//command.getParameterList();
}
/**
@@ -188,8 +186,9 @@ public class ExecutionContext {
*
* @return the original buffer
*/
+ @Deprecated
public ArgumentBuffer getOriginalBuffer() {
- return originalBuffer;
+ return buffer;
}
/**
@@ -197,8 +196,9 @@ public class ExecutionContext {
*
* @return the argument buffer
*/
+ @Deprecated
public ArgumentBuffer getProcessedBuffer() {
- return processedBuffer;
+ return buffer;
}
/**
@@ -216,7 +216,7 @@ public class ExecutionContext {
* @return original arguments.
*/
public String[] getOriginal() {
- return originalBuffer.getArrayFromIndex(cursorStart);
+ return buffer.getArrayFromIndex(cursorStart);
}
/**
@@ -225,7 +225,7 @@ public class ExecutionContext {
* @return the path used to access this address.
*/
public String[] getRoute() {
- return Arrays.copyOf(originalBuffer.toArray(), address.getDepth());
+ return Arrays.copyOf(buffer.toArray(), address.getDepth());
}
public Formatting getFormat(EMessageType type) {
@@ -238,9 +238,16 @@ public class ExecutionContext {
* @return the full command
*/
public String getRawInput() {
- return originalBuffer.getRawInput();
+ return buffer.getRawInput();
}
+ /**
+ * Get the value of the parameter with the given name
+ *
+ * @param name the parameter's name
+ * @param <T> expected type
+ * @return the parsed value or the default value
+ */
@SuppressWarnings("unchecked")
public <T> T get(String name) {
if (!parameterValueMap.containsKey(name)) {
@@ -254,15 +261,23 @@ public class ExecutionContext {
}
}
- @SuppressWarnings("unchecked")
- public <T> T get(int index) {
- return get(getParameterList().getIndexedParameterName(index));
- }
-
+ /**
+ * Get the value of the flag with the given name
+ *
+ * @param flag the flag's name, without preceding "-"
+ * @param <T> expected type
+ * @return the parsed value or the default value
+ */
public <T> T getFlag(String flag) {
return get("-" + flag);
}
+ @SuppressWarnings("unchecked")
+ @Deprecated
+ public <T> T get(int index) {
+ return null;//get(getParameterList().getIndexedParameterName(index));
+ }
+
/**
* Checks if the parameter by the name was provided in the command's arguments.
*
@@ -279,8 +294,9 @@ public class ExecutionContext {
* @param index the parameter index
* @return true if it was provided
*/
+ @Deprecated
public boolean isProvided(int index) {
- return isProvided(getParameterList().getIndexedParameterName(index));
+ return false;//isProvided(getParameterList().getIndexedParameterName(index));
}
/**
@@ -294,20 +310,6 @@ public class ExecutionContext {
}
/**
- * @return true if this context is muted.
- */
- public boolean isMuted() {
- return muted;
- }
-
- /**
- * @return true if this context is for a tab completion.
- */
- public boolean isTabComplete() {
- return tabComplete;
- }
-
- /**
* Get suggested completions.
*
* @param location The location as passed to {link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}, or null if requested in another way.
@@ -315,19 +317,22 @@ public class ExecutionContext {
*/
public List<String> getSuggestedCompletions(Location location) {
if (parameterToComplete != null) {
- return parameterToComplete.complete(this, location, processedBuffer.getUnaffectingCopy().setCursor(parameterToCompleteCursor));
+ return parameterToComplete.complete(this, location, buffer.getUnaffectingCopy().setCursor(parameterToCompleteCursor));
}
- ParameterList parameterList = getParameterList();
List<String> result = new ArrayList<>();
for (String name : parameterValueMap.keySet()) {
- if (parameterList.getParameterByName(name).isFlag() && !parsedParameters.contains(name)) {
+ if (name.startsWith("-") && !parsedParameters.contains(name)) {
result.add(name);
}
}
return result;
}
+ /*
+ Chat handling
+ */
+
public void sendMessage(String message) {
sendMessage(true, message);
}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/ExtendedCommand.java b/dicore3/command/src/main/java/io/dico/dicore/command/ExtendedCommand.java
index a34d30d..47c2aca 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/ExtendedCommand.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/ExtendedCommand.java
@@ -55,9 +55,10 @@ public abstract class ExtendedCommand<T extends ExtendedCommand<T>> extends Comm
return modifiable ? (T) super.setShortDescription(shortDescription) : newModifiableInstance().setShortDescription(shortDescription);
}
+ /*
@Override
public T preprocessArguments(IArgumentPreProcessor processor) {
return modifiable ? (T) super.preprocessArguments(processor) : newModifiableInstance().preprocessArguments(processor);
- }
+ }*/
}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/ICommandAddress.java b/dicore3/command/src/main/java/io/dico/dicore/command/ICommandAddress.java
index bef20e4..158b1f0 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/ICommandAddress.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/ICommandAddress.java
@@ -2,6 +2,7 @@ package io.dico.dicore.command;
import io.dico.dicore.command.chat.IChatHandler;
import io.dico.dicore.command.parameter.ArgumentBuffer;
+import io.dico.dicore.command.parameter.ParameterList;
import io.dico.dicore.command.predef.PredefinedCommand;
import org.bukkit.command.CommandSender;
@@ -131,6 +132,16 @@ public interface ICommandAddress {
* Get an unmodifiable view of the children of this address.
* Values might be duplicated for aliases.
*
+ * <p>
+ * To iterate children without duplicates, you can do something like this:
+ * <pre>{@code
+ * for (String key : address.getChildrenMainKeys()) {
+ * ICommandAddress child = address.getChild(key);
+ * // do stuff with child
+ * }
+ * }</pre>
+ * </p>
+ *
* @return the children of this address.
*/
Map<String, ? extends ICommandAddress> getChildren();
@@ -144,14 +155,19 @@ public interface ICommandAddress {
ICommandAddress getChild(String key);
/**
- * Query for a child at the given key, with the given context for reference.
- * Can be used to override behaviour of the tree.
+ * Query for a child using the given buffer, with the given context for reference.
+ * Can be used to override behaviour of the address tree.
+ * <p>
+ * The default implementation is as follows:
+ * <pre>{@code
+ * return buffer.hasNext() ? getChild(buffer.next()) : null;
+ * }</pre>
*
- * @param key the key. The name or alias of a command.
* @param context context of a command being executed
+ * @param buffer the buffer. The name or alias of a command.
* @return the child, or null if it's not found, altered freely by the implementation
*/
- ICommandAddress getChild(String key, ExecutionContext context) throws CommandException;
+ ICommandAddress getChild(ExecutionContext context, ArgumentBuffer buffer) throws CommandException;
/**
* Get the command dispatcher for this tree
@@ -165,6 +181,15 @@ public interface ICommandAddress {
*/
IChatHandler getChatHandler();
+ /**
+ * Returns if the command attached to this address should be treated as trailing.
+ * A trailing command is executed whenever the address is scanned for children.
+ * Its parameters are parsed and added to the context.
+ *
+ * @return true if the command attached to this address should be treated as trailing.
+ */
+ boolean isCommandTrailing();
+
static ICommandAddress newChild() {
return new ChildCommandAddress();
}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/ICommandReceiver.java b/dicore3/command/src/main/java/io/dico/dicore/command/ICommandReceiver.java
deleted file mode 100644
index 6660bf8..0000000
--- a/dicore3/command/src/main/java/io/dico/dicore/command/ICommandReceiver.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package io.dico.dicore.command;
-
-import org.bukkit.plugin.Plugin;
-
-import java.lang.reflect.Method;
-
-public interface ICommandReceiver {
-
- interface Factory {
-
- ICommandReceiver getReceiver(ExecutionContext context, Method target, String cmdName);
-
- Plugin getPlugin();
-
- // type is CoroutineContext, but we avoid referring to Kotlin runtime here
- default Object getCoroutineContext() {
- return null;
- }
-
- }
-
-}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/ModifiableCommandAddress.java b/dicore3/command/src/main/java/io/dico/dicore/command/ModifiableCommandAddress.java
index 0c4c476..0cfd755 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/ModifiableCommandAddress.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/ModifiableCommandAddress.java
@@ -2,6 +2,8 @@ package io.dico.dicore.command;
import io.dico.dicore.command.chat.ChatHandlers;
import io.dico.dicore.command.chat.IChatHandler;
+import io.dico.dicore.command.parameter.ArgumentBuffer;
+import io.dico.dicore.command.parameter.ParameterList;
import io.dico.dicore.command.predef.DefaultGroupCommand;
import io.dico.dicore.command.predef.HelpCommand;
import io.dico.dicore.command.predef.PredefinedCommand;
@@ -36,7 +38,7 @@ public abstract class ModifiableCommandAddress implements ICommandAddress {
@Override
public boolean hasUserDeclaredCommand() {
Command command = getCommand();
- return command != null && !(command instanceof PredefinedCommand) && !(command instanceof DefaultGroupCommand);
+ return command != null && !(command instanceof PredefinedCommand);
}
@Override
@@ -139,8 +141,8 @@ public abstract class ModifiableCommandAddress implements ICommandAddress {
}
@Override
- public ChildCommandAddress getChild(String key, ExecutionContext context) throws CommandException {
- return getChild(key);
+ public ChildCommandAddress getChild(ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
+ return buffer.hasNext() ? getChild(buffer.next()) : null;
}
public void addChild(ICommandAddress child) {
@@ -264,6 +266,15 @@ public abstract class ModifiableCommandAddress implements ICommandAddress {
return getRoot();
}
+ @Override
+ public boolean isCommandTrailing() {
+ return false;
+ }
+
+ public void setCommandTrailing(boolean trailing) {
+ throw new UnsupportedOperationException();
+ }
+
void appendDebugInformation(StringBuilder target, String linePrefix, Set<ICommandAddress> seen) {
target.append('\n').append(linePrefix);
if (!seen.add(this)) {
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/PermissionContextFilter.java b/dicore3/command/src/main/java/io/dico/dicore/command/PermissionContextFilter.java
index 3ca1131..75b2035 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/PermissionContextFilter.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/PermissionContextFilter.java
@@ -1,5 +1,6 @@
package io.dico.dicore.command;
+import java.util.List;
import java.util.Objects;
public class PermissionContextFilter implements IContextFilter {
@@ -106,4 +107,30 @@ public class PermissionContextFilter implements IContextFilter {
return failMessage;
}
+ /*
+ private fun getPermissionsOf(address: ICommandAddress) = getPermissionsOf(address, emptyArray(), mutableListOf())
+
+ private fun getPermissionsOf(address: ICommandAddress, path: Array<String>, result: MutableList<String>): List<String> {
+ val command = address.command ?: return result
+
+ var inherited = false
+ for (filter in command.contextFilters) {
+ when (filter) {
+ is PermissionContextFilter -> {
+ if (path.isEmpty()) result.add(filter.permission)
+ else if (filter.isInheritable) result.add(filter.getInheritedPermission(path))
+ }
+ is InheritingContextFilter -> {
+ if (filter.priority == PERMISSION && address.hasParent() && !inherited) {
+ inherited = true
+ getPermissionsOf(address.parent, arrayOf(address.mainKey, *path), result)
+ }
+ }
+ }
+ }
+
+ return result
+ }
+ */
+
}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/RootCommandAddress.java b/dicore3/command/src/main/java/io/dico/dicore/command/RootCommandAddress.java
index 10dade5..44f0540 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/RootCommandAddress.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/RootCommandAddress.java
@@ -85,7 +85,8 @@ public class RootCommandAddress extends ModifiableCommandAddress implements ICom
}
}
- private static void registerMember(Map<String, org.bukkit.command.Command> map, String key, org.bukkit.command.Command value, boolean override) {
+ private static void registerMember(Map<String, org.bukkit.command.Command> map,
+ String key, org.bukkit.command.Command value, boolean override) {
if (override) {
map.put(key, value);
} else {
@@ -147,15 +148,25 @@ public class RootCommandAddress extends ModifiableCommandAddress implements ICom
ModifiableCommandAddress cur = this;
ChildCommandAddress child;
while (buffer.hasNext()) {
- child = cur.getChild(buffer.next(), context);
+ int cursor = buffer.getCursor();
+
+ child = cur.getChild(context, buffer);
+
if (child == null
+ || (context.isTabComplete() && !buffer.hasNext())
|| (child.hasCommand() && !child.getCommand().isVisibleTo(sender))
|| (cur.hasCommand() && cur.getCommand().takePrecedenceOverSubcommand(buffer.peekPrevious(), buffer.getUnaffectingCopy()))) {
- buffer.rewind();
+ buffer.setCursor(cursor);
break;
}
cur = child;
+
+ context.setAddress(child);
+ if (child.hasCommand() && child.isCommandTrailing()) {
+ child.getCommand().initializeAndFilterContext(context);
+ child.getCommand().execute(context.getSender(), context);
+ }
}
return cur;
@@ -173,7 +184,7 @@ public class RootCommandAddress extends ModifiableCommandAddress implements ICom
@Override
public boolean dispatchCommand(CommandSender sender, ArgumentBuffer buffer) {
- ExecutionContext context = new ExecutionContext(sender, false);
+ ExecutionContext context = new ExecutionContext(sender, buffer, false);
ModifiableCommandAddress targetAddress = null;
@@ -189,8 +200,15 @@ public class RootCommandAddress extends ModifiableCommandAddress implements ICom
}
}
- context.targetAcquired(targetAddress, target, buffer);
- target.executeWithContext(context);
+ context.setCommand(target);
+
+ if (!targetAddress.isCommandTrailing()) {
+ target.initializeAndFilterContext(context);
+ String message = target.execute(sender, context);
+ if (message != null && !message.isEmpty()) {
+ context.sendMessage(EMessageType.RESULT, message);
+ }
+ }
} catch (Throwable t) {
if (targetAddress == null) {
@@ -214,15 +232,16 @@ public class RootCommandAddress extends ModifiableCommandAddress implements ICom
@Override
public List<String> getTabCompletions(CommandSender sender, Location location, ArgumentBuffer buffer) {
- ExecutionContext context = new ExecutionContext(sender, true);
+ ExecutionContext context = new ExecutionContext(sender, buffer, true);
try {
ICommandAddress target = getCommandTarget(context, buffer);
List<String> out;
if (target.hasCommand()) {
- context.targetAcquired(target, target.getCommand(), buffer);
- out = target.getCommand().tabCompleteWithContext(context, location);
+ context.setCommand(target.getCommand());
+ target.getCommand().initializeAndFilterContext(context);
+ out = target.getCommand().tabComplete(sender, context, location);
} else {
out = Collections.emptyList();
}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/PreprocessArgs.java b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/PreprocessArgs.java
index 40d6d73..57f53bd 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/PreprocessArgs.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/PreprocessArgs.java
@@ -7,6 +7,7 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
+@Deprecated
public @interface PreprocessArgs {
String tokens() default "\"\"";
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageBuilder.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageBuilder.java
index f5b7cdb..a584e7e 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageBuilder.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageBuilder.java
@@ -13,7 +13,8 @@ import java.util.ListIterator;
public class DefaultPageBuilder implements IPageBuilder {
@Override
- public String getPage(List<IHelpTopic> helpTopics, IPageLayout pageLayout, ICommandAddress target, Permissible viewer, ExecutionContext context, int pageNum, int pageLen) {
+ public String getPage(List<IHelpTopic> helpTopics, IPageLayout pageLayout, ICommandAddress target,
+ Permissible viewer, ExecutionContext context, int pageNum, int pageLen) {
if (pageLen <= 0 || pageNum < 0) {
throw new IllegalArgumentException();
}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/HelpComponentInserter.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/HelpComponentInserter.java
index b043deb..f153165 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/HelpComponentInserter.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/HelpComponentInserter.java
@@ -19,7 +19,7 @@ public class HelpComponentInserter extends HelpTopicModifier {
@Override
protected List<IHelpComponent> modify(List<IHelpComponent> components, ICommandAddress target, Permissible viewer, ExecutionContext context) {
- int componentCount = components.size();
+ // int componentCount = components.size();
for (int i = insertions.size() - 1; i >= 0; i--) {
IInsertion insertion = insertions.get(i);
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentBuffer.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentBuffer.java
index e063000..aa69730 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentBuffer.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentBuffer.java
@@ -1,6 +1,8 @@
package io.dico.dicore.command.parameter;
import io.dico.dicore.command.CommandException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -23,7 +25,7 @@ public class ArgumentBuffer extends AbstractList<String> implements Iterator<Str
// // drop the last element of args if it is empty
// result = args;
//} else {
- result = new String[args.length + 1];
+ result = new String[args.length + 1];
//}
System.arraycopy(args, 0, result, 1, result.length - 1);
result[0] = Objects.requireNonNull(label);
@@ -35,16 +37,21 @@ public class ArgumentBuffer extends AbstractList<String> implements Iterator<Str
* None of the array its elements should be empty.
*
* @param array the array
+ * @throws NullPointerException if the array or any of its elements are null
*/
public ArgumentBuffer(String[] array) {
- this.array = Objects.requireNonNull(array);
+ for (String elem : array) {
+ if (elem == null) throw new NullPointerException("ArgumentBuffer array element");
+ }
+ this.array = array;
+
}
public int getCursor() {
return cursor;
}
- public ArgumentBuffer setCursor(int cursor) {
+ public @NotNull ArgumentBuffer setCursor(int cursor) {
if (cursor <= 0) {
cursor = 0;
} else if (size() <= cursor) {
@@ -60,7 +67,7 @@ public class ArgumentBuffer extends AbstractList<String> implements Iterator<Str
}
@Override
- public String get(int index) {
+ public @NotNull String get(int index) {
return array[index];
}
@@ -91,11 +98,11 @@ public class ArgumentBuffer extends AbstractList<String> implements Iterator<Str
* @return the next value, or null
*/
@Override
- public String next() {
+ public @Nullable String next() {
return hasNext() ? get(cursor++) : null;
}
- public String requireNext(String parameterName) throws CommandException {
+ public @NotNull String requireNext(String parameterName) throws CommandException {
String next = next();
if (next == null) {
throw CommandException.missingArgument(parameterName);
@@ -104,7 +111,7 @@ public class ArgumentBuffer extends AbstractList<String> implements Iterator<Str
}
// useful for completion code
- public String nextOrEmpty() {
+ public @NotNull String nextOrEmpty() {
return hasNext() ? get(cursor++) : "";
}
@@ -113,62 +120,62 @@ public class ArgumentBuffer extends AbstractList<String> implements Iterator<Str
*
* @return the previous value, or null
*/
- public String previous() {
+ public @Nullable String previous() {
return hasPrevious() ? get(--cursor) : null;
}
- public String peekNext() {
+ public @Nullable String peekNext() {
return hasNext() ? get(cursor) : null;
}
- public String peekPrevious() {
+ public @Nullable String peekPrevious() {
return hasPrevious() ? get(cursor - 1) : null;
}
- public ArgumentBuffer advance() {
+ public @NotNull ArgumentBuffer advance() {
return advance(1);
}
- public ArgumentBuffer advance(int amount) {
+ public @NotNull ArgumentBuffer advance(int amount) {
cursor = Math.min(Math.max(0, cursor + amount), size());
return this;
}
- public ArgumentBuffer rewind() {
+ public @NotNull ArgumentBuffer rewind() {
return rewind(1);
}
- public ArgumentBuffer rewind(int amount) {
+ public @NotNull ArgumentBuffer rewind(int amount) {
return advance(-amount);
}
- String[] getArray() {
+ @NotNull String[] getArray() {
return array;
}
- public String[] getArrayFromCursor() {
+ public @NotNull String[] getArrayFromCursor() {
return getArrayFromIndex(cursor);
}
- public String[] getArrayFromIndex(int index) {
+ public @NotNull String[] getArrayFromIndex(int index) {
return Arrays.copyOfRange(array, index, array.length);
}
- public String getRawInput() {
+ public @NotNull String getRawInput() {
return String.join(" ", array);
}
- public String[] toArray() {
+ public @NotNull String[] toArray() {
return array.clone();
}
@Override
- public Iterator<String> iterator() {
+ public @NotNull Iterator<String> iterator() {
return this;
}
@Override
- public ListIterator<String> listIterator() {
+ public @NotNull ListIterator<String> listIterator() {
return new ListIterator<String>() {
@Override
public boolean hasNext() {
@@ -243,13 +250,14 @@ public class ArgumentBuffer extends AbstractList<String> implements Iterator<Str
}
}
- public ArgumentBuffer preprocessArguments(IArgumentPreProcessor preProcessor) {
- String[] array = this.array;
- // processor shouldn't touch any items prior to the cursor
- if (array != (array = preProcessor.process(cursor, array))) {
- return new ArgumentBuffer(array).setCursor(cursor);
- }
- return this;
+ /**
+ * Preprocess this argument buffer with the given preprocessor
+ *
+ * @param preProcessor preprocessor
+ * @return a new ArgumentBuffer with processed contents. Might be this buffer if nothing changed.
+ */
+ public @NotNull ArgumentBuffer preprocessArguments(IArgumentPreProcessor preProcessor) {
+ return preProcessor.process(this, -1);
}
/**
@@ -273,10 +281,15 @@ public class ArgumentBuffer extends AbstractList<String> implements Iterator<Str
}
@SuppressWarnings("MethodDoesntCallSuperMethod")
- public ArgumentBuffer clone() {
+ public @NotNull ArgumentBuffer clone() {
ArgumentBuffer result = getUnaffectingCopy();
this.unaffectingCopy = null;
return result;
}
+ @Override
+ public String toString() {
+ return String.format("ArgumentBuffer(size = %d, cursor = %d)", size(), getCursor());
+ }
+
}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentMergingPreProcessor.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentMergingPreProcessor.java
index 5f7b81d..ce818b7 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentMergingPreProcessor.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentMergingPreProcessor.java
@@ -11,39 +11,44 @@ public class ArgumentMergingPreProcessor implements IArgumentPreProcessor {
}
@Override
- public String[] process(int argStart, String[] args) {
- if (!(0 <= argStart && argStart <= args.length)) {
- throw new IndexOutOfBoundsException();
- }
-
- Parser parser = new Parser(argStart, args.clone());
- return parser.doProcess();
+ public ArgumentBuffer process(ArgumentBuffer buffer, int count) {
+ Parser parser = new Parser(buffer.getArray().clone(), buffer.getCursor(), count);
+ String[] array = parser.doProcess();
+ ArgumentBuffer result = new ArgumentBuffer(array);
+ parser.updateBuffer(result);
+ return result;
}
private class Parser {
- private final int argStart;
private final String[] args;
+ private final int start;
+ private final int count;
+ private int foundSectionCount;
private int currentIndex;
private int sectionStart;
private char closingToken;
private int sectionEnd;
private int removeCount;
- Parser(int argStart, String[] args) {
- this.argStart = argStart;
+ Parser(String[] args, int start, int count) {
+ this.start = start;
this.args = args;
+ this.count = count;
}
private void reset() {
- removeCount = 0;
- closingToken = 0;
+ foundSectionCount = 0;
+ currentIndex = start;
sectionStart = -1;
+ closingToken = 0;
sectionEnd = -1;
- currentIndex = argStart;
+ removeCount = 0;
}
private boolean findNextSectionStart() {
+ if (count >= 0 && foundSectionCount >= count) return false;
+
while (currentIndex < args.length) {
String arg = args[currentIndex];
if (arg == null) {
@@ -127,9 +132,11 @@ public class ArgumentMergingPreProcessor implements IArgumentPreProcessor {
sectionStart = -1;
sectionEnd = -1;
+
+ ++foundSectionCount;
}
- public String[] doProcess() {
+ String[] doProcess() {
reset();
while (findNextSectionStart()) {
@@ -155,6 +162,14 @@ public class ArgumentMergingPreProcessor implements IArgumentPreProcessor {
return result;
}
+ void updateBuffer(ArgumentBuffer buffer) {
+ if (count < 0) {
+ buffer.setCursor(start);
+ } else {
+ buffer.setCursor(currentIndex);
+ }
+ }
+
}
}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ContextParser.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ContextParser.java
index 3bfcf9b..a5afce5 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ContextParser.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ContextParser.java
@@ -13,21 +13,27 @@ public class ContextParser {
private final Parameter<?, ?> m_repeatedParam;
private final List<Parameter<?, ?>> m_indexedParams;
private final int m_maxIndex;
- private final int m_requiredIndex;
+ private final int m_maxRequiredIndex;
- private Map<String, Object> m_valueMap = new HashMap<>();
- private Set<String> m_parsedKeys = new HashSet<>();
+ private Map<String, Object> m_valueMap;
+ private Set<String> m_parsedKeys;
private int m_completionCursor = -1;
private Parameter<?, ?> m_completionTarget = null;
- public ContextParser(ExecutionContext context) {
- this.m_context = context;
- this.m_buffer = context.getProcessedBuffer();
- this.m_paramList = context.getParameterList();
- this.m_repeatedParam = m_paramList.getRepeatedParameter();
- this.m_indexedParams = m_paramList.getIndexedParameters();
- this.m_maxIndex = m_indexedParams.size() - 1;
- this.m_requiredIndex = m_paramList.getRequiredCount() - 1;
+ public ContextParser(ExecutionContext context,
+ ParameterList parameterList,
+ Map<String, Object> valueMap,
+ Set<String> keySet) {
+ m_context = context;
+ m_paramList = parameterList;
+ m_valueMap = valueMap;
+ m_parsedKeys = keySet;
+
+ m_buffer = context.getBuffer();
+ m_repeatedParam = m_paramList.getRepeatedParameter();
+ m_indexedParams = m_paramList.getIndexedParameters();
+ m_maxIndex = m_indexedParams.size() - 1;
+ m_maxRequiredIndex = m_paramList.getRequiredCount() - 1;
}
public ExecutionContext getContext() {
@@ -102,7 +108,7 @@ public class ContextParser {
m_curParamIndex++;
m_curParam = m_indexedParams.get(m_curParamIndex);
prepareRepeatedParameterIfSet();
- requireInput = m_curParamIndex <= m_requiredIndex;
+ requireInput = m_curParamIndex <= m_maxRequiredIndex;
} else if (m_buffer.hasNext()) {
throw new CommandException("Too many arguments for /" + m_context.getAddress().getAddress());
@@ -146,7 +152,7 @@ public class ContextParser {
private void prepareRepeatedParameterIfSet() throws CommandException {
if (m_curParam != null && m_curParam == m_repeatedParam) {
- if (m_curParam.isFlag() && m_curParamIndex < m_requiredIndex) {
+ if (m_curParam.isFlag() && m_curParamIndex < m_maxRequiredIndex) {
Parameter<?, ?> requiredParam = m_indexedParams.get(m_curParamIndex + 1);
reportParameterRequired(requiredParam);
}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/IArgumentPreProcessor.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/IArgumentPreProcessor.java
index b112367..0b8198e 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/IArgumentPreProcessor.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/IArgumentPreProcessor.java
@@ -3,19 +3,26 @@ package io.dico.dicore.command.parameter;
/**
* An interface to process tokens such as quotes
*/
+@Deprecated
public interface IArgumentPreProcessor {
/**
- * Preprocess the arguments without modifying the array.
- * Might return the same array (in which case no changes were made).
+ * Preprocess the arguments contained within the given ArgumentBuffer.
+ * If no changes are made, this might return the same buffer.
+ * Any arguments preceding {@code buffer.getCursor()} will not be affected.
*
- * @param argStart the index within the array where the given arguments start (the part before that identifies the command)
- * @param args the arguments
+ * <p>
+ * If {@code count} is non-negative, it declares a limit on the number of arguments after preprocessing.
+ * In that case, the buffer's cursor is set to the index of the first argument following processed arguments.
+ * </p>
+ *
+ * @param buffer the argument buffer
+ * @param count the maximum number of (processed) arguments
* @return the arguments after preprocessing
*/
- String[] process(int argStart, String[] args);
+ ArgumentBuffer process(ArgumentBuffer buffer, int count);
- IArgumentPreProcessor NONE = (argStart, args) -> args;
+ IArgumentPreProcessor NONE = (buffer, count) -> buffer;
/**
* Get an IArgumentPreProcessor that merges arguments between any two tokens
@@ -31,3 +38,4 @@ public interface IArgumentPreProcessor {
}
}
+
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ParameterList.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ParameterList.java
index 459ced5..613d057 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ParameterList.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ParameterList.java
@@ -5,10 +5,12 @@ import java.util.*;
/**
* IParameter definition for a command
*/
+@SuppressWarnings("UnusedReturnValue")
public class ParameterList {
+ //private ParameterList parent;
private List<Parameter<?, ?>> indexedParameters;
private Map<String, Parameter<?, ?>> byName;
- private IArgumentPreProcessor argumentPreProcessor = IArgumentPreProcessor.NONE;
+ //private IArgumentPreProcessor argumentPreProcessor = IArgumentPreProcessor.NONE;
private int requiredCount = -1;
private boolean repeatFinalParameter;
@@ -18,12 +20,22 @@ public class ParameterList {
// parameter is taken for repeating
private boolean finalParameterMayBeFlag;
+ /*
+ public ParameterList(ParameterList parent) {
+ this();
+ if (parent.repeatFinalParameter) {
+ throw new IllegalArgumentException("Parent may not have repeating parameters");
+ }
+ this.parent = parent;
+ }*/
+
public ParameterList() {
this.indexedParameters = new ArrayList<>();
this.byName = new LinkedHashMap<>();
this.repeatFinalParameter = false;
}
+ /*
public IArgumentPreProcessor getArgumentPreProcessor() {
return argumentPreProcessor;
}
@@ -31,7 +43,7 @@ public class ParameterList {
public ParameterList setArgumentPreProcessor(IArgumentPreProcessor argumentPreProcessor) {
this.argumentPreProcessor = argumentPreProcessor == null ? IArgumentPreProcessor.NONE : argumentPreProcessor;
return this;
- }
+ }*/
public boolean repeatFinalParameter() {
return repeatFinalParameter;
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/EnumParameterType.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/EnumParameterType.java
index e71c6cc..c23e09b 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/EnumParameterType.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/EnumParameterType.java
@@ -20,7 +20,8 @@ public class EnumParameterType<E extends Enum> extends SimpleParameterType<E, Vo
}
}
- @Override protected E parse(Parameter<E, Void> parameter, CommandSender sender, String input) throws CommandException {
+ @Override
+ protected E parse(Parameter<E, Void> parameter, CommandSender sender, String input) throws CommandException {
for (E constant : universe) {
if (constant.name().equalsIgnoreCase(input)) {
return constant;
@@ -30,7 +31,8 @@ public class EnumParameterType<E extends Enum> extends SimpleParameterType<E, Vo
throw CommandException.invalidArgument(parameter.getName(), "the enum value does not exist");
}
- @Override public List<String> complete(Parameter<E, Void> parameter, CommandSender sender, Location location, ArgumentBuffer buffer) {
+ @Override
+ public List<String> complete(Parameter<E, Void> parameter, CommandSender sender, Location location, ArgumentBuffer buffer) {
String input = buffer.next().toUpperCase();
List<String> result = new ArrayList<>();
for (E constant : universe) {
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterType.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterType.java
index d89fd10..e1a62fa 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterType.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterType.java
@@ -146,56 +146,4 @@ public abstract class ParameterType<TReturn, TParamInfo> {
}
- public @interface Reference {
-
- /**
- * The path to the static field holding the parameter type referred.
- *
- * @return The path
- */
- String value();
- }
-
- public static class ReferenceUtil {
-
- private ReferenceUtil() {
-
- }
-
-
- /**
- * Get the ParameterType with the associated Reference
- *
- * @param ref the reference
- * @return the parameter type object
- * @throws IllegalArgumentException if the class is found, but the field doesn't exist.
- * @throws IllegalStateException if this method fails to find the object for any other reason
- */
- public static Object getReference(Reference ref) {
- String[] path = ref.value().split("\\.");
- if (path.length < 2) {
- throw new IllegalStateException();
- }
-
- String fieldName = path[path.length - 1];
- String className = String.join(".", Arrays.copyOfRange(path, 0, path.length - 1));
-
- Class<?> clazz;
- try {
- clazz = Class.forName(className);
- } catch (ClassNotFoundException ex) {
- throw new IllegalArgumentException(ex);
- }
-
- Object result = Reflection.getStaticFieldValue(clazz, fieldName);
-
- if (result == null) {
- throw new IllegalStateException();
- }
-
- return result;
- }
-
- }
-
}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/predef/DefaultGroupCommand.java b/dicore3/command/src/main/java/io/dico/dicore/command/predef/DefaultGroupCommand.java
index 3988da2..e664cef 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/predef/DefaultGroupCommand.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/predef/DefaultGroupCommand.java
@@ -38,9 +38,9 @@ public class DefaultGroupCommand extends PredefinedCommand<DefaultGroupCommand>
noArgumentFilter = new IContextFilter() {
@Override
public void filterContext(ExecutionContext context) throws CommandException {
- if (context.getProcessedBuffer().hasNext()) {
+ if (context.getBuffer().hasNext()) {
throw new CommandException("No such command: /" + context.getAddress().getAddress()
- + " " + context.getProcessedBuffer().next());
+ + " " + context.getBuffer().next());
}
}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ICommandInterceptor.java b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ICommandInterceptor.java
new file mode 100644
index 0000000..67b65e4
--- /dev/null
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ICommandInterceptor.java
@@ -0,0 +1,36 @@
+package io.dico.dicore.command.registration.reflect;
+
+import io.dico.dicore.command.ExecutionContext;
+
+import java.lang.reflect.Method;
+
+public interface ICommandInterceptor {
+
+ /**
+ * Get the receiver of the command, if applicable.
+ * A command has a receiver if its first parameter implements {@link ICommandReceiver}
+ * and its instance object implements this interface.
+ *
+ * @param context the context of execution
+ * @param target the method of the command
+ * @param cmdName the name of the command
+ * @return the receiver
+ */
+ default ICommandReceiver getReceiver(ExecutionContext context, Method target, String cmdName) {
+ return null;
+ }
+
+ /**
+ * If applicable, get the coroutine context to use in suspend functions (Kotlin only).
+ * The return type is object to avoid depending on the kotlin runtime.
+ *
+ * @param context the context of execution
+ * @param target the method of the command
+ * @param cmdName the name of the command
+ * @return the coroutine context
+ */
+ default Object getCoroutineContext(ExecutionContext context, Method target, String cmdName) {
+ return null;
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ICommandReceiver.java b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ICommandReceiver.java
new file mode 100644
index 0000000..bdcb568
--- /dev/null
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ICommandReceiver.java
@@ -0,0 +1,5 @@
+package io.dico.dicore.command.registration.reflect;
+
+public interface ICommandReceiver {
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveCommand.java b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveCommand.java
index 591d824..ee90efe 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveCommand.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveCommand.java
@@ -15,6 +15,8 @@ public final class ReflectiveCommand extends Command {
private final Method method;
private final Object instance;
private String[] parameterOrder;
+
+ // hasContinuation | hasContext | hasSender | hasReceiver
private final int flags;
ReflectiveCommand(IParameterTypeSelector selector, Method method, Object instance) throws CommandParseException {
@@ -56,6 +58,8 @@ public final class ReflectiveCommand extends Command {
return instance;
}
+ public String getCmdName() { return cmdAnnotation.value(); }
+
void setParameterOrder(String[] parameterOrder) {
this.parameterOrder = parameterOrder;
}
@@ -86,18 +90,24 @@ public final class ReflectiveCommand extends Command {
Object[] args = new Object[parameterOrder.length + start];
int i = 0;
- if ((flags & 1) != 0) {
+
+ int mask = 1;
+ if ((flags & mask) != 0) {
try {
- args[i++] = ((ICommandReceiver.Factory) instance).getReceiver(context, method, cmdAnnotation.value());
+ args[i++] = ((ICommandInterceptor) instance).getReceiver(context, method, getCmdName());
} catch (Exception ex) {
handleException(ex);
return null; // unreachable
}
}
- if ((flags & 2) != 0) {
+
+ mask <<= 1;
+ if ((flags & mask) != 0) {
args[i++] = sender;
}
- if ((flags & 4) != 0) {
+
+ mask <<= 1;
+ if ((flags & mask) != 0) {
args[i++] = context;
}
@@ -105,11 +115,12 @@ public final class ReflectiveCommand extends Command {
args[i] = context.get(parameterOrder[i - start]);
}
- if (!isSuspendFunction()) {
- return callSynchronously(args);
+ mask <<= 1;
+ if ((flags & mask) != 0) {
+ return callAsCoroutine(context, args);
}
- return callAsCoroutine(context, args);
+ return callSynchronously(args);
}
private boolean isSuspendFunction() {
@@ -137,9 +148,6 @@ public final class ReflectiveCommand extends Command {
if (returned instanceof String) {
return (String) returned;
}
- if (returned instanceof CommandResult) {
- return ((CommandResult) returned).getMessage();
- }
return null;
}
@@ -160,7 +168,7 @@ public final class ReflectiveCommand extends Command {
}
private String callAsCoroutine(ExecutionContext context, Object[] args) {
- return KotlinReflectiveRegistrationKt.callAsCoroutine(this, (ICommandReceiver.Factory) instance, context, args);
+ return KotlinReflectiveRegistrationKt.callAsCoroutine(this, (ICommandInterceptor) instance, context, args);
}
}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveRegistration.java b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveRegistration.java
index 1279c2b..1405414 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveRegistration.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveRegistration.java
@@ -3,7 +3,6 @@ package io.dico.dicore.command.registration.reflect;
import io.dico.dicore.command.*;
import io.dico.dicore.command.annotation.*;
import io.dico.dicore.command.annotation.GroupMatchedCommands.GroupEntry;
-import io.dico.dicore.command.parameter.IArgumentPreProcessor;
import io.dico.dicore.command.parameter.Parameter;
import io.dico.dicore.command.parameter.ParameterList;
import io.dico.dicore.command.parameter.type.IParameterTypeSelector;
@@ -199,15 +198,20 @@ public class ReflectiveRegistration {
static int parseCommandAttributes(IParameterTypeSelector selector, Method method, ReflectiveCommand command, java.lang.reflect.Parameter[] parameters) throws CommandParseException {
ParameterList list = command.getParameterList();
+
boolean hasReceiverParameter = false;
boolean hasSenderParameter = false;
+ boolean hasContextParameter = false;
+ boolean hasContinuationParameter = false;
+
int start = 0;
- Class<?> firstParameterType = null;
+ int end = parameters.length;
+
Class<?> senderParameterType = null;
if (parameters.length > start
- && command.getInstance() instanceof ICommandReceiver.Factory
- && ICommandReceiver.class.isAssignableFrom(firstParameterType = parameters[start].getType())) {
+ && command.getInstance() instanceof ICommandInterceptor
+ && ICommandReceiver.class.isAssignableFrom(parameters[start].getType())) {
hasReceiverParameter = true;
start++;
}
@@ -217,20 +221,18 @@ public class ReflectiveRegistration {
start++;
}
- boolean hasContextParameter = false;
if (parameters.length > start && parameters[start].getType() == ExecutionContext.class) {
hasContextParameter = true;
start++;
}
+ if (parameters.length > start && parameters[end - 1].getType().getName().equals("kotlin.coroutines.Continuation")) {
+ hasContinuationParameter = true;
+ end--;
+ }
+
String[] parameterNames = lookupParameterNames(method, parameters, start);
- for (int i = start, n = parameters.length; i < n; i++) {
- if (parameters[i].getType().getName().equals("kotlin.coroutines.Continuation")) {
- List<String> temp = new ArrayList<>(Arrays.asList(parameterNames));
- temp.remove(i - start);
- parameterNames = temp.toArray(new String[0]);
- continue;
- }
+ for (int i = start, n = end; i < n; i++) {
Parameter<?, ?> parameter = parseParameter(selector, method, parameters[i], parameterNames[i - start]);
list.addParameter(parameter);
}
@@ -256,11 +258,12 @@ public class ReflectiveRegistration {
list.setRequiredCount(list.getIndexedParameters().size());
}
+ /*
PreprocessArgs preprocessArgs = method.getAnnotation(PreprocessArgs.class);
if (preprocessArgs != null) {
IArgumentPreProcessor preProcessor = IArgumentPreProcessor.mergeOnTokens(preprocessArgs.tokens(), preprocessArgs.escapeChar());
list.setArgumentPreProcessor(preProcessor);
- }
+ }*/
Desc desc = method.getAnnotation(Desc.class);
if (desc != null) {
@@ -286,7 +289,16 @@ public class ReflectiveRegistration {
list.setRepeatFinalParameter(parameters.length > start && parameters[parameters.length - 1].isVarArgs());
list.setFinalParameterMayBeFlag(true);
- return (hasSenderParameter ? 2 : 0) | (hasContextParameter ? 4 : 0) | (hasReceiverParameter ? 1 : 0);
+
+ int flags = 0;
+ if (hasContinuationParameter) flags |= 1;
+ flags <<= 1;
+ if (hasContextParameter) flags |= 1;
+ flags <<= 1;
+ if (hasSenderParameter) flags |= 1;
+ flags <<= 1;
+ if (hasReceiverParameter) flags |= 1;
+ return flags;
}
public static int parseCommandAttributes(IParameterTypeSelector selector, Method method, ReflectiveCommand command) throws CommandParseException {
@@ -373,7 +385,7 @@ public class ReflectiveRegistration {
@Cmd({"tp", "tpto"})
@RequirePermissions("teleport.self")
- public (static) String|void|CommandResult onCommand(Player sender, Player target, @Flag("force", permission = "teleport.self.force") boolean force) {
+ public (static) String|void onCommand(Player sender, Player target, @Flag("force", permission = "teleport.self.force") boolean force) {
Validate.isTrue(force || !hasTpToggledOff(target), "Target has teleportation disabled. Use -force to ignore");
sender.teleport(target);
//return