From d8f90e0b14c0e8394c7a03275148f3e9de867ee6 Mon Sep 17 00:00:00 2001 From: ThebigTijn <85112325+ThebigTijn@users.noreply.github.com> Date: Tue, 30 Jun 2026 21:10:10 +0200 Subject: [PATCH 1/3] Add debug flags and conditional logging --- build.gradle.kts | 2 -- .../jazzkuh/commandlib/jda/AnnotationCommand.java | 4 ++-- .../com/jazzkuh/commandlib/jda/JDACommandLoader.java | 5 ++++- .../commandlib/minestom/AnnotationCommand.java | 12 ++++++++---- .../commandlib/minestom/MinestomCommandLoader.java | 3 +++ .../jazzkuh/commandlib/spigot/AnnotationCommand.java | 8 +++++--- .../commandlib/spigot/SpigotCommandLoader.java | 4 ++++ 7 files changed, 26 insertions(+), 12 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 0057d38..1856ae0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,8 +15,6 @@ subprojects { tasks.withType().configureEach { options.encoding = "UTF-8" - // Target Java 21 bytecode for the modules shaded into Paper plugins so they - // load on Java 21+ servers. Other platforms (e.g. minestom) need Java 25. if (project.name in listOf("spigot", "common")) { options.release.set(21) } diff --git a/jda/src/main/java/com/jazzkuh/commandlib/jda/AnnotationCommand.java b/jda/src/main/java/com/jazzkuh/commandlib/jda/AnnotationCommand.java index 9091b11..98412c9 100644 --- a/jda/src/main/java/com/jazzkuh/commandlib/jda/AnnotationCommand.java +++ b/jda/src/main/java/com/jazzkuh/commandlib/jda/AnnotationCommand.java @@ -95,7 +95,7 @@ private void executeCommand(JDASubCommand subCommand, SlashCommandInteractionEve try { commandExecutor.execute(commandSender, args); - System.out.println("Executed command " + subCommand.getName()); + if (JDACommandLoader.isDebug()) System.out.println("Executed command " + subCommand.getName()); } catch (CommandException commandException) { switch (commandException) { case ArgumentException ignored -> event.reply("Not enough arguments.").queue(); @@ -175,7 +175,7 @@ public void register(JDA jda) { commandData.addSubcommands(subcommandData); } - System.out.println("Registered command " + commandName); + if (JDACommandLoader.isDebug()) System.out.println("Registered command " + commandName); JDACommandLoader.getToPropagate().add(commandData); } } diff --git a/jda/src/main/java/com/jazzkuh/commandlib/jda/JDACommandLoader.java b/jda/src/main/java/com/jazzkuh/commandlib/jda/JDACommandLoader.java index 71d7af9..59c86d7 100644 --- a/jda/src/main/java/com/jazzkuh/commandlib/jda/JDACommandLoader.java +++ b/jda/src/main/java/com/jazzkuh/commandlib/jda/JDACommandLoader.java @@ -1,6 +1,7 @@ package com.jazzkuh.commandlib.jda; import lombok.Getter; +import lombok.Setter; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.*; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; @@ -15,6 +16,8 @@ public class JDACommandLoader { private static final @Getter Set toPropagate = new HashSet<>(); + @Getter @Setter + private static boolean debug = true; public static final Map, OptionType> DEFINITIONS; static { @@ -36,7 +39,7 @@ public class JDACommandLoader { public static void propagate(JDA jda) { CommandListUpdateAction action = jda.updateCommands(); action.addCommands(toPropagate).complete(); - System.out.println("Propagated " + toPropagate.size() + " commands."); + if (debug) System.out.println("Propagated " + toPropagate.size() + " commands."); toPropagate.clear(); } } diff --git a/minestom/src/main/java/com/jazzkuh/commandlib/minestom/AnnotationCommand.java b/minestom/src/main/java/com/jazzkuh/commandlib/minestom/AnnotationCommand.java index c0e6572..89d0310 100644 --- a/minestom/src/main/java/com/jazzkuh/commandlib/minestom/AnnotationCommand.java +++ b/minestom/src/main/java/com/jazzkuh/commandlib/minestom/AnnotationCommand.java @@ -278,7 +278,9 @@ private void executeCommand(AnnotationSubCommand subCommand, CommandSender sende if (sender instanceof ConsoleSender) sender = new LoggingConsoleSender(); if (sender instanceof Player player) { permissable = new Permissable(player.getUuid()); - LOGGER.info("Command executed by {}: {} {}", player.getUsername(), this.getCommandName(), String.join(" ", args)); + if (MinestomCommandLoader.isDebug()) { + LOGGER.info("Command executed by {}: {} {}", player.getUsername(), this.getCommandName(), String.join(" ", args)); + } } if (subCommand.getPermission() != null && !(sender instanceof ConsoleSender) && !permissable.hasPermission(subCommand.getPermission())) { @@ -361,9 +363,11 @@ public List suggest(CommandSender sender, String[] args) { public void register(CommandManager commandManager) { try { commandManager.register(this); - LOGGER.info("Registered command: {}", this.getCommandName()); - if (!Arrays.stream(this.getAliases()).toList().isEmpty()) { - LOGGER.info("- Registered aliases: {}", String.join(", ", this.getAliases())); + if (MinestomCommandLoader.isDebug()) { + LOGGER.info("Registered command: {}", this.getCommandName()); + if (!Arrays.stream(this.getAliases()).toList().isEmpty()) { + LOGGER.info("- Registered aliases: {}", String.join(", ", this.getAliases())); + } } } catch (Exception exception) { LOGGER.info("Unable to register command: {}", this.getCommandName()); diff --git a/minestom/src/main/java/com/jazzkuh/commandlib/minestom/MinestomCommandLoader.java b/minestom/src/main/java/com/jazzkuh/commandlib/minestom/MinestomCommandLoader.java index 4fba8f7..a534258 100644 --- a/minestom/src/main/java/com/jazzkuh/commandlib/minestom/MinestomCommandLoader.java +++ b/minestom/src/main/java/com/jazzkuh/commandlib/minestom/MinestomCommandLoader.java @@ -18,6 +18,9 @@ public class MinestomCommandLoader { @Getter @Setter private static PermissionProvider permissionProvider; + @Getter @Setter + private static boolean debug = true; + public static void startTerminal() { MinestomTerminal.start(); } diff --git a/spigot/src/main/java/com/jazzkuh/commandlib/spigot/AnnotationCommand.java b/spigot/src/main/java/com/jazzkuh/commandlib/spigot/AnnotationCommand.java index ab1f7d7..ed20c43 100644 --- a/spigot/src/main/java/com/jazzkuh/commandlib/spigot/AnnotationCommand.java +++ b/spigot/src/main/java/com/jazzkuh/commandlib/spigot/AnnotationCommand.java @@ -180,9 +180,11 @@ public void register(JavaPlugin plugin) { CommandMap commandMap = (CommandMap) bukkitCommandMap.get(Bukkit.getServer()); commandMap.register(plugin.getName(), this); - plugin.getLogger().info("Registered command: " + this.getCommandName()); - if (!allAliases.isEmpty()) { - plugin.getLogger().info("- Registered aliases: " + String.join(", ", allAliases)); + if (SpigotCommandLoader.isDebug()) { + plugin.getLogger().info("Registered command: " + this.getCommandName()); + if (!allAliases.isEmpty()) { + plugin.getLogger().info("- Registered aliases: " + String.join(", ", allAliases)); + } } } catch (Exception exception) { plugin.getLogger().severe("Unable to register command: " + this.getCommandName()); diff --git a/spigot/src/main/java/com/jazzkuh/commandlib/spigot/SpigotCommandLoader.java b/spigot/src/main/java/com/jazzkuh/commandlib/spigot/SpigotCommandLoader.java index b55864c..7a32040 100644 --- a/spigot/src/main/java/com/jazzkuh/commandlib/spigot/SpigotCommandLoader.java +++ b/spigot/src/main/java/com/jazzkuh/commandlib/spigot/SpigotCommandLoader.java @@ -16,6 +16,10 @@ public class SpigotCommandLoader { @Setter private static FormattingProvider formattingProvider; + @Getter + @Setter + private static boolean debug = true; + public static void loadResolvers() { Resolvers.register(Player.class, new PlayerResolver()); Resolvers.register(GameMode.class, new GameModeResolver()); From 8d065ddef145d0a0fc76ab6bddb1acf143ef0f3f Mon Sep 17 00:00:00 2001 From: ThebigTijn <85112325+ThebigTijn@users.noreply.github.com> Date: Tue, 14 Jul 2026 21:31:52 +0200 Subject: [PATCH 2/3] Support nested (multi-word) subcommands in AnnotationCommand --- .../commandlib/spigot/AnnotationCommand.java | 82 ++++++++++++++----- 1 file changed, 63 insertions(+), 19 deletions(-) diff --git a/spigot/src/main/java/com/jazzkuh/commandlib/spigot/AnnotationCommand.java b/spigot/src/main/java/com/jazzkuh/commandlib/spigot/AnnotationCommand.java index ed20c43..a1bae28 100644 --- a/spigot/src/main/java/com/jazzkuh/commandlib/spigot/AnnotationCommand.java +++ b/spigot/src/main/java/com/jazzkuh/commandlib/spigot/AnnotationCommand.java @@ -11,15 +11,15 @@ import org.bukkit.command.CommandMap; import org.bukkit.command.CommandSender; import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.util.StringUtil; import org.jetbrains.annotations.NotNull; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; -import java.util.Comparator; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; public class AnnotationCommand extends Command implements AnnotationCommandImpl { @@ -76,9 +76,19 @@ public boolean execute(@NotNull CommandSender sender, @NotNull String label, @No return true; } + AnnotationSubCommand match = null; + int matchLength = 0; for (AnnotationSubCommand subCommand : subCommands) { - if (!args[0].equalsIgnoreCase(subCommand.getName()) && !subCommand.getAliases().contains(args[0].toLowerCase())) continue; - this.executeCommand(subCommand, sender, args); + int length = matchLength(subCommand, args); + if (length > matchLength) { + match = subCommand; + matchLength = length; + } + } + + if (match != null) { + String[] effectiveArgs = matchLength > 1 ? collapse(args, matchLength, match.getName()) : args; + this.executeCommand(match, sender, effectiveArgs); return true; } @@ -126,7 +136,7 @@ private void executeCommand(AnnotationSubCommand subCommand, CommandSender sende @Override @NotNull public List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - List options = new ArrayList<>(); + Set options = new LinkedHashSet<>(); AnnotationCommandSender commandSender = new AnnotationCommandSender<>(sender); for (AnnotationSubCommand mainCommand : this.mainCommands) { @@ -136,26 +146,60 @@ public List tabComplete(@NotNull CommandSender sender, @NotNull String a } } - if (args.length == 1 && !this.subCommands.isEmpty()) { - for (AnnotationSubCommand subCommand : this.subCommands) { - if (subCommand.getPermission() == null) { - options.add(subCommand.getName()); - continue; - } + int index = args.length - 1; + if (index < 0) return new ArrayList<>(options); + String partial = args[index]; - if (commandSender.getSender().hasPermission(subCommand.getPermission())) options.add(subCommand.getName()); + for (AnnotationSubCommand subCommand : this.subCommands) { + if (subCommand.getPermission() != null && !sender.hasPermission(subCommand.getPermission())) continue; + String[] name = nameTokens(subCommand); + + if (name.length <= index && prefixMatches(args, name, name.length)) { + String[] effectiveArgs = name.length > 1 ? collapse(args, name.length, subCommand.getName()) : args; + AnnotationCommandExecutor subCommandExecutor = new AnnotationCommandExecutor<>(subCommand, this); + options.addAll(subCommandExecutor.complete(commandSender, effectiveArgs)); + } else if (name.length > index && prefixMatches(args, name, index) + && startsWithIgnoreCase(name[index], partial)) { + options.add(name[index]); } - return StringUtil.copyPartialMatches(args[0], options, new ArrayList<>(options.size())); + if (index == 0) { + for (String subAlias : subCommand.getAliases()) { + if (startsWithIgnoreCase(subAlias, partial)) options.add(subAlias); + } + } } + return new ArrayList<>(options); + } - for (AnnotationSubCommand subCommand : this.subCommands) { - if (!args[0].equalsIgnoreCase(subCommand.getName()) && !subCommand.getAliases().contains(args[0].toLowerCase())) continue; - AnnotationCommandExecutor subCommandExecutor = new AnnotationCommandExecutor<>(subCommand, this); - if (subCommand.getPermission() != null && !commandSender.getSender().hasPermission(subCommand.getPermission())) continue; - options.addAll(subCommandExecutor.complete(commandSender, args)); + private static String[] nameTokens(AnnotationSubCommand subCommand) { + return subCommand.getName().trim().split("\\s+"); + } + + private static boolean prefixMatches(String[] args, String[] name, int count) { + if (args.length < count || name.length < count) return false; + for (int i = 0; i < count; i++) { + if (!name[i].equalsIgnoreCase(args[i])) return false; } - return options; + return true; + } + + private static int matchLength(AnnotationSubCommand subCommand, String[] args) { + String[] name = nameTokens(subCommand); + if (name.length <= args.length && prefixMatches(args, name, name.length)) return name.length; + if (args.length >= 1 && subCommand.getAliases().contains(args[0].toLowerCase())) return 1; + return 0; + } + + private static String[] collapse(String[] args, int count, String name) { + String[] collapsed = new String[args.length - count + 1]; + collapsed[0] = name; + System.arraycopy(args, count, collapsed, 1, args.length - count); + return collapsed; + } + + private static boolean startsWithIgnoreCase(String value, String prefix) { + return value.length() >= prefix.length() && value.regionMatches(true, 0, prefix, 0, prefix.length()); } public void register(JavaPlugin plugin) { From b6c7dfd721f2bab7ce1ccc99d86e1b1314d58a8d Mon Sep 17 00:00:00 2001 From: ThebigTijn <85112325+ThebigTijn@users.noreply.github.com> Date: Fri, 17 Jul 2026 14:27:43 +0200 Subject: [PATCH 3/3] Update build.yml --- .github/workflows/build.yml | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cf49a0a..7f2024f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,7 +1,7 @@ -# This workflow will build a Java project with Maven -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven +# This workflow will build a Java project with Gradle +# For more information see: https://docs.github.com/actions/guides/building-and-testing-java-with-gradle -name: Java CI with Maven +name: Java CI with Gradle on: push: @@ -11,19 +11,20 @@ on: jobs: build: - if: "!contains(github.event.commits[0].message, '[ci-skip]')" + if: "!contains(github.event.head_commit.message, '[ci-skip]')" runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Set up JDK 21 - uses: actions/setup-java@v2 + - name: Set up JDK 25 + uses: actions/setup-java@v4 with: - java-version: '21' - distribution: 'adopt' - - name: Build with Maven - run: mvn -B package --file pom.xml + java-version: '25' + distribution: 'temurin' + cache: 'gradle' + - name: Build with Gradle + run: ./gradlew build --no-daemon - name: Upload a Build Artifact uses: actions/upload-artifact@v4 with: name: CommandLibrary - path: ./*/target/*.jar + path: ./*/build/libs/*.jar