summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDico Karssiens <dico.karssiens@gmail.com>2018-09-30 17:05:42 +0100
committerDico Karssiens <dico.karssiens@gmail.com>2018-09-30 17:05:42 +0100
commitc4801757a2fda147e1cee65f70f80fb215047525 (patch)
treecc19a113ede79396b56b0adb0ebdb12d63613e2f
parent7f36b6f561e17fa76c184053d46254faff69142b (diff)
Some changes
-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
-rw-r--r--dicore3/command/src/main/kotlin/io/dico/dicore/command/registration/reflect/KotlinReflectiveRegistration.kt16
-rw-r--r--dicore3/command/src/test/java/io/dico/dicore/command/example/ParameterInfoObjectExample.java73
-rw-r--r--gradle/wrapper/gradle-wrapper.jarbin0 -> 54413 bytes
-rw-r--r--gradle/wrapper/gradle-wrapper.properties5
-rw-r--r--gradlew172
-rw-r--r--gradlew.bat84
-rw-r--r--src/main/kotlin/io/dico/parcels2/command/AbstractParcelCommands.kt16
-rw-r--r--src/main/kotlin/io/dico/parcels2/command/ParcelCommandBuilder.kt5
-rw-r--r--src/main/kotlin/io/dico/parcels2/command/ParcelCommandReceivers.kt2
-rw-r--r--src/main/kotlin/io/dico/parcels2/command/ParcelParameterTypes.kt4
-rw-r--r--src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt2
-rw-r--r--src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelGenerator.kt1
-rw-r--r--src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelProviderImpl.kt11
-rw-r--r--src/main/kotlin/io/dico/parcels2/listener/ParcelListeners.kt2
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/Hikari.kt2
41 files changed, 835 insertions, 403 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
diff --git a/dicore3/command/src/main/kotlin/io/dico/dicore/command/registration/reflect/KotlinReflectiveRegistration.kt b/dicore3/command/src/main/kotlin/io/dico/dicore/command/registration/reflect/KotlinReflectiveRegistration.kt
index c4aa134..2ef6e39 100644
--- a/dicore3/command/src/main/kotlin/io/dico/dicore/command/registration/reflect/KotlinReflectiveRegistration.kt
+++ b/dicore3/command/src/main/kotlin/io/dico/dicore/command/registration/reflect/KotlinReflectiveRegistration.kt
@@ -1,9 +1,6 @@
package io.dico.dicore.command.registration.reflect
-import io.dico.dicore.command.CommandException
-import io.dico.dicore.command.EMessageType
-import io.dico.dicore.command.ExecutionContext
-import io.dico.dicore.command.ICommandReceiver
+import io.dico.dicore.command.*
import kotlinx.coroutines.CoroutineStart.UNDISPATCHED
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.GlobalScope
@@ -22,15 +19,16 @@ fun isSuspendFunction(method: Method): Boolean {
fun callAsCoroutine(
command: ReflectiveCommand,
- factory: ICommandReceiver.Factory,
+ factory: ICommandInterceptor,
context: ExecutionContext,
args: Array<Any?>
): String? {
+ val coroutineContext = factory.getCoroutineContext(context, command.method, command.cmdName) as CoroutineContext
// UNDISPATCHED causes the handler to run until the first suspension point on the current thread,
// meaning command handlers that don't have suspension points will run completely synchronously.
// Tasks that take time to compute should suspend the coroutine and resume on another thread.
- val job = GlobalScope.async(context = factory.coroutineContext as CoroutineContext, start = UNDISPATCHED) {
+ val job = GlobalScope.async(context = coroutineContext, start = UNDISPATCHED) {
suspendCoroutineUninterceptedOrReturn<Any?> { cont ->
command.method.invoke(command.instance, *args, cont.intercepted())
}
@@ -41,12 +39,12 @@ fun callAsCoroutine(
}
job.invokeOnCompletion {
- val cc = context.address.chatHandler
+ val chatHandler = context.address.chatHandler
try {
val result = job.getResult()
- cc.sendMessage(context.sender, EMessageType.RESULT, result)
+ chatHandler.sendMessage(context.sender, EMessageType.RESULT, result)
} catch (ex: Throwable) {
- cc.handleException(context.sender, context, ex)
+ chatHandler.handleException(context.sender, context, ex)
}
}
diff --git a/dicore3/command/src/test/java/io/dico/dicore/command/example/ParameterInfoObjectExample.java b/dicore3/command/src/test/java/io/dico/dicore/command/example/ParameterInfoObjectExample.java
new file mode 100644
index 0000000..1cd4e23
--- /dev/null
+++ b/dicore3/command/src/test/java/io/dico/dicore/command/example/ParameterInfoObjectExample.java
@@ -0,0 +1,73 @@
+package io.dico.dicore.command.example;
+
+import io.dico.dicore.command.CommandBuilder;
+import io.dico.dicore.command.CommandException;
+import io.dico.dicore.command.Validate;
+import io.dico.dicore.command.annotation.Cmd;
+import io.dico.dicore.command.parameter.ArgumentBuffer;
+import io.dico.dicore.command.parameter.Parameter;
+import io.dico.dicore.command.parameter.type.ParameterConfig;
+import io.dico.dicore.command.parameter.type.ParameterType;
+import org.bukkit.command.CommandSender;
+
+public class ParameterInfoObjectExample {
+
+ private @interface ParentPermission {
+ String value();
+ }
+
+ static class MyInfoObject {
+ public static final ParameterConfig<ParentPermission, MyInfoObject> config = new ParameterConfig<ParentPermission, MyInfoObject>() {
+ @Override
+ protected MyInfoObject toParameterInfo(ParentPermission annotation) {
+ return new MyInfoObject(annotation.value());
+ }
+ };
+
+ private String permissionParent;
+
+ MyInfoObject(String permissionParent) {
+ this.permissionParent = permissionParent;
+ }
+
+ public String getPermissionParent() {
+ return permissionParent;
+ }
+ }
+
+ static class MyParameterType extends ParameterType<String, MyInfoObject> {
+
+ public MyParameterType() {
+ super(String.class, MyInfoObject.config);
+ }
+
+ @Override
+ public String parse(Parameter<String, MyInfoObject> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException {
+ String value = buffer.next();
+
+ MyInfoObject mio = parameter.getParamInfo();
+ if (mio != null) {
+ String permission = mio.permissionParent + "." + value;
+ Validate.isAuthorized(sender, permission);
+ }
+
+ return value;
+ }
+ }
+
+ static class MyCommands {
+
+ @Cmd("test")
+ Object cmdTest(@ParentPermission("test.permission") String value) {
+ return "You have permission to use the argument '" + value + "'!";
+ }
+
+ }
+
+ static void main(String[] args) {
+ new CommandBuilder()
+ .addParameterType(false, new MyParameterType())
+ .registerCommands(new MyCommands());
+ }
+
+}
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..1948b90
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..d2c45a4
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..cccdd3d
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/src/main/kotlin/io/dico/parcels2/command/AbstractParcelCommands.kt b/src/main/kotlin/io/dico/parcels2/command/AbstractParcelCommands.kt
index bcc7997..eaa9f57 100644
--- a/src/main/kotlin/io/dico/parcels2/command/AbstractParcelCommands.kt
+++ b/src/main/kotlin/io/dico/parcels2/command/AbstractParcelCommands.kt
@@ -1,9 +1,8 @@
package io.dico.parcels2.command
-import io.dico.dicore.command.CommandException
-import io.dico.dicore.command.EMessageType
-import io.dico.dicore.command.ExecutionContext
-import io.dico.dicore.command.ICommandReceiver
+import io.dico.dicore.command.*
+import io.dico.dicore.command.registration.reflect.ICommandInterceptor
+import io.dico.dicore.command.registration.reflect.ICommandReceiver
import io.dico.parcels2.*
import io.dico.parcels2.PlayerProfile.Real
import io.dico.parcels2.PlayerProfile.Unresolved
@@ -13,13 +12,16 @@ import org.bukkit.entity.Player
import org.bukkit.plugin.Plugin
import java.lang.reflect.Method
-abstract class AbstractParcelCommands(val plugin: ParcelsPlugin) : ICommandReceiver.Factory {
- override fun getPlugin(): Plugin = plugin
+abstract class AbstractParcelCommands(val plugin: ParcelsPlugin) : ICommandInterceptor {
override fun getReceiver(context: ExecutionContext, target: Method, cmdName: String): ICommandReceiver {
return getParcelCommandReceiver(plugin.parcelProvider, context, target, cmdName)
}
+ override fun getCoroutineContext(context: ExecutionContext?, target: Method?, cmdName: String?): Any {
+ return plugin.coroutineContext
+ }
+
protected fun checkConnected(action: String) {
if (!plugin.storage.isConnected) err("Parcels cannot $action right now because of a database error")
}
@@ -57,8 +59,6 @@ abstract class AbstractParcelCommands(val plugin: ParcelsPlugin) : ICommandRecei
.format(progress * 100, elapsedTime / 1000.0)
)
}
-
- override fun getCoroutineContext() = plugin.coroutineContext
}
fun err(message: String): Nothing = throw CommandException(message) \ No newline at end of file
diff --git a/src/main/kotlin/io/dico/parcels2/command/ParcelCommandBuilder.kt b/src/main/kotlin/io/dico/parcels2/command/ParcelCommandBuilder.kt
index 2777b7f..721ce2d 100644
--- a/src/main/kotlin/io/dico/parcels2/command/ParcelCommandBuilder.kt
+++ b/src/main/kotlin/io/dico/parcels2/command/ParcelCommandBuilder.kt
@@ -1,6 +1,7 @@
package io.dico.parcels2.command
import io.dico.dicore.command.*
+import io.dico.dicore.command.parameter.ArgumentBuffer
import io.dico.dicore.command.predef.DefaultGroupCommand
import io.dico.dicore.command.registration.reflect.ReflectiveRegistration
import io.dico.parcels2.Interactables
@@ -107,10 +108,12 @@ class SpecialCommandAddress : ChildCommandAddress() {
}
}
+ // h:1
@Throws(CommandException::class)
- override fun getChild(key: String, context: ExecutionContext): ChildCommandAddress? {
+ override fun getChild(context: ExecutionContext, buffer: ArgumentBuffer): ChildCommandAddress? {
speciallyParsedIndex = null
+ val key = buffer.next() ?: return null
for (specialKey in speciallyTreatedKeys) {
if (key.startsWith(specialKey)) {
val result = getChild(specialKey.substring(0, specialKey.length - 1))
diff --git a/src/main/kotlin/io/dico/parcels2/command/ParcelCommandReceivers.kt b/src/main/kotlin/io/dico/parcels2/command/ParcelCommandReceivers.kt
index 8f6dabc..15548b4 100644
--- a/src/main/kotlin/io/dico/parcels2/command/ParcelCommandReceivers.kt
+++ b/src/main/kotlin/io/dico/parcels2/command/ParcelCommandReceivers.kt
@@ -2,7 +2,7 @@ package io.dico.parcels2.command
import io.dico.dicore.command.CommandException
import io.dico.dicore.command.ExecutionContext
-import io.dico.dicore.command.ICommandReceiver
+import io.dico.dicore.command.registration.reflect.ICommandReceiver
import io.dico.dicore.command.Validate
import io.dico.parcels2.*
import io.dico.parcels2.Privilege.*
diff --git a/src/main/kotlin/io/dico/parcels2/command/ParcelParameterTypes.kt b/src/main/kotlin/io/dico/parcels2/command/ParcelParameterTypes.kt
index 736e568..a9f5498 100644
--- a/src/main/kotlin/io/dico/parcels2/command/ParcelParameterTypes.kt
+++ b/src/main/kotlin/io/dico/parcels2/command/ParcelParameterTypes.kt
@@ -30,7 +30,7 @@ class ParcelParameterType(val parcelProvider: ParcelProvider) : ParameterType<Pa
val regex = Regex.fromLiteral("((.+)->)?([0-9]+):([0-9]+)")
override fun parse(parameter: Parameter<Parcel, Void>, sender: CommandSender, buffer: ArgumentBuffer): Parcel {
- val matchResult = regex.matchEntire(buffer.next())
+ val matchResult = regex.matchEntire(buffer.next()!!)
?: invalidInput(parameter, "must match (w->)?a:b (/${regex.pattern}/)")
val world = parcelProvider.getTargetWorld(matchResult.groupValues[2], sender, parameter)
@@ -66,7 +66,7 @@ class ProfileParameterType : ParameterType<PlayerProfile, Int>(PlayerProfile::cl
val allowReal = (info and REAL) != 0
val allowFake = (info and FAKE) != 0
- val input = buffer.next()
+ val input = buffer.next()!!
return PlayerProfile.byName(input, allowReal, allowFake)
}
diff --git a/src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt b/src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt
index 70a8dda..8891912 100644
--- a/src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt
+++ b/src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt
@@ -91,7 +91,7 @@ sealed class ParcelTarget(val world: ParcelWorld, val parsedKind: Int, val isDef
ParameterType<ParcelTarget, Int>(ParcelTarget::class.java, TargetKind) {
override fun parse(parameter: Parameter<ParcelTarget, Int>, sender: CommandSender, buffer: ArgumentBuffer): ParcelTarget {
- var input = buffer.next()
+ var input = buffer.next()!!
val worldString = input.substringBefore("/", missingDelimiterValue = "")
input = input.substringAfter("/")
diff --git a/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelGenerator.kt b/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelGenerator.kt
index e9ec148..9e43c05 100644
--- a/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelGenerator.kt
+++ b/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelGenerator.kt
@@ -279,7 +279,6 @@ class DefaultParcelGenerator(
val region = getRegion(parcel)
val blocks = parcelTraverser.traverseRegion(region)
val blockCount = region.blockCount.toDouble()
-
val world = world
val floorHeight = o.floorHeight
val airType = airType
diff --git a/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelProviderImpl.kt b/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelProviderImpl.kt
index 74545d6..48a7fee 100644
--- a/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelProviderImpl.kt
+++ b/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelProviderImpl.kt
@@ -50,7 +50,7 @@ class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider {
return
}
- //val newlyCreatedWorlds = mutableListOf<ParcelWorld>()
+ val newlyCreatedWorlds = mutableListOf<ParcelWorld>()
for ((worldName, worldOptions) in options.worlds.entries) {
var parcelWorld = _worlds[worldName]
if (parcelWorld != null) continue
@@ -70,7 +70,7 @@ class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider {
val time = DateTime.now()
plugin.storage.setWorldCreationTime(parcelWorld.id, time)
parcelWorld.creationTime = time
- //newlyCreatedWorlds.add(parcelWorld)
+ newlyCreatedWorlds.add(parcelWorld)
} else {
GlobalScope.launch(context = Dispatchers.Unconfined) {
parcelWorld.creationTime = plugin.storage.getWorldCreationTime(parcelWorld.id).await() ?: DateTime.now()
@@ -80,10 +80,10 @@ class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider {
_worlds[worldName] = parcelWorld
}
- loadStoredData()
+ loadStoredData(newlyCreatedWorlds.toSet())
}
- private fun loadStoredData() {
+ private fun loadStoredData(newlyCreatedWorlds: Collection<ParcelWorld> = emptyList()) {
plugin.launch(Dispatchers.Default) {
val migration = plugin.options.migration
if (migration.enabled) {
@@ -105,9 +105,8 @@ class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider {
val channel = plugin.storage.transmitAllParcelData()
while (true) {
val (id, data) = channel.receiveOrNull() ?: break
- if (data == null) continue
val parcel = getParcelById(id) ?: continue
- parcel.copyData(data, callerIsDatabase = true)
+ data?.let { parcel.copyData(it, callerIsDatabase = true) }
}
}
diff --git a/src/main/kotlin/io/dico/parcels2/listener/ParcelListeners.kt b/src/main/kotlin/io/dico/parcels2/listener/ParcelListeners.kt
index 04941b4..59d10e7 100644
--- a/src/main/kotlin/io/dico/parcels2/listener/ParcelListeners.kt
+++ b/src/main/kotlin/io/dico/parcels2/listener/ParcelListeners.kt
@@ -85,8 +85,6 @@ class ParcelListeners(
newTo = newTo.add(it, delta * 100 * if (it == Dimension.Y) 0.5 else speed)
}
-
-
event.to = Location(
toLoc.world,
newTo.x, newTo.y.clampMin(0.0).clampMax(255.0), newTo.z,
diff --git a/src/main/kotlin/io/dico/parcels2/storage/Hikari.kt b/src/main/kotlin/io/dico/parcels2/storage/Hikari.kt
index d1500d5..480d533 100644
--- a/src/main/kotlin/io/dico/parcels2/storage/Hikari.kt
+++ b/src/main/kotlin/io/dico/parcels2/storage/Hikari.kt
@@ -32,7 +32,7 @@ fun getHikariConfig(dialectName: String,
username = dco.username
password = dco.password
connectionTimeout = 15000
- leakDetectionThreshold = 30000
+ leakDetectionThreshold = 10000
connectionTestQuery = "SELECT 1"