From 2f700b2d9334ebdadd8e3bd605aee09466b1e218 Mon Sep 17 00:00:00 2001 From: William Date: Mon, 8 Aug 2022 19:32:09 +0100 Subject: [PATCH] Use Commodore for rich command completion registering --- api/build.gradle | 5 +++ build.gradle | 5 +-- bukkit/build.gradle | 8 ++++- .../william278/husksync/BukkitHuskSync.java | 6 ++++ .../husksync/command/BrigadierUtil.java | 32 +++++++++++++++++++ .../husksync/command/BukkitCommand.java | 12 ++++--- .../husksync/util/BukkitResourceReader.java | 6 ---- .../resources/commodore/enderchest.commodore | 3 ++ .../resources/commodore/husksync.commodore | 5 +++ .../resources/commodore/inventory.commodore | 3 ++ .../resources/commodore/userdata.commodore | 29 +++++++++++++++++ bukkit/src/main/resources/plugin.yml | 2 +- common/build.gradle | 2 +- .../net/william278/husksync/HuskSync.java | 9 ++++++ .../husksync/command/HuskSyncCommand.java | 10 ++++-- .../husksync/command/UserDataCommand.java | 2 +- .../husksync/database/Database.java | 3 +- .../husksync/util/ResourceReader.java | 14 ++------ 18 files changed, 125 insertions(+), 31 deletions(-) create mode 100644 bukkit/src/main/java/net/william278/husksync/command/BrigadierUtil.java create mode 100644 bukkit/src/main/resources/commodore/enderchest.commodore create mode 100644 bukkit/src/main/resources/commodore/husksync.commodore create mode 100644 bukkit/src/main/resources/commodore/inventory.commodore create mode 100644 bukkit/src/main/resources/commodore/userdata.commodore diff --git a/api/build.gradle b/api/build.gradle index 3407aa49..2e9ad263 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -7,6 +7,10 @@ dependencies { } shadowJar { + dependencies { + exclude(dependency('com.mojang:brigadier')) + } + relocate 'org.apache', 'net.william278.husksync.libraries' relocate 'dev.dejvokep', 'net.william278.husksync.libraries' relocate 'de.themoep', 'net.william278.husksync.libraries' @@ -16,6 +20,7 @@ shadowJar { relocate 'com.google', 'net.william278.husksync.libraries' relocate 'redis.clients', 'net.william278.husksync.libraries' relocate 'org.json', 'net.william278.husksync.libraries.json' + relocate 'me.lucko.commodore', 'net.william278.husksync.libraries.commodore' relocate 'net.byteflux.libby', 'net.william278.husksync.libraries.libby' relocate 'org.bstats', 'net.william278.husksync.libraries.bstats' diff --git a/build.gradle b/build.gradle index 6bc0f973..2b9ae5e2 100644 --- a/build.gradle +++ b/build.gradle @@ -31,11 +31,12 @@ allprojects { maven { url 'https://repo.minebench.de/' } maven { url 'https://repo.alessiodp.com/releases/' } maven { url 'https://jitpack.io' } + maven { url 'https://libraries.minecraft.net/' } } dependencies { - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2' - testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.8.2' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.0' + testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.9.0' } test { diff --git a/bukkit/build.gradle b/bukkit/build.gradle index 8c0f8c28..6f4ba96d 100644 --- a/bukkit/build.gradle +++ b/bukkit/build.gradle @@ -3,11 +3,12 @@ dependencies { implementation 'org.bstats:bstats-bukkit:3.0.0' implementation 'net.william278:mpdbdataconverter:1.0.1' implementation 'net.william278:hsldataconverter:1.0' + implementation 'me.lucko:commodore:2.2' compileOnly 'redis.clients:jedis:4.2.3' compileOnly 'commons-io:commons-io:2.11.0' compileOnly 'de.themoep:minedown:1.7.1-SNAPSHOT' - compileOnly 'dev.dejvokep:boosted-yaml:1.2' + compileOnly 'dev.dejvokep:boosted-yaml:1.3' compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT' compileOnly 'com.zaxxer:HikariCP:5.0.1' @@ -15,6 +16,10 @@ dependencies { } shadowJar { + dependencies { + exclude(dependency('com.mojang:brigadier')) + } + relocate 'org.apache', 'net.william278.husksync.libraries' relocate 'de.themoep', 'net.william278.husksync.libraries' relocate 'org.jetbrains', 'net.william278.husksync.libraries' @@ -23,6 +28,7 @@ shadowJar { relocate 'com.google', 'net.william278.husksync.libraries' relocate 'redis.clients', 'net.william278.husksync.libraries' relocate 'org.json', 'net.william278.husksync.libraries.json' + relocate 'me.lucko.commodore', 'net.william278.husksync.libraries.commodore' relocate 'net.byteflux.libby', 'net.william278.husksync.libraries.libby' relocate 'org.bstats', 'net.william278.husksync.libraries.bstats' diff --git a/bukkit/src/main/java/net/william278/husksync/BukkitHuskSync.java b/bukkit/src/main/java/net/william278/husksync/BukkitHuskSync.java index e2372492..8f486b50 100644 --- a/bukkit/src/main/java/net/william278/husksync/BukkitHuskSync.java +++ b/bukkit/src/main/java/net/william278/husksync/BukkitHuskSync.java @@ -268,6 +268,12 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync { return logger; } + @NotNull + @Override + public ResourceReader getResourceReader() { + return resourceReader; + } + @Override public @NotNull Version getPluginVersion() { return Version.pluginVersion(getDescription().getVersion()); diff --git a/bukkit/src/main/java/net/william278/husksync/command/BrigadierUtil.java b/bukkit/src/main/java/net/william278/husksync/command/BrigadierUtil.java new file mode 100644 index 00000000..d38d2c81 --- /dev/null +++ b/bukkit/src/main/java/net/william278/husksync/command/BrigadierUtil.java @@ -0,0 +1,32 @@ +package net.william278.husksync.command; + +import me.lucko.commodore.CommodoreProvider; +import me.lucko.commodore.file.CommodoreFileReader; +import net.william278.husksync.BukkitHuskSync; +import org.bukkit.command.PluginCommand; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.io.InputStream; +import java.util.logging.Level; + +/** + * Used for registering Brigadier hooks on platforms that support commodore for rich command syntax + */ +public class BrigadierUtil { + + protected static void registerCommodore(@NotNull BukkitHuskSync plugin, @NotNull PluginCommand pluginCommand, + @NotNull CommandBase command) { + // Register command descriptions via commodore (brigadier wrapper) + try (InputStream pluginFile = plugin.getResourceReader() + .getResource("commodore/" + command.command + ".commodore")) { + CommodoreProvider.getCommodore(plugin).register(pluginCommand, + CommodoreFileReader.INSTANCE.parse(pluginFile), + player -> player.hasPermission(command.permission)); + } catch (IOException e) { + plugin.getLoggingAdapter().log(Level.SEVERE, + "Failed to load " + command.command + ".commodore command definitions", e); + } + } + +} diff --git a/bukkit/src/main/java/net/william278/husksync/command/BukkitCommand.java b/bukkit/src/main/java/net/william278/husksync/command/BukkitCommand.java index 945f42d9..ef9e39bd 100644 --- a/bukkit/src/main/java/net/william278/husksync/command/BukkitCommand.java +++ b/bukkit/src/main/java/net/william278/husksync/command/BukkitCommand.java @@ -1,6 +1,7 @@ package net.william278.husksync.command; -import net.william278.husksync.HuskSync; +import me.lucko.commodore.CommodoreProvider; +import net.william278.husksync.BukkitHuskSync; import net.william278.husksync.player.BukkitPlayer; import org.bukkit.command.*; import org.bukkit.entity.Player; @@ -18,14 +19,14 @@ public class BukkitCommand implements CommandExecutor, TabExecutor { /** * The {@link CommandBase} that will be executed */ - private final CommandBase command; + protected final CommandBase command; /** * The implementing plugin */ - private final HuskSync plugin; + private final BukkitHuskSync plugin; - public BukkitCommand(@NotNull CommandBase command, @NotNull HuskSync implementor) { + public BukkitCommand(@NotNull CommandBase command, @NotNull BukkitHuskSync implementor) { this.command = command; this.plugin = implementor; } @@ -40,6 +41,9 @@ public class BukkitCommand implements CommandExecutor, TabExecutor { pluginCommand.setTabCompleter(this); pluginCommand.setPermission(command.permission); pluginCommand.setDescription(command.getDescription()); + if (CommodoreProvider.isSupported()) { + BrigadierUtil.registerCommodore(plugin, pluginCommand, command); + } } @Override diff --git a/bukkit/src/main/java/net/william278/husksync/util/BukkitResourceReader.java b/bukkit/src/main/java/net/william278/husksync/util/BukkitResourceReader.java index 38200c39..ce4e8e6f 100644 --- a/bukkit/src/main/java/net/william278/husksync/util/BukkitResourceReader.java +++ b/bukkit/src/main/java/net/william278/husksync/util/BukkitResourceReader.java @@ -3,7 +3,6 @@ package net.william278.husksync.util; import net.william278.husksync.BukkitHuskSync; import org.jetbrains.annotations.NotNull; -import java.io.File; import java.io.InputStream; import java.util.Objects; @@ -20,9 +19,4 @@ public class BukkitResourceReader implements ResourceReader { return Objects.requireNonNull(plugin.getResource(fileName)); } - @Override - public @NotNull File getDataFolder() { - return plugin.getDataFolder(); - } - } diff --git a/bukkit/src/main/resources/commodore/enderchest.commodore b/bukkit/src/main/resources/commodore/enderchest.commodore new file mode 100644 index 00000000..8bd4c96f --- /dev/null +++ b/bukkit/src/main/resources/commodore/enderchest.commodore @@ -0,0 +1,3 @@ +inventory { + name brigadier:string single_word; +} \ No newline at end of file diff --git a/bukkit/src/main/resources/commodore/husksync.commodore b/bukkit/src/main/resources/commodore/husksync.commodore new file mode 100644 index 00000000..ce2ab50a --- /dev/null +++ b/bukkit/src/main/resources/commodore/husksync.commodore @@ -0,0 +1,5 @@ +husksync { + update; + about; + reload; +} \ No newline at end of file diff --git a/bukkit/src/main/resources/commodore/inventory.commodore b/bukkit/src/main/resources/commodore/inventory.commodore new file mode 100644 index 00000000..9904e908 --- /dev/null +++ b/bukkit/src/main/resources/commodore/inventory.commodore @@ -0,0 +1,3 @@ +enderchest { + name brigadier:string single_word; +} \ No newline at end of file diff --git a/bukkit/src/main/resources/commodore/userdata.commodore b/bukkit/src/main/resources/commodore/userdata.commodore new file mode 100644 index 00000000..3d71b36f --- /dev/null +++ b/bukkit/src/main/resources/commodore/userdata.commodore @@ -0,0 +1,29 @@ +userdata { + view { + name brigadier:string single_word { + version brigadier:string single_word; + test; + } + } + list { + name brigadier:string single_word; + test; + } + delete { + name brigadier:string single_word { + version brigadier:string single_word; + test; + } + } + restore { + name brigadier:string single_word { + version brigadier:string single_word; + test; + } + } + pin { + name brigadier:string single_word { + version brigadier:string single_word; + } + } +} \ No newline at end of file diff --git a/bukkit/src/main/resources/plugin.yml b/bukkit/src/main/resources/plugin.yml index bc54a3fa..384bc166 100644 --- a/bukkit/src/main/resources/plugin.yml +++ b/bukkit/src/main/resources/plugin.yml @@ -11,7 +11,7 @@ softdepend: libraries: - 'mysql:mysql-connector-java:8.0.29' - 'org.xerial.snappy:snappy-java:1.1.8.4' - - 'dev.dejvokep:boosted-yaml:1.2' + - 'dev.dejvokep:boosted-yaml:1.3' commands: husksync: usage: '/husksync ' diff --git a/common/build.gradle b/common/build.gradle index 92bd5344..35a0c078 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -9,7 +9,7 @@ dependencies { exclude module: 'slf4j-api' } - compileOnly 'dev.dejvokep:boosted-yaml:1.2' + compileOnly 'dev.dejvokep:boosted-yaml:1.3' compileOnly 'org.xerial.snappy:snappy-java:1.1.8.4' compileOnly 'org.jetbrains:annotations:23.0.0' compileOnly 'com.github.plan-player-analytics:Plan:5.4.1690' diff --git a/common/src/main/java/net/william278/husksync/HuskSync.java b/common/src/main/java/net/william278/husksync/HuskSync.java index 5d647491..7c20ddea 100644 --- a/common/src/main/java/net/william278/husksync/HuskSync.java +++ b/common/src/main/java/net/william278/husksync/HuskSync.java @@ -10,6 +10,7 @@ import net.william278.husksync.migrator.Migrator; import net.william278.husksync.player.OnlineUser; import net.william278.husksync.redis.RedisManager; import net.william278.husksync.util.Logger; +import net.william278.husksync.util.ResourceReader; import net.william278.husksync.util.Version; import org.jetbrains.annotations.NotNull; @@ -114,6 +115,14 @@ public interface HuskSync { @NotNull Logger getLoggingAdapter(); + /** + * Returns the plugin resource file reader + * + * @return the {@link ResourceReader} + */ + @NotNull + ResourceReader getResourceReader(); + /** * Returns the plugin version * diff --git a/common/src/main/java/net/william278/husksync/command/HuskSyncCommand.java b/common/src/main/java/net/william278/husksync/command/HuskSyncCommand.java index 3aceda24..02bfd1f5 100644 --- a/common/src/main/java/net/william278/husksync/command/HuskSyncCommand.java +++ b/common/src/main/java/net/william278/husksync/command/HuskSyncCommand.java @@ -9,6 +9,7 @@ import net.william278.husksync.util.UpdateChecker; import org.jetbrains.annotations.NotNull; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.logging.Level; @@ -126,9 +127,12 @@ public class HuskSyncCommand extends CommandBase implements TabCompletable, Cons @Override public List onTabComplete(@NotNull String[] args) { - return Arrays.stream(COMMAND_ARGUMENTS) - .filter(argument -> argument.startsWith(args.length >= 1 ? args[0] : "")) - .sorted().collect(Collectors.toList()); + if (args.length <= 1) { + return Arrays.stream(COMMAND_ARGUMENTS) + .filter(argument -> argument.startsWith(args.length >= 1 ? args[0] : "")) + .sorted().collect(Collectors.toList()); + } + return Collections.emptyList(); } private void displayPluginInformation(@NotNull OnlineUser player) { diff --git a/common/src/main/java/net/william278/husksync/command/UserDataCommand.java b/common/src/main/java/net/william278/husksync/command/UserDataCommand.java index e2726adb..1aa50c44 100644 --- a/common/src/main/java/net/william278/husksync/command/UserDataCommand.java +++ b/common/src/main/java/net/william278/husksync/command/UserDataCommand.java @@ -225,7 +225,7 @@ public class UserDataCommand extends CommandBase implements TabCompletable { switch (args.length) { case 0, 1 -> { return Arrays.stream(COMMAND_ARGUMENTS) - .filter(argument -> argument.startsWith(args.length >= 1 ? args[0] : "")) + .filter(argument -> argument.startsWith(args.length == 1 ? args[0] : "")) .sorted().collect(Collectors.toList()); } case 2 -> { diff --git a/common/src/main/java/net/william278/husksync/database/Database.java b/common/src/main/java/net/william278/husksync/database/Database.java index 8c7c4f11..6ed10145 100644 --- a/common/src/main/java/net/william278/husksync/database/Database.java +++ b/common/src/main/java/net/william278/husksync/database/Database.java @@ -14,6 +14,7 @@ import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -108,7 +109,7 @@ public abstract class Database { */ @SuppressWarnings("SameParameterValue") protected final String[] getSchemaStatements(@NotNull String schemaFileName) throws IOException { - return formatStatementTables(new String(resourceReader.getResource(schemaFileName) + return formatStatementTables(new String(Objects.requireNonNull(resourceReader.getResource(schemaFileName)) .readAllBytes(), StandardCharsets.UTF_8)).split(";"); } diff --git a/common/src/main/java/net/william278/husksync/util/ResourceReader.java b/common/src/main/java/net/william278/husksync/util/ResourceReader.java index 7acbe70a..bf3e56e4 100644 --- a/common/src/main/java/net/william278/husksync/util/ResourceReader.java +++ b/common/src/main/java/net/william278/husksync/util/ResourceReader.java @@ -1,8 +1,7 @@ package net.william278.husksync.util; -import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.io.File; import java.io.InputStream; /** @@ -14,15 +13,8 @@ public interface ResourceReader { * Gets the resource with given filename and reads it as an {@link InputStream} * * @param fileName Name of the resource file to read - * @return The resource, read as an {@link InputStream} + * @return The resource, read as an {@link InputStream}; or {@code null} if the resource was not found */ - @NotNull InputStream getResource(String fileName); - - /** - * Gets the plugin data folder where plugin configuration and data are kept - * - * @return the plugin data directory - */ - @NotNull File getDataFolder(); + @Nullable InputStream getResource(String fileName); }