From f1e5e39156b889169135eed1aad113430826397c Mon Sep 17 00:00:00 2001 From: yoyosource Date: Sat, 20 Nov 2021 18:56:38 +0100 Subject: [PATCH] Add SWCommand.Register.description to simplify help commands --- SpigotCore_Main/build.gradle | 5 ++ .../src/de/steamwar/command/SWCommand.java | 76 ++++++++++++++++++- .../src/de/steamwar/command/SubCommand.java | 8 +- 3 files changed, 82 insertions(+), 7 deletions(-) diff --git a/SpigotCore_Main/build.gradle b/SpigotCore_Main/build.gradle index 59c9f89..7a48ea5 100644 --- a/SpigotCore_Main/build.gradle +++ b/SpigotCore_Main/build.gradle @@ -46,6 +46,11 @@ dependencies { compileOnly files("${project.rootDir}/lib/Spigot-1.15.jar") compileOnly files("${project.rootDir}/lib/WorldEdit-1.12.jar") implementation 'net.wesjd:anvilgui:1.4.0-SNAPSHOT' + + compileOnly 'org.projectlombok:lombok:1.18.6' + testCompileOnly 'org.projectlombok:lombok:1.18.6' + annotationProcessor 'org.projectlombok:lombok:1.18.6' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.6' } processResources { diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 99864c2..f04cf62 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -19,14 +19,18 @@ package de.steamwar.command; +import de.steamwar.message.Message; +import lombok.Setter; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; import java.lang.annotation.*; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiConsumer; import java.util.function.IntPredicate; import java.util.logging.Level; @@ -41,6 +45,9 @@ public abstract class SWCommand { private final Map> localTypeMapper = new HashMap<>(); private final Map localGuardChecker = new HashMap<>(); + @Setter + private Message message = null; + protected SWCommand(String command) { this(command, new String[0]); } @@ -82,7 +89,7 @@ public abstract class SWCommand { } private synchronized void createMapping() { - Method[] methods = getClass().getDeclaredMethods(); + List methods = methods(); for (Method method : methods) { addMapper(Mapper.class, method, i -> i == 0, false, TypeMapper.class, (anno, typeMapper) -> { (anno.local() ? localTypeMapper : SWCommandUtils.MAPPER_FUNCTIONS).putIfAbsent(anno.value(), typeMapper); @@ -109,7 +116,7 @@ public abstract class SWCommand { Bukkit.getLogger().log(Level.WARNING, () -> "The method '" + method.toString() + "' is lacking the varArgs parameters of type '" + String.class.getTypeName() + "' as last Argument"); return; } - commandHelpList.add(new SubCommand(this, method, anno.value(), new HashMap<>(), localGuardChecker, true)); + commandHelpList.add(new SubCommand(this, method, anno.value(), new HashMap<>(), localGuardChecker, true, null)); }); } for (Method method : methods) { @@ -131,7 +138,7 @@ public abstract class SWCommand { return; } } - commandList.add(new SubCommand(this, method, anno.value(), localTypeMapper, localGuardChecker, false)); + commandList.add(new SubCommand(this, method, anno.value(), localTypeMapper, localGuardChecker, false, anno.description())); }); this.commandList.sort((o1, o2) -> { @@ -143,7 +150,15 @@ public abstract class SWCommand { o2.varArgType != null ? Integer.MAX_VALUE : o2.arguments.length); } }); - commandHelpList.sort(Comparator.comparingInt(o -> -o.subCommand.length)); + commandHelpList.sort((o1, o2) -> { + int compare = Integer.compare(-o1.subCommand.length, -o2.subCommand.length); + if (compare != 0) { + return compare; + } else { + return Integer.compare(o1.method.getDeclaringClass() == SWCommand.class ? 1 : 0, + o2.method.getDeclaringClass() == SWCommand.class ? 1 : 0); + } + }); } initialized = true; } @@ -190,6 +205,12 @@ public abstract class SWCommand { }); } + private List methods() { + List methods = new ArrayList<>(Arrays.asList(getClass().getDeclaredMethods())); + methods.addAll(Arrays.asList(SWCommand.class.getDeclaredMethods())); + return methods; + } + public void unregister() { SWCommandUtils.knownCommandMap.remove(command.getName()); command.getAliases().forEach(SWCommandUtils.knownCommandMap::remove); @@ -200,6 +221,51 @@ public abstract class SWCommand { SWCommandUtils.commandMap.register("steamwar", this.command); } + @Register(help = true) + private void internalHelp(Player p, String... args) { + if (message == null) { + return; + } + try { + message.sendPrefixless("COMMAND_HELP_HEAD", p, command.getName()); + } catch (Exception e) { + Bukkit.getLogger().log(Level.WARNING, "Failed to send help message", e); + return; + } + AtomicInteger atomicInteger = new AtomicInteger(); + if (args.length != 0) { + commandList.forEach(subCommand -> { + List tabCompletes = subCommand.tabComplete(p, args); + if (tabCompletes == null || tabCompletes.isEmpty()) { + atomicInteger.incrementAndGet(); + return; + } + boolean hasTabCompletes = tabCompletes.stream() + .anyMatch(s -> s.toLowerCase().startsWith(args[args.length - 1].toLowerCase())); + if (hasTabCompletes) { + try { + message.sendPrefixless(subCommand.description, p); + } catch (Exception e) { + Bukkit.getLogger().log(Level.WARNING, "Failed to send description of registered method '" + subCommand.method + "' with description '" + subCommand.description + "'", e); + } + } else { + atomicInteger.incrementAndGet(); + } + }); + } + if (args.length == 0 || atomicInteger.get() == commandList.size()) { + commandList.forEach(subCommand -> { + if (subCommand.guardChecker == null || subCommand.guardChecker.guard(p, GuardCheckType.TAB_COMPLETE, new String[0], null) == GuardResult.ALLOWED) { + try { + message.sendPrefixless(subCommand.description, p); + } catch (Exception e) { + Bukkit.getLogger().log(Level.WARNING, "Failed to send description of registered method '" + subCommand.method + "' with description '" + subCommand.description + "'", e); + } + } + }); + } + } + @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) @Repeatable(Register.Registeres.class) @@ -208,6 +274,8 @@ public abstract class SWCommand { boolean help() default false; + String description() default ""; + @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) @interface Registeres { diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 3cd6778..4581c8d 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -35,20 +35,22 @@ import static de.steamwar.command.SWCommandUtils.*; class SubCommand { private SWCommand swCommand; - private Method method; + Method method; + String description; String[] subCommand; TypeMapper[] arguments; GuardChecker[] guards; private Predicate commandSenderPredicate; private Function commandSenderFunction; - private GuardChecker guardChecker; + GuardChecker guardChecker; Class varArgType = null; private boolean help; - SubCommand(SWCommand swCommand, Method method, String[] subCommand, Map> localTypeMapper, Map localGuardChecker, boolean help) { + SubCommand(SWCommand swCommand, Method method, String[] subCommand, Map> localTypeMapper, Map localGuardChecker, boolean help, String description) { this.swCommand = swCommand; this.method = method; this.help = help; + this.description = description; Parameter[] parameters = method.getParameters(); commandSenderPredicate = sender -> parameters[0].getType().isAssignableFrom(sender.getClass());