From 5fa255d7c7a97ca39403b114deb7d6e90612e51f Mon Sep 17 00:00:00 2001 From: CarmJos Date: Mon, 23 May 2022 00:10:34 +0800 Subject: [PATCH] =?UTF-8?q?feat(command):=20=E6=96=B0=E5=A2=9E=E5=BF=AB?= =?UTF-8?q?=E6=8D=B7=E5=AD=90=E6=8C=87=E4=BB=A4=E5=88=B6=E4=BD=9C=E7=9A=84?= =?UTF-8?q?=E7=9B=B8=E5=85=B3API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增指令相关API,便于快速制作指令与子指令。 --- README.md | 2 +- base/command/pom.xml | 20 +++ .../easyplugin/command/CommandHandler.java | 136 ++++++++++++++++++ .../lib/easyplugin/command/NamedExecutor.java | 20 +++ .../easyplugin/command/SimpleCompleter.java | 93 ++++++++++++ .../lib/easyplugin/command/SubCommand.java | 28 ++++ base/gui/pom.xml | 2 +- base/main/pom.xml | 2 +- collection/all/pom.xml | 2 +- collection/bom/pom.xml | 2 +- collection/common/pom.xml | 2 +- extension/papi/pom.xml | 2 +- extension/vault/pom.xml | 2 +- pom.xml | 3 +- 14 files changed, 307 insertions(+), 9 deletions(-) create mode 100644 base/command/pom.xml create mode 100644 base/command/src/main/java/cc/carm/lib/easyplugin/command/CommandHandler.java create mode 100644 base/command/src/main/java/cc/carm/lib/easyplugin/command/NamedExecutor.java create mode 100644 base/command/src/main/java/cc/carm/lib/easyplugin/command/SimpleCompleter.java create mode 100644 base/command/src/main/java/cc/carm/lib/easyplugin/command/SubCommand.java diff --git a/README.md b/README.md index 536a004..ad5ea1c 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ ### 主要部分 (`/base`) - Main [`easyplugin-main`](base/main) -- ~~Command*~~ (已独立项目到 [**MineCommands**](https://github.com/CarmJos/MineCommands)) +- Command [`easyplugin-command`](base/command) - ~~Messages*~~ (已独立项目到 [**EasyMessages**](https://github.com/CarmJos/EasyMessages)) - ~~Configuration~~ (已独立项目到 [**MineConfiguration**](https://github.com/CarmJos/MineConfiguration)) - ~~Database~~ (已独立项目到 [**EasySQL**](https://github.com/CarmJos/EasySQL)) diff --git a/base/command/pom.xml b/base/command/pom.xml new file mode 100644 index 0000000..5ad877a --- /dev/null +++ b/base/command/pom.xml @@ -0,0 +1,20 @@ + + + + easyplugin-parent + cc.carm.lib + 1.4.1 + ../../pom.xml + + 4.0.0 + + easyplugin-command + + + 8 + 8 + + + \ No newline at end of file diff --git a/base/command/src/main/java/cc/carm/lib/easyplugin/command/CommandHandler.java b/base/command/src/main/java/cc/carm/lib/easyplugin/command/CommandHandler.java new file mode 100644 index 0000000..e2d4968 --- /dev/null +++ b/base/command/src/main/java/cc/carm/lib/easyplugin/command/CommandHandler.java @@ -0,0 +1,136 @@ + +package cc.carm.lib.easyplugin.command; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.util.StringUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.*; +import java.util.stream.Collectors; + +public abstract class CommandHandler implements TabExecutor, NamedExecutor { + + protected final @NotNull JavaPlugin plugin; + protected final @NotNull String cmd; + + protected final @NotNull Map registeredCommands = new HashMap<>(); + protected final @NotNull Map registeredHandlers = new HashMap<>(); + + public CommandHandler(@NotNull JavaPlugin plugin) { + this(plugin, plugin.getName()); + } + + public CommandHandler(@NotNull JavaPlugin plugin, @NotNull String cmd) { + this.plugin = plugin; + this.cmd = cmd; + } + + public abstract void noArgs(CommandSender sender); + + public abstract void unknownCommand(CommandSender sender, String[] args); + + public abstract void noPermission(CommandSender sender); + + @Override + public String getName() { + return this.cmd; + } + + public void registerSubCommand(SubCommand command) { + for (String alias : command.getAliases()) { + if (this.registeredCommands.containsKey(alias)) { + this.plugin.getLogger().warning("Conflicting command aliases '" + alias + "' for '" + command.getName() + "', overwriting."); + } + this.registeredCommands.put(alias, command); + } + } + + public void registerHandler(CommandHandler handler) { + for (String alias : handler.getAliases()) { + if (this.registeredCommands.containsKey(alias)) { + this.plugin.getLogger().warning("Conflicting command aliases '" + alias + "' for '" + handler.getName() + "', overwriting."); + } + this.registeredHandlers.put(alias, handler); + } + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (args.length == 0) { + this.noArgs(sender); + } else { + String sub = args[0].toLowerCase(); + CommandHandler handler = this.registeredHandlers.get(sub); + if (handler != null) { + if (!handler.hasPermission(sender)) { + this.noPermission(sender); + } else { + handler.onCommand(sender, command, label, this.shortenArgs(args)); + } + } else { + SubCommand subCommand = this.registeredCommands.get(sub); + if (subCommand == null) { + this.unknownCommand(sender, args); + } else if (!subCommand.hasPermission(sender)) { + this.noPermission(sender); + } else { + try { + subCommand.execute(this.plugin, sender, this.shortenArgs(args)); + } catch (ArrayIndexOutOfBoundsException var9) { + this.unknownCommand(sender, args); + } + } + } + } + return true; + } + + @Override + public List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) { + if (args.length == 0) return Collections.emptyList(); + + String input = args[0].toLowerCase(); + if (args.length == 1) { + return getExecutors().stream() + .filter(e -> e.hasPermission(sender)) + .map(NamedExecutor::getName) + .filter(s -> StringUtil.startsWithIgnoreCase(s, input)) + .collect(Collectors.toList()); + } else { + + CommandHandler handler = this.registeredHandlers.get(input); + if (handler != null && handler.hasPermission(sender)) { + return handler.onTabComplete(sender, command, alias, this.shortenArgs(args)); + } + + SubCommand subCommand = this.registeredCommands.get(input); + if (subCommand != null && subCommand.hasPermission(sender)) { + return subCommand.tabComplete(this.plugin, sender, this.shortenArgs(args)); + } + + return Collections.emptyList(); + } + } + + public List getExecutors() { + Set executors = new HashSet<>(); + executors.addAll(this.registeredHandlers.values()); + executors.addAll(this.registeredCommands.values()); + List sortedExecutors = new ArrayList<>(executors); + sortedExecutors.sort(Comparator.comparing(NamedExecutor::getName)); + return sortedExecutors; + } + + protected String[] shortenArgs(String[] args) { + if (args.length == 0) { + return args; + } else { + List argList = new ArrayList<>(Arrays.asList(args).subList(1, args.length)); + return argList.toArray(new String[0]); + } + } + +} diff --git a/base/command/src/main/java/cc/carm/lib/easyplugin/command/NamedExecutor.java b/base/command/src/main/java/cc/carm/lib/easyplugin/command/NamedExecutor.java new file mode 100644 index 0000000..045f616 --- /dev/null +++ b/base/command/src/main/java/cc/carm/lib/easyplugin/command/NamedExecutor.java @@ -0,0 +1,20 @@ +package cc.carm.lib.easyplugin.command; + +import org.bukkit.permissions.Permissible; + +import java.util.Collections; +import java.util.List; + +public interface NamedExecutor { + + String getName(); + + default List getAliases() { + return Collections.singletonList(getName()); + } + + default boolean hasPermission(Permissible permissible) { + return true; + } + +} diff --git a/base/command/src/main/java/cc/carm/lib/easyplugin/command/SimpleCompleter.java b/base/command/src/main/java/cc/carm/lib/easyplugin/command/SimpleCompleter.java new file mode 100644 index 0000000..7ef030c --- /dev/null +++ b/base/command/src/main/java/cc/carm/lib/easyplugin/command/SimpleCompleter.java @@ -0,0 +1,93 @@ +package cc.carm.lib.easyplugin.command; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.World; +import org.bukkit.entity.HumanEntity; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.StringUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public class SimpleCompleter { + + public static @NotNull List objects(@NotNull String input, Object... objects) { + return objects(input, objects.length, objects); + } + + public static @NotNull List objects(@NotNull String input, int limit, Object... objects) { + return objects(input, limit, Arrays.asList(objects)); + } + + public static @NotNull List objects(@NotNull String input, List objects) { + return objects(input, objects.size(), objects); + } + + public static @NotNull List objects(@NotNull String input, int limit, List objects) { + return objects.stream().filter(Objects::nonNull).map(Object::toString) + .filter(s -> StringUtil.startsWithIgnoreCase(s, input)) + .limit(Math.min(0, limit)).collect(Collectors.toList()); + } + + public static @NotNull List text(@NotNull String input, String... texts) { + return text(input, texts.length, texts); + } + + public static @NotNull List text(@NotNull String input, int limit, String... texts) { + return text(input, limit, Arrays.asList(texts)); + } + + public static @NotNull List text(@NotNull String input, List texts) { + return text(input, texts.size(), texts); + } + + public static @NotNull List text(@NotNull String input, int limit, List texts) { + return objects(input, limit, texts); + } + + public static @NotNull List onlinePlayers(@NotNull String input) { + return onlinePlayers(input, 10); + } + + public static @NotNull List onlinePlayers(@NotNull String input, int limit) { + return text(input, limit, Bukkit.getOnlinePlayers().stream().map(HumanEntity::getName).collect(Collectors.toList())); + } + + public static @NotNull List allPlayers(@NotNull String input) { + return allPlayers(input, 10); + } + + public static @NotNull List allPlayers(@NotNull String input, int limit) { + return text(input, limit, Arrays.stream(Bukkit.getOfflinePlayers()).map(OfflinePlayer::getName).collect(Collectors.toList())); + } + + public static @NotNull List worlds(@NotNull String input) { + return worlds(input, 10); + } + + public static @NotNull List worlds(@NotNull String input, int limit) { + return text(input, limit, Bukkit.getWorlds().stream().map(World::getName).collect(Collectors.toList())); + } + + public static @NotNull List materials(@NotNull String input) { + return materials(input, 10); + } + + public static @NotNull List materials(@NotNull String input, int limit) { + return text(input, limit, Arrays.stream(Material.values()).map(Enum::name).collect(Collectors.toList())); + } + + public static @NotNull List effects(@NotNull String input) { + return effects(input, 10); + } + + public static @NotNull List effects(@NotNull String input, int limit) { + return text(input, limit, Arrays.stream(PotionEffectType.values()).map(PotionEffectType::getName).collect(Collectors.toList())); + } + +} diff --git a/base/command/src/main/java/cc/carm/lib/easyplugin/command/SubCommand.java b/base/command/src/main/java/cc/carm/lib/easyplugin/command/SubCommand.java new file mode 100644 index 0000000..89dcf98 --- /dev/null +++ b/base/command/src/main/java/cc/carm/lib/easyplugin/command/SubCommand.java @@ -0,0 +1,28 @@ +package cc.carm.lib.easyplugin.command; + +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.ArrayList; +import java.util.List; + +@SuppressWarnings("UnusedReturnValue") +public abstract class SubCommand implements NamedExecutor { + private final String name; + + public SubCommand(String name) { + this.name = name; + } + + public abstract Void execute(JavaPlugin plugin, CommandSender sender, String[] args); + + public List tabComplete(JavaPlugin plugin, CommandSender sender, String[] args) { + return new ArrayList<>(); + } + + @Override + public String getName() { + return this.name; + } + +} diff --git a/base/gui/pom.xml b/base/gui/pom.xml index f46f775..67c96d3 100644 --- a/base/gui/pom.xml +++ b/base/gui/pom.xml @@ -5,7 +5,7 @@ easyplugin-parent cc.carm.lib - 1.4.0 + 1.4.1 ../../pom.xml 4.0.0 diff --git a/base/main/pom.xml b/base/main/pom.xml index 711f8d3..9de372f 100644 --- a/base/main/pom.xml +++ b/base/main/pom.xml @@ -5,7 +5,7 @@ easyplugin-parent cc.carm.lib - 1.4.0 + 1.4.1 ../../pom.xml 4.0.0 diff --git a/collection/all/pom.xml b/collection/all/pom.xml index 943b01b..3bc4cf8 100644 --- a/collection/all/pom.xml +++ b/collection/all/pom.xml @@ -5,7 +5,7 @@ easyplugin-parent cc.carm.lib - 1.4.0 + 1.4.1 ../../pom.xml 4.0.0 diff --git a/collection/bom/pom.xml b/collection/bom/pom.xml index 3fb502f..a83bd65 100644 --- a/collection/bom/pom.xml +++ b/collection/bom/pom.xml @@ -5,7 +5,7 @@ easyplugin-parent cc.carm.lib - 1.4.0 + 1.4.1 ../../pom.xml 4.0.0 diff --git a/collection/common/pom.xml b/collection/common/pom.xml index 27216e9..8a23c3c 100644 --- a/collection/common/pom.xml +++ b/collection/common/pom.xml @@ -5,7 +5,7 @@ easyplugin-parent cc.carm.lib - 1.4.0 + 1.4.1 ../../pom.xml 4.0.0 diff --git a/extension/papi/pom.xml b/extension/papi/pom.xml index 026bdf5..ccea407 100644 --- a/extension/papi/pom.xml +++ b/extension/papi/pom.xml @@ -5,7 +5,7 @@ easyplugin-parent cc.carm.lib - 1.4.0 + 1.4.1 ../../pom.xml 4.0.0 diff --git a/extension/vault/pom.xml b/extension/vault/pom.xml index 6bf20e9..c0e4200 100644 --- a/extension/vault/pom.xml +++ b/extension/vault/pom.xml @@ -5,7 +5,7 @@ easyplugin-parent cc.carm.lib - 1.4.0 + 1.4.1 ../../pom.xml 4.0.0 diff --git a/pom.xml b/pom.xml index 97f8dc9..a00c834 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ cc.carm.lib easyplugin-parent pom - 1.4.0 + 1.4.1 base/main @@ -27,6 +27,7 @@ collection/all collection/bom collection/common + base/command