Some changes
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -265,10 +265,19 @@ 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
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.
|
||||
* @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 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.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,6 +91,13 @@ public class ExecutionContext {
|
||||
return sender;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the buffer of arguments
|
||||
*/
|
||||
public ArgumentBuffer getBuffer() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command's address
|
||||
*
|
||||
@@ -165,6 +107,15 @@ public class ExecutionContext {
|
||||
return address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the address
|
||||
*
|
||||
* @param address the new address
|
||||
*/
|
||||
public void setAddress(ICommandAddress address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
/**
|
||||
* The command
|
||||
*
|
||||
@@ -174,13 +125,60 @@ public class ExecutionContext {
|
||||
return command;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -293,20 +309,6 @@ public class ExecutionContext {
|
||||
return parameterToComplete;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
@Deprecated
|
||||
public @interface PreprocessArgs {
|
||||
|
||||
String tokens() default "\"\"";
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package io.dico.dicore.command.registration.reflect;
|
||||
|
||||
public interface ICommandReceiver {
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -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
|
||||
172
gradlew
vendored
Normal file
172
gradlew
vendored
Normal file
@@ -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" "$@"
|
||||
84
gradlew.bat
vendored
Normal file
84
gradlew.bat
vendored
Normal file
@@ -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
|
||||
@@ -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)
|
||||
@@ -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))
|
||||
|
||||
@@ -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.*
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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("/")
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -32,7 +32,7 @@ fun getHikariConfig(dialectName: String,
|
||||
username = dco.username
|
||||
password = dco.password
|
||||
connectionTimeout = 15000
|
||||
leakDetectionThreshold = 30000
|
||||
leakDetectionThreshold = 10000
|
||||
connectionTestQuery = "SELECT 1"
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user