diff --git a/pom.xml b/pom.xml
index d827781..ef4224f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -26,6 +26,9 @@
${java.version}
${java.version}
+
+ -parameters
+
diff --git a/src/main/java/com/io/yutian/elementoriginlib/ElementOriginLib.java b/src/main/java/com/io/yutian/elementoriginlib/ElementOriginLib.java
index e260bef..889bcc7 100644
--- a/src/main/java/com/io/yutian/elementoriginlib/ElementOriginLib.java
+++ b/src/main/java/com/io/yutian/elementoriginlib/ElementOriginLib.java
@@ -4,6 +4,7 @@ import com.io.yutian.elementoriginlib.lang.Lang;
import com.io.yutian.elementoriginlib.listener.GuiHandlerListener;
import com.io.yutian.elementoriginlib.listener.PlayerChatInputListener;
import com.io.yutian.elementoriginlib.logger.Logger;
+import com.io.yutian.elementoriginlib.manager.CommandManager;
import com.io.yutian.elementoriginlib.redis.RedisIO;
import net.byteflux.libby.*;
import net.byteflux.libby.logging.LogLevel;
@@ -19,6 +20,8 @@ public final class ElementOriginLib extends JavaPlugin {
private static RedisIO redisIO;
+ private static CommandManager commandManager;
+
@Override
public void onEnable() {
instance = this;
@@ -28,6 +31,9 @@ public final class ElementOriginLib extends JavaPlugin {
new GuiHandlerListener(this);
new PlayerChatInputListener(this);
+ commandManager = new CommandManager(this);
+ commandManager.registerPluginCommand("elementoriginlib");
+
Lang.registerLangFile(this);
Lang.reload();
diff --git a/src/main/java/com/io/yutian/elementoriginlib/command/Command.java b/src/main/java/com/io/yutian/elementoriginlib/command/Command.java
deleted file mode 100644
index 6c6972e..0000000
--- a/src/main/java/com/io/yutian/elementoriginlib/command/Command.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.io.yutian.elementoriginlib.command;
-
-@FunctionalInterface
-public interface Command {
-
- void run(S context);
-
-}
diff --git a/src/main/java/com/io/yutian/elementoriginlib/command/CommandContext.java b/src/main/java/com/io/yutian/elementoriginlib/command/CommandContext.java
index f2d2f05..1d93a61 100644
--- a/src/main/java/com/io/yutian/elementoriginlib/command/CommandContext.java
+++ b/src/main/java/com/io/yutian/elementoriginlib/command/CommandContext.java
@@ -7,18 +7,25 @@ import java.util.Map;
public class CommandContext {
+ private Object commandInstance;
+
private String command;
private String label;
private CommandSender sender;
private Map argumentsValues;
- public CommandContext(String command, String label, CommandSender sender, Map argumentsValues) {
+ public CommandContext(Object commandInstance, String command, String label, CommandSender sender, Map argumentsValues) {
+ this.commandInstance = commandInstance;
this.command = command;
this.label = label;
this.sender = sender;
this.argumentsValues = argumentsValues;
}
+ public Object getCommandInstance() {
+ return commandInstance;
+ }
+
public String getCommand() {
return command;
}
diff --git a/src/main/java/com/io/yutian/elementoriginlib/command/CommandEntity.java b/src/main/java/com/io/yutian/elementoriginlib/command/CommandEntity.java
new file mode 100644
index 0000000..93add21
--- /dev/null
+++ b/src/main/java/com/io/yutian/elementoriginlib/command/CommandEntity.java
@@ -0,0 +1,225 @@
+package com.io.yutian.elementoriginlib.command;
+
+import com.io.yutian.elementoriginlib.command.argument.Argument;
+import com.io.yutian.elementoriginlib.command.argument.ArgumentType;
+import com.io.yutian.elementoriginlib.command.interfaces.Command;
+import com.io.yutian.elementoriginlib.command.interfaces.CommandArgument;
+import com.io.yutian.elementoriginlib.command.interfaces.SubCommand;
+import com.io.yutian.elementoriginlib.exception.command.CommandRegisterException;
+import com.io.yutian.elementoriginlib.logger.Logger;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.*;
+
+public class CommandEntity {
+
+ private static final Logger LOGGER = Logger.getLogger(CommandEntity.class);
+
+ private Object instance;
+
+ private String command;
+ private String permission;
+
+ private List childrens = new ArrayList<>();
+
+ public CommandEntity(Object instance, String command, String permission, List childrens) {
+ this.instance = instance;
+ this.command = command;
+ this.permission = permission;
+ this.childrens = childrens;
+ }
+
+ public Object getInstance() {
+ return instance;
+ }
+
+ public void addChild(CommandEntry child) {
+ childrens.add(child);
+ }
+
+ public String getCommand() {
+ return command;
+ }
+
+ public String getPermission() {
+ return permission;
+ }
+
+ public List getChildrens() {
+ return childrens;
+ }
+
+ public static CommandEntity parseFromClass(Class clazz) {
+ if (clazz == null) {
+ LOGGER.warn("Class is null");
+ return null;
+ }
+ if (!clazz.isAnnotationPresent(Command.class)) {
+ LOGGER.warn("Class " + clazz.getName() + " is not annotated with @Command");
+ return null;
+ }
+
+ Object instance;
+ try {
+ instance = clazz.getConstructor(null).newInstance();
+ } catch (Exception e) {
+ LOGGER.warn("无法实例化类 " + clazz);
+ return null;
+ }
+
+ Command commandAnnotation = (Command) clazz.getAnnotation(Command.class);
+ String command = commandAnnotation.value();
+ String permission = commandAnnotation.permission();
+
+ List allEntries = new ArrayList<>();
+ Map pathToEntryMap = new HashMap<>();
+ List rootEntries = new ArrayList<>();
+
+ try {
+ for (Method method : clazz.getDeclaredMethods()) {
+ if (!method.isAnnotationPresent(SubCommand.class)) {
+ continue;
+ }
+
+ CommandEntry commandEntry = parseFromMethod(method);
+ if (commandEntry != null) {
+ allEntries.add(commandEntry);
+
+ String path = commandEntry.getFullName();
+ String parentPath = getParentPath(path);
+
+ if (pathToEntryMap.containsKey(path)) {
+ LOGGER.warn("命令路径冲突: 子命令 '" + path + "' 已经定义, 不能再定义父命令 '" + parentPath + "'");
+ throw new CommandRegisterException("命令路径冲突: 子命令 '" + path + "' 已经定义, 不能再定义父命令 '" + parentPath + "'");
+ }
+
+ if (!parentPath.isEmpty() && pathToEntryMap.containsKey(parentPath)) {
+ LOGGER.warn("命令路径冲突: 子命令 '" + path + "' 已经定义, 不能再定义父命令 '" + parentPath + "'");
+ throw new CommandRegisterException("命令路径冲突: 子命令 '" + path + "' 已经定义, 不能再定义父命令 '" + parentPath + "'");
+ }
+
+ pathToEntryMap.put(commandEntry.getFullName(), commandEntry);
+ }
+ }
+
+ for (CommandEntry entry : allEntries) {
+ String fullPath = entry.getFullName();
+ int lastDotIndex = fullPath.lastIndexOf('.');
+
+ if (lastDotIndex == -1) {
+ rootEntries.add(entry);
+ } else {
+ String parentPath = fullPath.substring(0, lastDotIndex);
+ CommandEntry parentEntry = pathToEntryMap.get(parentPath);
+
+ if (parentEntry == null) {
+ parentEntry = createParentNodes(pathToEntryMap, parentPath);
+ if (parentPath.indexOf('.') == -1) {
+ rootEntries.add(parentEntry);
+ }
+ }
+ parentEntry.getChildrens().add(entry);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+
+ return new CommandEntity(instance, command, permission, rootEntries);
+ }
+
+ private static String getParentPath(String path) {
+ int lastDotIndex = path.lastIndexOf('.');
+ if (lastDotIndex == -1) {
+ return "";
+ }
+ return path.substring(0, lastDotIndex);
+ }
+
+ private static CommandEntry createParentNodes(Map pathToEntryMap, String currentPath) {
+ if (pathToEntryMap.containsKey(currentPath)) {
+ return pathToEntryMap.get(currentPath);
+ }
+
+ int lastDotIndex = currentPath.lastIndexOf('.');
+ CommandEntry parentEntry;
+
+ if (lastDotIndex == -1) {
+ parentEntry = new CommandEntry(currentPath, currentPath);
+ } else {
+ String grandParentPath = currentPath.substring(0, lastDotIndex);
+ CommandEntry grandParentEntry = createParentNodes(pathToEntryMap, grandParentPath);
+ parentEntry = new CommandEntry(currentPath, currentPath.substring(lastDotIndex + 1));
+ grandParentEntry.getChildrens().add(parentEntry);
+ }
+ pathToEntryMap.put(currentPath, parentEntry);
+ return parentEntry;
+ }
+
+
+ private static CommandEntry parseFromMethod(Method method) {
+ SubCommand subCommand = method.getAnnotation(SubCommand.class);
+ String path = subCommand.value();
+ String permission = subCommand.permission();
+ String[] senderRequireArray = subCommand.senderRequire();
+ List senderRequireList = new ArrayList<>();
+ for (String senderRequire : senderRequireArray) {
+ SenderRequire senderRequire1 = SenderRequires.get(senderRequire);
+ if (senderRequire1 == null) {
+ LOGGER.warn("Sender require " + senderRequire + " is null");
+ continue;
+ }
+ senderRequireList.add(SenderRequires.get(senderRequire));
+ }
+
+ String subName = path;
+
+ if (path.contains(".")) {
+ int lastDotIndex = path.lastIndexOf('.');
+ if (lastDotIndex == -1 || lastDotIndex > path.length() - 1) {
+ LOGGER.warn("Invalid command name '" + path + "'");
+ return null;
+ }
+ subName = path.substring(path.lastIndexOf('.') + 1);
+ }
+ List arguments = new ArrayList<>();
+ for (Parameter parameter : method.getParameters()) {
+ if (!parameter.isAnnotationPresent(CommandArgument.class)) {
+ continue;
+ }
+ CommandArgument commandArgument = parameter.getAnnotation(CommandArgument.class);
+ String name = commandArgument.name();
+ String argumentName = name.isEmpty() ? parameter.getName() : name;
+ boolean required = commandArgument.required();
+ String suggestionType = commandArgument.suggestionType();
+ Class> type = parameter.getType();
+ ArgumentType argumentType = ArgumentType.get(parameter.getType());
+ if (argumentType == null) {
+ LOGGER.warn("Argument type " + parameter.getType().getName() + " is null");
+ continue;
+ }
+ Argument argument = new Argument(argumentName, argumentType);
+ if (!suggestionType.isEmpty()) {
+ Suggest suggest = Suggests.getSuggest(suggestionType);
+ if (suggest == null) {
+ LOGGER.warn("Suggest type " + suggestionType + " is null");
+ } else {
+ argument.suggest(suggest);
+ }
+ }
+ arguments.add(argument);
+ }
+ return new CommandEntry(path, subName, permission, senderRequireList, arguments, method);
+ }
+
+ @Override
+ public String toString() {
+ return "CommandEntity{" +
+ "command='" + command + '\'' +
+ ", permission='" + permission + '\'' +
+ ", childrens=" + childrens +
+ '}';
+ }
+}
diff --git a/src/main/java/com/io/yutian/elementoriginlib/command/CommandEntry.java b/src/main/java/com/io/yutian/elementoriginlib/command/CommandEntry.java
new file mode 100644
index 0000000..b1fef56
--- /dev/null
+++ b/src/main/java/com/io/yutian/elementoriginlib/command/CommandEntry.java
@@ -0,0 +1,227 @@
+package com.io.yutian.elementoriginlib.command;
+
+import com.io.yutian.elementoriginlib.command.argument.Argument;
+import com.io.yutian.elementoriginlib.command.argument.ArgumentValue;
+import com.io.yutian.elementoriginlib.command.interfaces.CommandArgument;
+import com.io.yutian.elementoriginlib.logger.Logger;
+import org.bukkit.command.CommandSender;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.ArrayList;
+import java.util.List;
+
+public class CommandEntry {
+
+ private static final Logger LOGGER = Logger.getLogger(CommandEntry.class);
+
+ private String fullName;
+ private String name;
+ private String permission;
+ private List senderRequires = new ArrayList<>();
+
+ private List arguments = new ArrayList<>();
+
+ private List childrens = new ArrayList<>();
+
+ private long depth = 0;
+
+ private final Method method;
+ private final MethodHandle methodHandle;
+
+ private Class>[] parameterTypes;
+
+ public CommandEntry(String fullName, String name, String permission, List senderRequires, List arguments, Method method) {
+ this.fullName = fullName;
+ this.name = name;
+ this.permission = permission;
+ this.senderRequires = senderRequires;
+ this.arguments = arguments;
+ this.method = method;
+ try {
+ this.methodHandle = MethodHandles.lookup().unreflect(this.method);
+ this.parameterTypes = methodHandle.type().parameterArray();
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ this.depth = fullName.chars().filter(ch -> ch == '.').count();
+ }
+
+ public CommandEntry(String fullName, String name) {
+ this.fullName = fullName;
+ this.name = name;
+ this.method = null;
+ this.methodHandle = null;
+ this.parameterTypes = new Class>[0];
+ }
+
+ public void invoke(CommandContext commandContext) {
+ if (method == null || methodHandle == null) {
+ return;
+ }
+
+ Object targetInstance = commandContext.getCommandInstance();
+ if (targetInstance == null) {
+ LOGGER.warn("该命令的实例为空,无法执行命令: " + fullName);
+ return;
+ }
+
+ try {
+ Class>[] parameterTypes = method.getParameterTypes();
+ Object[] parameters = new Object[parameterTypes.length];
+
+ int argumentIndex = 0;
+
+ for (int i = 0; i < parameterTypes.length; i++) {
+ Parameter parameter = method.getParameters()[i];
+ if (parameter.isAnnotationPresent(CommandArgument.class)) {
+ String paramName = arguments.get(argumentIndex).getName();
+ ArgumentValue argumentValue = commandContext.getArgumentsValue(paramName);
+ if (argumentValue != null) {
+ parameters[i] = argumentValue.getValue();
+ } else {
+ parameters[i] = null;
+ }
+ argumentIndex++;
+ } else if (parameter.getType() == CommandContext.class) {
+ parameters[i] = commandContext;
+ } else {
+ parameters[i] = getDefaultForType(parameterTypes[i]);
+ }
+ }
+
+ Object[] parms = new Object[parameters.length+1];
+ parms[0] = targetInstance;
+ System.arraycopy(parameters, 0, parms, 1, parameters.length);
+ methodHandle.invokeWithArguments(parms);
+ } catch (Exception e) {
+ e.printStackTrace();
+ LOGGER.error("执行命令时出现异常: " + fullName);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ LOGGER.error("执行命令时出现异常: " + fullName);
+ }
+ }
+
+ public boolean canInvoke(CommandSender sender) {
+ if (senderRequires != null && senderRequires.size() > 0) {
+ for (SenderRequire senderRequire : senderRequires) {
+ if (senderRequire.test(sender)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ return true;
+ }
+
+ public boolean hasPermission(CommandSender sender) {
+ if (permission != null && !permission.isEmpty()) {
+ return sender.isOp() || sender.hasPermission(permission);
+ }
+ return true;
+ }
+
+ private Object[] convertToPrimitive(Object[] parameters) {
+ Object[] convertedParams = new Object[parameters.length];
+ for (int i = 0; i < parameters.length; i++) {
+ Object param = parameters[i];
+ Class> parameterType = parameterTypes[i+1];
+ if (parameterType.isPrimitive()) {
+ if (param instanceof Integer) {
+ convertedParams[i] = ((Integer) param).intValue();
+ } else if (param instanceof Double) {
+ convertedParams[i] = ((Double) param).doubleValue();
+ } else if (param instanceof Boolean) {
+ convertedParams[i] = ((Boolean) param).booleanValue();
+ } else if (param instanceof Character) {
+ convertedParams[i] = ((Character) param).charValue();
+ } else if (param instanceof Byte) {
+ convertedParams[i] = ((Byte) param).byteValue();
+ } else if (param instanceof Short) {
+ convertedParams[i] = ((Short) param).shortValue();
+ } else if (param instanceof Long) {
+ convertedParams[i] = ((Long) param).longValue();
+ } else if (param instanceof Float) {
+ convertedParams[i] = ((Float) param).floatValue();
+ } else {
+ convertedParams[i] = param;
+ }
+ }
+ }
+ return convertedParams;
+ }
+
+ private Object getDefaultForType(Class> parameterType) {
+ if (parameterType.isPrimitive()) {
+ if (parameterType == int.class) {
+ return 0;
+ } else if (parameterType == double.class) {
+ return 0.0;
+ } else if (parameterType == boolean.class) {
+ return false;
+ } else if (parameterType == char.class) {
+ return '\u0000';
+ } else if (parameterType == byte.class) {
+ return (byte) 0;
+ } else if (parameterType == short.class) {
+ return (short) 0;
+ } else if (parameterType == long.class) {
+ return 0L;
+ } else if (parameterType == float.class) {
+ return 0.0f;
+ }
+ }
+ return null;
+ }
+
+ public boolean isEmptyEntry() {
+ return method == null;
+ }
+
+ public void addChild(CommandEntry child) {
+ childrens.add(child);
+ }
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getPermission() {
+ return permission;
+ }
+
+ public List getSenderRequires() {
+ return senderRequires;
+ }
+
+ public List getArguments() {
+ return arguments;
+ }
+
+ public List getChildrens() {
+ return childrens;
+ }
+
+ public long getDepth() {
+ return depth;
+ }
+
+ @Override
+ public String toString() {
+ return "CommandEntry{" +
+ "fullName='" + fullName + '\'' +
+ ", name='" + name + '\'' +
+ ", permission='" + permission + '\'' +
+ ", arguments=" + arguments +
+ ", childrens=" + childrens +
+ '}';
+ }
+
+}
diff --git a/src/main/java/com/io/yutian/elementoriginlib/command/CommandNode.java b/src/main/java/com/io/yutian/elementoriginlib/command/CommandNode.java
deleted file mode 100644
index 87c1d38..0000000
--- a/src/main/java/com/io/yutian/elementoriginlib/command/CommandNode.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package com.io.yutian.elementoriginlib.command;
-
-import com.io.yutian.elementoriginlib.command.argument.Argument;
-import org.bukkit.command.CommandSender;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.function.Predicate;
-
-public class CommandNode {
-
- private String name;
-
- private List childrens = new ArrayList<>();
- private List arguments = new ArrayList<>();
-
- private List alias = new ArrayList<>();
-
- private Predicate commandSenderPredicate = (commandSender -> true);
- private Command command;
-
- public CommandNode(String name) {
- this.name = name;
- }
-
- public CommandNode(String name, String[] alias) {
- this.name = name;
- this.alias = Arrays.asList(alias);
- }
-
- public CommandNode(String name, List alias) {
- this.name = name;
- this.alias = alias;
- }
-
- public CommandNode permission(Predicate commandSenderPredicate) {
- this.commandSenderPredicate = commandSenderPredicate;
- return this;
- }
-
- public List getAlias() {
- return alias;
- }
-
- public CommandNode setAlias(List alias) {
- this.alias = alias;
- return this;
- }
-
- public CommandNode addAilas(String alias) {
- this.alias.add(alias);
- return this;
- }
-
- public CommandNode addArgument(Argument argument) {
- arguments.add(argument);
- return this;
- }
-
- public CommandNode addChildren(CommandNode commandNode) {
- this.childrens.add(commandNode);
- return this;
- }
-
- public List getChildrens() {
- return childrens;
- }
-
- public List getArguments() {
- return arguments;
- }
-
- public CommandNode executes(Command command) {
- this.command = command;
- return this;
- }
-
- public Command getCommand() {
- return command;
- }
-
- public String getName() {
- return name;
- }
-
- public static CommandNode node(String name) {
- return new CommandNode(name);
- }
-
-}
diff --git a/src/main/java/com/io/yutian/elementoriginlib/command/IAlias.java b/src/main/java/com/io/yutian/elementoriginlib/command/IAlias.java
deleted file mode 100644
index 4f8fe79..0000000
--- a/src/main/java/com/io/yutian/elementoriginlib/command/IAlias.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.io.yutian.elementoriginlib.command;
-
-public interface IAlias {
-
- String[] getAlias();
-
-}
diff --git a/src/main/java/com/io/yutian/elementoriginlib/command/ICommand.java b/src/main/java/com/io/yutian/elementoriginlib/command/ICommand.java
deleted file mode 100644
index e5e914c..0000000
--- a/src/main/java/com/io/yutian/elementoriginlib/command/ICommand.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.io.yutian.elementoriginlib.command;
-
-import com.io.yutian.elementoriginlib.command.argument.Argument;
-import org.bukkit.command.CommandSender;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public abstract class ICommand {
-
- private String name;
- private String description;
-
- private List commandNodes = new ArrayList<>();
- private List arguments = new ArrayList<>();
-
- public ICommand(String name) {
- this(name, null);
- }
-
- public ICommand(String name, String description) {
- this.name = name;
- this.description = description;
- }
-
- public void executes(CommandContext commandContext) {
- }
-
- public boolean emptyExecutes(CommandSender commandSender) {
- return false;
- }
-
- public boolean hasPermission(CommandSender sender) {
- return sender.isOp() || sender.hasPermission(getPermissionPrefix()+"."+name);
- }
-
- public String getPermissionPrefix() {
- return "command."+name;
- }
-
- public ICommand addArgument(Argument argument) {
- arguments.add(argument);
- return this;
- }
-
- public ICommand addCommandNode(CommandNode commandNode) {
- this.commandNodes.add(commandNode);
- return this;
- }
-
- public List getCommandNodes() {
- return commandNodes;
- }
-
- public List getArguments() {
- return arguments;
- }
-
- public String getName() {
- return name;
- }
-
- public String getDescription() {
- return description;
- }
-
-}
diff --git a/src/main/java/com/io/yutian/elementoriginlib/command/ICommandManager.java b/src/main/java/com/io/yutian/elementoriginlib/command/ICommandManager.java
index 9b7c580..86bf773 100644
--- a/src/main/java/com/io/yutian/elementoriginlib/command/ICommandManager.java
+++ b/src/main/java/com/io/yutian/elementoriginlib/command/ICommandManager.java
@@ -6,6 +6,6 @@ public interface ICommandManager {
String getName();
- List getCommands();
+ List getCommands();
}
diff --git a/src/main/java/com/io/yutian/elementoriginlib/command/SenderRequire.java b/src/main/java/com/io/yutian/elementoriginlib/command/SenderRequire.java
new file mode 100644
index 0000000..9e1fcf5
--- /dev/null
+++ b/src/main/java/com/io/yutian/elementoriginlib/command/SenderRequire.java
@@ -0,0 +1,10 @@
+package com.io.yutian.elementoriginlib.command;
+
+import org.bukkit.command.CommandSender;
+
+@FunctionalInterface
+public interface SenderRequire {
+
+ boolean test(CommandSender sender);
+
+}
diff --git a/src/main/java/com/io/yutian/elementoriginlib/command/SenderRequires.java b/src/main/java/com/io/yutian/elementoriginlib/command/SenderRequires.java
new file mode 100644
index 0000000..83d7316
--- /dev/null
+++ b/src/main/java/com/io/yutian/elementoriginlib/command/SenderRequires.java
@@ -0,0 +1,29 @@
+package com.io.yutian.elementoriginlib.command;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class SenderRequires {
+
+ public static final SenderRequire CONSOLE = (sender) -> sender instanceof org.bukkit.command.ConsoleCommandSender;
+
+ public static final SenderRequire PLAYER = (sender) -> sender instanceof org.bukkit.entity.Player;
+
+ private static Map requireMap = new HashMap<>();
+
+ public static void register(String name, SenderRequire require) {
+ requireMap.put(name, require);
+ }
+
+ public static SenderRequire get(String name) {
+ return requireMap.get(name);
+ }
+
+ static {
+
+ register("console", CONSOLE);
+ register("player", PLAYER);
+
+ }
+
+}
diff --git a/src/main/java/com/io/yutian/elementoriginlib/command/SimpleCommandHandler.java b/src/main/java/com/io/yutian/elementoriginlib/command/SimpleCommandHandler.java
deleted file mode 100644
index 3a90352..0000000
--- a/src/main/java/com/io/yutian/elementoriginlib/command/SimpleCommandHandler.java
+++ /dev/null
@@ -1,295 +0,0 @@
-package com.io.yutian.elementoriginlib.command;
-
-import com.io.yutian.elementoriginlib.command.argument.Argument;
-import com.io.yutian.elementoriginlib.command.argument.ArgumentValue;
-import com.io.yutian.elementoriginlib.command.handler.CommandHandler;
-import com.io.yutian.elementoriginlib.lang.Lang;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandSender;
-
-import java.util.*;
-import java.util.stream.Stream;
-
-public class SimpleCommandHandler extends Command {
-
- private ICommand iCommand;
-
- public SimpleCommandHandler(String name, ICommand iCommand) {
- super(name);
- this.iCommand = iCommand;
- }
-
- @Override
- public boolean execute(CommandSender sender, String commandLabel, String[] args) {
- executes(sender, commandLabel, args);
- return true;
- }
-
- public void executes(CommandSender sender, String commandLabel, String[] args) {
- if (!iCommand.hasPermission(sender)) {
- sender.sendMessage(Lang.get("command-no-permission"));
- return;
- }
- List commandNodes = iCommand.getCommandNodes();
- StringBuilder stringBuilder = new StringBuilder();
- for (int i = 0; i < args.length; i++) {
- stringBuilder.append(args[i]);
- if (i < args.length - 1) {
- stringBuilder.append(" ");
- }
- }
- String commandString = stringBuilder.toString();
- if (commandNodes.size() == 0) {
- Map map = new HashMap<>();
- if (iCommand.getArguments().size() > 0) {
- int argSize = args.length;
- List arguments = iCommand.getArguments();
- int k = 0;
- if (arguments.get(arguments.size()-1).isOptional()) {
- k++;
- }
- if (argSize < arguments.size()-k) {
- sender.sendMessage(Lang.get("command-short-arg"));
- return;
- }
- for (int l = 0; l < arguments.size(); l++) {
- Argument a = arguments.get(l);
- int index = l;
- if (index >= args.length) {
- break;
- }
- String arg = args[index];
- if (!a.getArgumentsType().test(arg)) {
- sender.sendMessage(Lang.get("command-unknown-arg", index+1, arg));
- return;
- }
- }
- map = parseArgumentValue(sender, arguments, args, -1);
- }
- iCommand.executes(new CommandContext(commandString, commandLabel, sender, map));
- return;
- }
-
- int nodeSize = args.length;
-
- if (commandNodes.size() > 0 && nodeSize == 0) {
- if (!iCommand.emptyExecutes(sender)) {
- sender.sendMessage(Lang.get("command-short-arg"));
- }
- return;
- }
-
- String mainNode = args[0];
-
- Stream nodeStream = commandNodes.stream().filter((n) -> {
- return n.getName().equalsIgnoreCase(mainNode) || n.getAlias().contains(mainNode);
- });
- Optional nodeOptional = nodeStream.findFirst();
- if (!nodeOptional.isPresent()) {
- sender.sendMessage(Lang.get("command-unknown-arg", 1, mainNode));
- return;
- }
- CommandNode node = nodeOptional.get();
-
- if (node.getChildrens().size() > 0) {
- checkClidren(commandString, commandLabel, sender, 0, args, node);
- } else {
- if (node.getCommand() != null) {
- Map map = new HashMap<>();
- if (node.getArguments().size() > 0) {
- int argSize = args.length - 1;
- List arguments = node.getArguments();
- int k = 0;
- if (arguments.get(arguments.size()-1).isOptional()) {
- k++;
- }
- if (argSize < arguments.size()-k) {
- sender.sendMessage(Lang.get("command-short-arg"));
- return;
- }
- for (int l = 0; l < arguments.size(); l++) {
- Argument a = arguments.get(l);
- int index = l + 1;
- if (index >= args.length) {
- break;
- }
- String arg = args[index];
- if (!a.getArgumentsType().test(arg)) {
- sender.sendMessage(Lang.get("command-error-arg", index+1, arg));
- return;
- }
- }
- map = parseArgumentValue(sender, node.getArguments(), args, 0);
- }
- node.getCommand().run(new CommandContext(commandString, commandLabel, sender, map));
- } else {
- sender.sendMessage(Lang.get("command-unknown-arg", 2, mainNode));
- return;
- }
- }
-
- }
-
- private void checkClidren(String commandString, String commandLabel, CommandSender sender, int i, String[] args, CommandNode node) {
- i++;
- if (i >= args.length) {
- if (node.getCommand() == null) {
- sender.sendMessage(Lang.get("command-short-arg"));
- } else {
- node.getCommand().run(new CommandContext(commandString, commandLabel, sender, new HashMap<>()));
- }
- return;
- }
- String s = args[i];
- Stream nodeStream = node.getChildrens().stream().filter((n) -> {
- return n.getName().equalsIgnoreCase(s) || n.getAlias().contains(s);
- });
- Optional nodeOptional = nodeStream.findFirst();
- if (!nodeOptional.isPresent()) {
- sender.sendMessage(Lang.get("command-unknown-arg", i+1, s));
- return;
- }
- CommandNode node1 = nodeOptional.get();
-
- if (node1.getChildrens().size() > 0) {
- checkClidren(commandString, commandLabel, sender, i, args, node1);
- } else {
- if (node1.getCommand() != null) {
- Map map = new HashMap<>();
- if (node1.getArguments().size() > 0) {
- int argSize = args.length - i - 1;
- List arguments = node1.getArguments();
- int k = 0;
- if (arguments.get(arguments.size()-1).isOptional()) {
- k++;
- }
- if (argSize < arguments.size()-k) {
- sender.sendMessage(Lang.get("command-short-arg"));
- return;
- }
- for (int l = 0; l < arguments.size(); l++) {
- Argument a = arguments.get(l);
- int index = i + l + 1;
- if (index >= args.length) {
- break;
- }
- String arg = args[index];
- if (!a.getArgumentsType().test(arg)) {
- sender.sendMessage(Lang.get("command-unknown-arg", index+1, arg));
- return;
- }
- }
- map = parseArgumentValue(sender, node1.getArguments(), args, i);
- }
- node1.getCommand().run(new CommandContext(commandString, commandLabel, sender, map));
- } else {
- sender.sendMessage(Lang.get("command-unknown-arg", i+1, s));
- return;
- }
- }
-
- }
-
- private Map parseArgumentValue(CommandSender commandSender, List argumentList, String[] args, int i) {
- Map map = new HashMap<>();
- List arguments = argumentList;
- for (int l = 0; l < arguments.size(); l++) {
- Argument a = arguments.get(l);
- if (i+1+l >= args.length) {
- if (a.isOptional()) {
- map.put(a.getName(), new ArgumentValue(a.getDefaultValue()));
- }
- return map;
- }
- String arg = args[i+1+l];
- if (!a.getArgumentsType().test(arg)) {
- continue;
- }
- ArgumentValue argumentValue = new ArgumentValue(a.getArgumentsType().get(arg));
- map.put(a.getName(), argumentValue);
- }
- return map;
- }
-
- @Override
- public List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException {
- return onTabComplete(sender, alias, args);
- }
-
- public List onTabComplete(CommandSender sender, String alias, String[] args) {
- List list = new ArrayList<>();
- int index = args.length;
- String arg = args[index-1];
- if (!iCommand.hasPermission(sender)) {
- return list;
- }
- if (iCommand instanceof ITabCompleter) {
- ITabCompleter tabCompleter = (ITabCompleter) iCommand;
- return tabCompleter.onTabComplete(sender, args, index-1, arg);
- } else {
- Map> map = new HashMap<>();
- if (iCommand.getCommandNodes().size() > 0) {
- List list1 = new ArrayList<>();
- for (CommandNode node : iCommand.getCommandNodes()) {
- list1.add(node.getName());
- list1.addAll(node.getAlias());
- if (index >= 2) {
- if (!node.getName().equalsIgnoreCase(args[0])) {
- continue;
- }
- }
- if (node.getChildrens().size() > 0) {
- getTabComplete(node, 1, map);
- } else if (node.getArguments().size() > 0) {
- List arguments = node.getArguments();
- for (int l = 0; l < arguments.size(); l++) {
- Argument argument = arguments.get(l);
- if (argument.getSuggest() != null) {
- map.put(2+l, argument.getSuggest().getSuggest());
- continue;
- }
- map.put(2+l, Arrays.asList("<"+argument.getName()+">"));
- }
- }
- }
- map.put(1, list1);
- return CommandHandler.preseSuggest(map.getOrDefault(index, list), arg);
- } else if (iCommand.getArguments().size() > 0) {
- List arguments = iCommand.getArguments();
- for (int l = 0; l < arguments.size(); l++) {
- Argument argument = arguments.get(l);
- if (argument.getSuggest() != null) {
- map.put(0+l+1, argument.getSuggest().getSuggest());
- continue;
- }
- map.put(0+l+1, Arrays.asList("<"+argument.getName()+">"));
- }
- return CommandHandler.preseSuggest(map.getOrDefault(index, list), arg);
- }
- }
- return CommandHandler.preseSuggest(list, arg);
- }
-
- private void getTabComplete(CommandNode node, int i, Map> map) {
- i++;
- List list = map.getOrDefault(i, new ArrayList<>());
- for (CommandNode c : node.getChildrens()) {
- list.add(c.getName());
- if (c.getChildrens().size() > 0) {
- getTabComplete(c, i, map);
- } else if (c.getArguments().size() > 0) {
- List arguments = c.getArguments();
- for (int l = 0; l < arguments.size(); l++) {
- Argument argument = arguments.get(l);
- if (argument.getSuggest() != null) {
- map.put(i+l+1, argument.getSuggest().getSuggest());
- continue;
- }
- map.put(i+l+1, Arrays.asList("<"+argument.getName()+">"));
- }
- }
- }
- map.put(i, list);
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/com/io/yutian/elementoriginlib/command/SimpleCommandManager.java b/src/main/java/com/io/yutian/elementoriginlib/command/SimpleCommandManager.java
index 6113962..4c2d83e 100644
--- a/src/main/java/com/io/yutian/elementoriginlib/command/SimpleCommandManager.java
+++ b/src/main/java/com/io/yutian/elementoriginlib/command/SimpleCommandManager.java
@@ -1,7 +1,6 @@
package com.io.yutian.elementoriginlib.command;
import com.io.yutian.elementoriginlib.command.handler.CommandHandler;
-import com.io.yutian.elementoriginlib.command.list.CommandHelp;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandMap;
@@ -23,65 +22,46 @@ public class SimpleCommandManager implements ICommandManager {
private final String name;
@NotNull
- private List commands;
+ private List> commandClasses = new ArrayList<>();
+ @NotNull
+ private List commands = new ArrayList<>();
public SimpleCommandManager(Plugin plugin, String name) {
this(plugin, name, new ArrayList<>());
}
- public SimpleCommandManager(Plugin plugin, String name, @NotNull List commands) {
+ public SimpleCommandManager(Plugin plugin, String name, @NotNull List> commandClasses) {
this.plugin = plugin;
this.name = name;
- this.commands = commands;
- register(new CommandHelp(this));
+ this.commandClasses = commandClasses;
}
- public void register(@NotNull ICommand command) {
+ public void register(@NotNull Class> commandClass) {
+ if (commandClass == null) {
+ return;
+ }
+ CommandEntity command = CommandEntity.parseFromClass(commandClass);
if (command == null) {
return;
}
+ commandClasses.add(commandClass);
commands.add(command);
- if (command instanceof IAlias alias) {
- String[] array = alias.getAlias();
- for (String s : array) {
- registerPluginBukkitCommand(plugin, s, command);
- }
- }
}
public void unregisterAll() {
- for (ICommand command : commands) {
- if (command instanceof IAlias) {
- unregister(command);
- }
- }
+ commands.clear();
}
- public static void unregister(ICommand command) {
- if (!(command instanceof IAlias)) {
+ public void unregister(Class> commandClass) {
+ if (commandClass == null) {
return;
}
- try {
- Map map = (Map) commandMap.getClass().getMethod("getKnownCommands").invoke(commandMap);
- for (String name : ((IAlias) command).getAlias()) {
- map.remove(name);
- Command bukkitCommand = bukkitCommandMap.get(name);
- bukkitCommand.unregister(commandMap);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
+ commands.remove(commandClass);
}
- public void registerPluginCommand(@NotNull Plugin plugin, String commandName) {
- Bukkit.getPluginCommand(commandName).setExecutor(new CommandHandler(plugin, this));
- }
-
- protected static void registerPluginBukkitCommand(Plugin plugin, String name, ICommand command) {
- SimpleCommandHandler simpleCommandHandler = new SimpleCommandHandler(name, command);
- bukkitCommandMap.put(name, simpleCommandHandler);
- commandMap.register(plugin.getName(), simpleCommandHandler);
+ public void registerPluginCommand(@NotNull String commandName) {
+ Bukkit.getPluginCommand(commandName).setExecutor(new CommandHandler(this));
}
public Plugin getPlugin() {
@@ -96,7 +76,7 @@ public class SimpleCommandManager implements ICommandManager {
@NotNull
@Override
- public List getCommands() {
+ public List getCommands() {
return commands;
}
diff --git a/src/main/java/com/io/yutian/elementoriginlib/command/Suggests.java b/src/main/java/com/io/yutian/elementoriginlib/command/Suggests.java
index eb23c09..743dc35 100644
--- a/src/main/java/com/io/yutian/elementoriginlib/command/Suggests.java
+++ b/src/main/java/com/io/yutian/elementoriginlib/command/Suggests.java
@@ -4,8 +4,10 @@ import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Player;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
public class Suggests {
@@ -25,4 +27,25 @@ public class Suggests {
return list;
};
+ private static final Map suggests = new HashMap<>();
+
+ public static void registerSuggest(String name, Suggest suggest) {
+ suggests.put(name, suggest);
+ }
+
+ public static Suggest getSuggest(String name) {
+ return suggests.get(name);
+ }
+
+ public static void unregisterSuggest(String name) {
+ suggests.remove(name);
+ }
+
+ static {
+
+ registerSuggest("world_list", WORLD_LIST);
+ registerSuggest("player_list", PLAYER_LIST);
+
+ }
+
}
diff --git a/src/main/java/com/io/yutian/elementoriginlib/command/argument/Argument.java b/src/main/java/com/io/yutian/elementoriginlib/command/argument/Argument.java
index 94f0f5f..4c3ba1e 100644
--- a/src/main/java/com/io/yutian/elementoriginlib/command/argument/Argument.java
+++ b/src/main/java/com/io/yutian/elementoriginlib/command/argument/Argument.java
@@ -49,8 +49,4 @@ public class Argument {
return suggest;
}
- public static Argument argument(String name, ArgumentType type) {
- return new Argument(name, type);
- }
-
}
diff --git a/src/main/java/com/io/yutian/elementoriginlib/command/argument/ArgumentNode.java b/src/main/java/com/io/yutian/elementoriginlib/command/argument/ArgumentNode.java
new file mode 100644
index 0000000..3446a47
--- /dev/null
+++ b/src/main/java/com/io/yutian/elementoriginlib/command/argument/ArgumentNode.java
@@ -0,0 +1,12 @@
+package com.io.yutian.elementoriginlib.command.argument;
+
+public class ArgumentNode extends Argument {
+
+ private static final ArgumentType