From 1148cdbb2e928d776121a301774a390054d6bac8 Mon Sep 17 00:00:00 2001 From: YuTian <2953516620@qq.com> Date: Tue, 23 Jul 2024 16:22:37 +0800 Subject: [PATCH] v2.6 --- .../com/io/yutian/aulib/command/IAlias.java | 4 - .../aulib/command/SimpleCommandHandler.java | 295 ++++++++++++++++++ .../aulib/command/SimpleCommandManager.java | 72 ++++- .../aulib/redis/RedisCacheSyncTimer.java | 2 +- src/main/resources/plugin.yml | 2 +- 5 files changed, 365 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/io/yutian/aulib/command/SimpleCommandHandler.java diff --git a/src/main/java/com/io/yutian/aulib/command/IAlias.java b/src/main/java/com/io/yutian/aulib/command/IAlias.java index 82a2a45..56126d3 100644 --- a/src/main/java/com/io/yutian/aulib/command/IAlias.java +++ b/src/main/java/com/io/yutian/aulib/command/IAlias.java @@ -2,10 +2,6 @@ package com.io.yutian.aulib.command; public interface IAlias { - default boolean inMainCommand() { - return true; - } - String[] getAlias(); } diff --git a/src/main/java/com/io/yutian/aulib/command/SimpleCommandHandler.java b/src/main/java/com/io/yutian/aulib/command/SimpleCommandHandler.java new file mode 100644 index 0000000..9b6f3d0 --- /dev/null +++ b/src/main/java/com/io/yutian/aulib/command/SimpleCommandHandler.java @@ -0,0 +1,295 @@ +package com.io.yutian.aulib.command; + +import com.io.yutian.aulib.command.argument.Argument; +import com.io.yutian.aulib.command.argument.ArgumentValue; +import com.io.yutian.aulib.command.handler.CommandHandler; +import com.io.yutian.aulib.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/aulib/command/SimpleCommandManager.java b/src/main/java/com/io/yutian/aulib/command/SimpleCommandManager.java index 914c3a0..93d04d6 100644 --- a/src/main/java/com/io/yutian/aulib/command/SimpleCommandManager.java +++ b/src/main/java/com/io/yutian/aulib/command/SimpleCommandManager.java @@ -3,24 +3,35 @@ package com.io.yutian.aulib.command; import com.io.yutian.aulib.command.handler.CommandHandler; import com.io.yutian.aulib.command.list.CommandHelp; import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandMap; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; +import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; public class SimpleCommandManager implements ICommandManager { + protected static Map bukkitCommandMap = new HashMap<>(); + protected static CommandMap commandMap; + + private final Plugin plugin; private final String name; @NotNull private List commands; - public SimpleCommandManager(String name) { - this(name, new ArrayList<>()); + + public SimpleCommandManager(Plugin plugin, String name) { + this(plugin, name, new ArrayList<>()); } - public SimpleCommandManager(String name, @NotNull List commands) { + public SimpleCommandManager(Plugin plugin, String name, @NotNull List commands) { + this.plugin = plugin; this.name = name; this.commands = commands; register(new CommandHelp(this)); @@ -31,12 +42,52 @@ public class SimpleCommandManager implements ICommandManager { return; } commands.add(command); + if (command instanceof IAlias alias) { + String[] array = alias.getAlias(); + for (String s : array) { + registerPluginBukkitCommand(plugin, s, command); + } + } } - public void registerBukkitCommand(@NotNull Plugin plugin, String commandName) { + public void unregisterAll() { + for (ICommand command : commands) { + if (command instanceof IAlias) { + unregister(command); + } + } + } + + public static void unregister(ICommand command) { + if (!(command instanceof IAlias)) { + 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(); + } + } + + 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 Plugin getPlugin() { + return plugin; + } + @NotNull @Override public String getName() { @@ -49,4 +100,17 @@ public class SimpleCommandManager implements ICommandManager { return commands; } + static { + try { + Class c = Bukkit.getServer().getClass(); + for (Method method : c.getDeclaredMethods()) { + if (method.getName().equals("getCommandMap")) { + commandMap = (CommandMap) method.invoke(Bukkit.getServer(), new Object[0]); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } diff --git a/src/main/java/com/io/yutian/aulib/redis/RedisCacheSyncTimer.java b/src/main/java/com/io/yutian/aulib/redis/RedisCacheSyncTimer.java index a7e1d60..eb2e5e0 100644 --- a/src/main/java/com/io/yutian/aulib/redis/RedisCacheSyncTimer.java +++ b/src/main/java/com/io/yutian/aulib/redis/RedisCacheSyncTimer.java @@ -33,7 +33,7 @@ public class RedisCacheSyncTimer { PluginInfo pluginInfo = entry.getValue(); String lockKey = LOCK_KEY + "_" + plugin.getName(); IJedisGetter jedisGetter = pluginInfo.getJedisGetter(); - try (Jedis jedis = jedisGetter.getRedis()) { + try (Jedis jedis = jedisGetter.getRedis()) {ยท long lockResult = jedis.setnx(lockKey, "locked"); if (lockResult != 1) { continue; diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 7e89db6..e494cb6 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: AuLib main: com.io.yutian.aulib.AuLib -version: 2.5.2 +version: 2.6 api-version: 1.18 author: SuperYuTian \ No newline at end of file