From b42b77b0bf09f3d87a876456d1a6de9f4673f332 Mon Sep 17 00:00:00 2001 From: zax71 Date: Sat, 2 Sep 2023 18:04:31 +0100 Subject: [PATCH 1/8] implement `/mv gamerules` command --- .../commands/GamerulesCommand.java | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java new file mode 100644 index 00000000..1c397719 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java @@ -0,0 +1,109 @@ +package com.onarandombox.MultiverseCore.commands; + +import co.aikar.commands.BukkitCommandIssuer; +import co.aikar.commands.annotation.CommandAlias; +import co.aikar.commands.annotation.CommandCompletion; +import co.aikar.commands.annotation.CommandPermission; +import co.aikar.commands.annotation.Description; +import co.aikar.commands.annotation.Flags; +import co.aikar.commands.annotation.Single; +import co.aikar.commands.annotation.Subcommand; +import co.aikar.commands.annotation.Syntax; +import com.dumptruckman.minecraft.util.Logging; +import com.onarandombox.MultiverseCore.api.MVWorld; +import com.onarandombox.MultiverseCore.api.MVWorldManager; +import com.onarandombox.MultiverseCore.commandtools.MVCommandManager; +import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand; +import jakarta.inject.Inject; +import org.bukkit.GameRule; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jvnet.hk2.annotations.Service; + +import java.util.HashMap; +import java.util.Map; + +/** + * List all gamerules in your current or specified world + */ +@Service +@CommandAlias("mv") +public class GamerulesCommand extends MultiverseCommand { + + private final MVWorldManager worldManager; + + @Inject + public GamerulesCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) { + super(commandManager); + this.worldManager = worldManager; + } + + @Subcommand("gamerules|rules") + @CommandPermission("multiverse.core.gamerules.list") + @CommandCompletion("@mvworlds") + @Syntax("[World]") + @Description("{@@mv-core.gamerules.description}") //TODO i18n + public void onGamerulesCommand(@NotNull BukkitCommandIssuer issuer, + + @Flags("resolve=issuerOnly") + Player player, + + @Single + @Syntax("") + @Description("{@@mv-core.gamerules.world.description}") //TODO i18n + MVWorld world + ) { + if (!issuer.isPlayer()) { + if (world == null) { + issuer.sendMessage("You must specify a world from the command line"); + return; + } + } + + // Get the players world if none is specified + if (world == null) { + Logging.finer("Getting the player's current world to list gamerules for"); + world = worldManager.getMVWorld(player.getWorld()); + } + + issuer.sendMessage("--- Gamerules for " + world.getName() + " ---\n" + encodeMap(getGameRuleMap(world.getCBWorld()))); + + + + } + + /** + * Gets all the gamerules and their values for a given world + * @param world The world to find gamerules for + * @return A map of the gamerules and their values + */ + private Map getGameRuleMap(World world) { + Map gameRuleMap = new HashMap<>(); + + for (GameRule gamerule : GameRule.values()) { + Object gameruleValue = world.getGameRuleValue(gamerule); + if (gameruleValue == null) { + gameRuleMap.put(gamerule.getName(), "null"); + continue; + } + gameRuleMap.put(gamerule.getName(), gameruleValue.toString()); + } + return gameRuleMap; + } + + private String encodeMap(Map inMap) { //TODO i18n + StringBuilder stringBuilder = new StringBuilder(); + for (String key : inMap.keySet()) { + String value = inMap.get(key); + + stringBuilder + .append("&l") + .append(key) + .append("&f : &6") + .append(value) + .append("\n"); + } + return stringBuilder.toString(); + } +} From 1ac54b7e1d73bf6e8104380b3ab835b3edad3f0c Mon Sep 17 00:00:00 2001 From: zax71 Date: Mon, 4 Sep 2023 13:08:39 +0100 Subject: [PATCH 2/8] Add i18n --- .../commands/GamerulesCommand.java | 33 ++++++++++--------- .../MultiverseCore/utils/MVCorei18n.java | 7 ++++ .../resources/multiverse-core_en.properties | 7 ++++ 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java index 1c397719..782ddf8d 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java @@ -1,6 +1,8 @@ package com.onarandombox.MultiverseCore.commands; import co.aikar.commands.BukkitCommandIssuer; +import co.aikar.commands.CommandIssuer; +import co.aikar.commands.MessageType; import co.aikar.commands.annotation.CommandAlias; import co.aikar.commands.annotation.CommandCompletion; import co.aikar.commands.annotation.CommandPermission; @@ -14,6 +16,7 @@ import com.onarandombox.MultiverseCore.api.MVWorld; import com.onarandombox.MultiverseCore.api.MVWorldManager; import com.onarandombox.MultiverseCore.commandtools.MVCommandManager; import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand; +import com.onarandombox.MultiverseCore.utils.MVCorei18n; import jakarta.inject.Inject; import org.bukkit.GameRule; import org.bukkit.World; @@ -43,31 +46,29 @@ public class GamerulesCommand extends MultiverseCommand { @CommandPermission("multiverse.core.gamerules.list") @CommandCompletion("@mvworlds") @Syntax("[World]") - @Description("{@@mv-core.gamerules.description}") //TODO i18n + @Description("{@@mv-core.gamerules.description}") public void onGamerulesCommand(@NotNull BukkitCommandIssuer issuer, - @Flags("resolve=issuerOnly") - Player player, - @Single @Syntax("") - @Description("{@@mv-core.gamerules.world.description}") //TODO i18n + @Description("{@@mv-core.gamerules.description.world}") MVWorld world ) { - if (!issuer.isPlayer()) { - if (world == null) { - issuer.sendMessage("You must specify a world from the command line"); + if (!issuer.isPlayer() && world == null) { + issuer.sendInfo(MVCorei18n.GAMERULES_ERROR_SPECIFYWORLD); return; - } } // Get the players world if none is specified if (world == null) { + Player player = issuer.getPlayer(); // Need to do it here so the command can be run from console Logging.finer("Getting the player's current world to list gamerules for"); world = worldManager.getMVWorld(player.getWorld()); } - issuer.sendMessage("--- Gamerules for " + world.getName() + " ---\n" + encodeMap(getGameRuleMap(world.getCBWorld()))); + // Finally, send the list + issuer.sendInfo(MVCorei18n.GAMERULES_TITLE, "{world}", world.getName()); + issuer.sendMessage("\n" + encodeMap(issuer, getGameRuleMap(world.getCBWorld()))); @@ -92,16 +93,16 @@ public class GamerulesCommand extends MultiverseCommand { return gameRuleMap; } - private String encodeMap(Map inMap) { //TODO i18n + private String encodeMap(CommandIssuer issuer, Map inMap) { StringBuilder stringBuilder = new StringBuilder(); for (String key : inMap.keySet()) { String value = inMap.get(key); - stringBuilder - .append("&l") - .append(key) - .append("&f : &6") - .append(value) + stringBuilder.append(this.commandManager.formatMessage( + issuer, + MessageType.INFO, + MVCorei18n.GAMERULES_RULE, + "{gamerule}", key, "{value}", value)) .append("\n"); } return stringBuilder.toString(); diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/MVCorei18n.java b/src/main/java/com/onarandombox/MultiverseCore/utils/MVCorei18n.java index 0c2b3351..f2b7ac8f 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/MVCorei18n.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/MVCorei18n.java @@ -42,6 +42,13 @@ public enum MVCorei18n implements MessageKeyProvider { GAMERULE_SUCCESS_SINGLE, GAMERULE_SUCCESS_MULTIPLE, + // Gamerules command + GAMERULES_DESCRIPTION, + GAMERULES_DESCRIPTION_WORLD, + GAMERULES_ERROR_SPECIFYWORLD, + GAMERULES_TITLE, + GAMERULES_RULE, + // import command IMPORT_IMPORTING, IMPORT_FAILED, diff --git a/src/main/resources/multiverse-core_en.properties b/src/main/resources/multiverse-core_en.properties index b97ca106..a72bfb44 100644 --- a/src/main/resources/multiverse-core_en.properties +++ b/src/main/resources/multiverse-core_en.properties @@ -59,6 +59,13 @@ mv-core.gamerule.failed=Failed to set gamerule {gamerule} to {value} in {world}. mv-core.gamerule.success.single=&aSuccessfully set {gamerule} to {value} in {world}. mv-core.gamerule.success.multiple=&aSuccessfully set {gamerule} to {value} in {count} worlds. +# /mv gamerules +mv-core.gamerules.description=Lists gamerules for the specified world +mv-core.gamerules.description.world=The world to list gamerules in +mv-core.gamerules.error.specifyworld=You must specify a world from the command line +mv-core.gamerules.title= --- Gamerules for {world} --- +mv-core.gamerules.rule=&l{gamerule}&f : &6{value} + # /mv import mv-core.import.description=Imports an existing world folder. mv-core.import.name.description=Name of the world folder. From 3cdf9736ec8d91a8e1cdf1c0f993294f69e7e7f0 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Thu, 7 Sep 2023 23:31:54 +0800 Subject: [PATCH 3/8] Refactor a better method of registering and using command flags --- .../commandtools/MultiverseCommand.java | 21 +++++++++++++++++++ .../flags/ParsedCommandFlags.java | 12 +++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/main/java/com/onarandombox/MultiverseCore/commandtools/MultiverseCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commandtools/MultiverseCommand.java index b198166b..8d8658f1 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commandtools/MultiverseCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commandtools/MultiverseCommand.java @@ -1,9 +1,12 @@ package com.onarandombox.MultiverseCore.commandtools; import co.aikar.commands.BaseCommand; +import com.dumptruckman.minecraft.util.Logging; +import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlag; import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagGroup; import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagsManager; import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags; +import jakarta.annotation.PostConstruct; import org.jetbrains.annotations.NotNull; import org.jvnet.hk2.annotations.Contract; @@ -12,21 +15,39 @@ public abstract class MultiverseCommand extends BaseCommand { protected final MVCommandManager commandManager; private String flagGroupName; + private CommandFlagGroup.Builder flagGroupBuilder; protected MultiverseCommand(@NotNull MVCommandManager commandManager) { this.commandManager = commandManager; } + @PostConstruct + private void postConstruct() { + if (flagGroupBuilder != null) { + registerFlagGroup(flagGroupBuilder.build()); + flagGroupBuilder = null; + } + } + protected CommandFlagsManager getFlagsManager() { return commandManager.getFlagsManager(); } + protected CommandFlag flag(CommandFlag flag) { + if (flagGroupBuilder == null) { + flagGroupBuilder = CommandFlagGroup.builder("mv" + getClass().getSimpleName().toLowerCase()); + } + flagGroupBuilder.add(flag); + return flag; + } + protected void registerFlagGroup(@NotNull CommandFlagGroup flagGroup) { if (flagGroupName != null) { throw new IllegalStateException("Flag group already registered! (name: " + flagGroupName + ")"); } getFlagsManager().registerFlagGroup(flagGroup); flagGroupName = flagGroup.getName(); + Logging.fine("Registered flag group: " + flagGroupName); } protected @NotNull ParsedCommandFlags parseFlags(@NotNull String[] flags) { diff --git a/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/ParsedCommandFlags.java b/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/ParsedCommandFlags.java index 4f522925..be45a877 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/ParsedCommandFlags.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/ParsedCommandFlags.java @@ -29,6 +29,10 @@ public class ParsedCommandFlags flagValues.put(key, value); } + public boolean hasFlag(@NotNull CommandFlag flag) { + return hasFlag(flag.getKey()); + } + /** * Check if a flag is present. * @@ -43,6 +47,10 @@ public class ParsedCommandFlags return flagValue(key, Object.class) != null; } + public @Nullable T flagValue(@NotNull CommandFlag flag, @NotNull Class type) { + return flagValue(flag.getKey(), type); + } + /** * Get the value of a flag. * @@ -54,6 +62,10 @@ public class ParsedCommandFlags return (T) value; } + public @Nullable T flagValue(@NotNull CommandFlag flag, @NotNull T defaultValue, @NotNull Class type) { + return flagValue(flag.getKey(), defaultValue, type); + } + public @NotNull T flagValue(@Nullable String key, @NotNull T defaultValue, @NotNull Class type) { T value = flagValue(key, type); return value != null ? value : defaultValue; From 48ff8d8bd1e03fc02a4357fd84f8b5ab0e5a18f3 Mon Sep 17 00:00:00 2001 From: Zax71 Date: Sat, 9 Sep 2023 12:16:48 +0100 Subject: [PATCH 4/8] Switch to ContentDisplay API --- .../commands/GamerulesCommand.java | 77 ++++++++++--------- .../display/handlers/PagedSendHandler.java | 2 +- .../MultiverseCore/utils/MVCorei18n.java | 3 +- .../resources/multiverse-core_en.properties | 3 +- 4 files changed, 43 insertions(+), 42 deletions(-) diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java index 782ddf8d..eb263bbe 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java @@ -6,9 +6,9 @@ import co.aikar.commands.MessageType; import co.aikar.commands.annotation.CommandAlias; import co.aikar.commands.annotation.CommandCompletion; import co.aikar.commands.annotation.CommandPermission; +import co.aikar.commands.annotation.Default; import co.aikar.commands.annotation.Description; -import co.aikar.commands.annotation.Flags; -import co.aikar.commands.annotation.Single; +import co.aikar.commands.annotation.Optional; import co.aikar.commands.annotation.Subcommand; import co.aikar.commands.annotation.Syntax; import com.dumptruckman.minecraft.util.Logging; @@ -16,11 +16,14 @@ import com.onarandombox.MultiverseCore.api.MVWorld; import com.onarandombox.MultiverseCore.api.MVWorldManager; import com.onarandombox.MultiverseCore.commandtools.MVCommandManager; import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand; +import com.onarandombox.MultiverseCore.display.ContentDisplay; +import com.onarandombox.MultiverseCore.display.handlers.PagedSendHandler; +import com.onarandombox.MultiverseCore.display.parsers.MapContentProvider; import com.onarandombox.MultiverseCore.utils.MVCorei18n; import jakarta.inject.Inject; +import org.bukkit.ChatColor; import org.bukkit.GameRule; import org.bukkit.World; -import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jvnet.hk2.annotations.Service; @@ -43,35 +46,42 @@ public class GamerulesCommand extends MultiverseCommand { } @Subcommand("gamerules|rules") - @CommandPermission("multiverse.core.gamerules.list") - @CommandCompletion("@mvworlds") - @Syntax("[World]") + @CommandPermission("multiverse.core.gamerule.list") + @CommandCompletion("@mvworlds @range:1-6") + @Syntax("[world] [page]") @Description("{@@mv-core.gamerules.description}") public void onGamerulesCommand(@NotNull BukkitCommandIssuer issuer, - @Single + @Optional @Syntax("") @Description("{@@mv-core.gamerules.description.world}") - MVWorld world + MVWorld world, + + @Optional + @Default("1") + @Syntax("") + @Description("{@@mv-core.gamerules.description.page}") + int page + + ) { - if (!issuer.isPlayer() && world == null) { - issuer.sendInfo(MVCorei18n.GAMERULES_ERROR_SPECIFYWORLD); - return; - } - - // Get the players world if none is specified - if (world == null) { - Player player = issuer.getPlayer(); // Need to do it here so the command can be run from console - Logging.finer("Getting the player's current world to list gamerules for"); - world = worldManager.getMVWorld(player.getWorld()); - } - - // Finally, send the list - issuer.sendInfo(MVCorei18n.GAMERULES_TITLE, "{world}", world.getName()); - issuer.sendMessage("\n" + encodeMap(issuer, getGameRuleMap(world.getCBWorld()))); - + Logging.finer("Page is: " + page); + ContentDisplay.create() + .addContent( + new MapContentProvider<>(getGameRuleMap(world.getCBWorld())) + .withKeyColor(ChatColor.AQUA) + .withValueColor(ChatColor.WHITE) + ) + .withSendHandler( + new PagedSendHandler() + .withHeader(this.getTitle(issuer, world.getCBWorld())) + .doPagination(true) + .withLinesPerPage(8) + .withTargetPage(page) + ) + .send(issuer); } /** @@ -93,18 +103,11 @@ public class GamerulesCommand extends MultiverseCommand { return gameRuleMap; } - private String encodeMap(CommandIssuer issuer, Map inMap) { - StringBuilder stringBuilder = new StringBuilder(); - for (String key : inMap.keySet()) { - String value = inMap.get(key); - - stringBuilder.append(this.commandManager.formatMessage( - issuer, - MessageType.INFO, - MVCorei18n.GAMERULES_RULE, - "{gamerule}", key, "{value}", value)) - .append("\n"); - } - return stringBuilder.toString(); + private String getTitle(CommandIssuer issuer, World world) { + return this.commandManager.formatMessage( + issuer, + MessageType.INFO, + MVCorei18n.GAMERULES_TITLE, + "{world}", world.getName()); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/display/handlers/PagedSendHandler.java b/src/main/java/com/onarandombox/MultiverseCore/display/handlers/PagedSendHandler.java index 301e7347..03458779 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/display/handlers/PagedSendHandler.java +++ b/src/main/java/com/onarandombox/MultiverseCore/display/handlers/PagedSendHandler.java @@ -99,7 +99,7 @@ public class PagedSendHandler extends BaseSendHandler { /** * Sets whether display output should be paginated if is for console output. - * This option will be useless of {@link PagedSendHandler#paginate} is set to false. + * This option will be useless if {@link PagedSendHandler#paginate} is set to false. * * @param paginateInConsole State of doing pagination in console. * @return Same {@link PagedSendHandler} for method chaining. diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/MVCorei18n.java b/src/main/java/com/onarandombox/MultiverseCore/utils/MVCorei18n.java index f2b7ac8f..3ba4cd44 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/MVCorei18n.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/MVCorei18n.java @@ -44,10 +44,9 @@ public enum MVCorei18n implements MessageKeyProvider { // Gamerules command GAMERULES_DESCRIPTION, + GAMERULES_DESCRIPTION_PAGE, GAMERULES_DESCRIPTION_WORLD, - GAMERULES_ERROR_SPECIFYWORLD, GAMERULES_TITLE, - GAMERULES_RULE, // import command IMPORT_IMPORTING, diff --git a/src/main/resources/multiverse-core_en.properties b/src/main/resources/multiverse-core_en.properties index a72bfb44..225fca53 100644 --- a/src/main/resources/multiverse-core_en.properties +++ b/src/main/resources/multiverse-core_en.properties @@ -61,10 +61,9 @@ mv-core.gamerule.success.multiple=&aSuccessfully set {gamerule} to {value} in {c # /mv gamerules mv-core.gamerules.description=Lists gamerules for the specified world +mv-core.gamerules.description.page=The page to view mv-core.gamerules.description.world=The world to list gamerules in -mv-core.gamerules.error.specifyworld=You must specify a world from the command line mv-core.gamerules.title= --- Gamerules for {world} --- -mv-core.gamerules.rule=&l{gamerule}&f : &6{value} # /mv import mv-core.import.description=Imports an existing world folder. From ee4a8c8ec96247245d7658f22c5293dc3c3ca7a6 Mon Sep 17 00:00:00 2001 From: Zax71 Date: Sat, 9 Sep 2023 12:27:44 +0100 Subject: [PATCH 5/8] Fix (some) of the checkstyle violations --- .../commands/GamerulesCommand.java | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java index eb263bbe..3025d664 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java @@ -31,18 +31,15 @@ import java.util.HashMap; import java.util.Map; /** - * List all gamerules in your current or specified world + * List all gamerules in your current or specified world. */ @Service @CommandAlias("mv") public class GamerulesCommand extends MultiverseCommand { - private final MVWorldManager worldManager; - @Inject - public GamerulesCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) { + public GamerulesCommand(@NotNull MVCommandManager commandManager) { super(commandManager); - this.worldManager = worldManager; } @Subcommand("gamerules|rules") @@ -51,19 +48,16 @@ public class GamerulesCommand extends MultiverseCommand { @Syntax("[world] [page]") @Description("{@@mv-core.gamerules.description}") public void onGamerulesCommand(@NotNull BukkitCommandIssuer issuer, + @Optional + @Syntax("") + @Description("{@@mv-core.gamerules.description.world}") + MVWorld world, - @Optional - @Syntax("") - @Description("{@@mv-core.gamerules.description.world}") - MVWorld world, - - @Optional - @Default("1") - @Syntax("") - @Description("{@@mv-core.gamerules.description.page}") - int page - - + @Optional + @Default("1") + @Syntax("") + @Description("{@@mv-core.gamerules.description.page}") + int page ) { Logging.finer("Page is: " + page); From b70960d39c6faa17e4e40fc64c56bbbc8c1c9bf2 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Sat, 9 Sep 2023 20:02:50 +0800 Subject: [PATCH 6/8] Add javadocs to new command flag methods --- .../flags/ParsedCommandFlags.java | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/ParsedCommandFlags.java b/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/ParsedCommandFlags.java index be45a877..605237bd 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/ParsedCommandFlags.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/ParsedCommandFlags.java @@ -15,7 +15,7 @@ public class ParsedCommandFlags private final Map flagValues; - public ParsedCommandFlags() { + ParsedCommandFlags() { flagValues = new HashMap<>(); } @@ -29,6 +29,12 @@ public class ParsedCommandFlags flagValues.put(key, value); } + /** + * Check if a flag is present. + * + * @param flag The flag to check. + * @return True if the flag is present, false otherwise. + */ public boolean hasFlag(@NotNull CommandFlag flag) { return hasFlag(flag.getKey()); } @@ -43,10 +49,24 @@ public class ParsedCommandFlags return this.flagValues.containsKey(key); } + /** + * Check if a flag is present and has a value. + * + * @param key The key of the flag. + * @return True if the flag is present and has a value, false otherwise. + */ public boolean hasFlagValue(@Nullable String key) { return flagValue(key, Object.class) != null; } + /** + * Get the value of a flag. + * + * @param The type of the value. + * @param flag The flag to get the value of. + * @param type The type of the value. + * @return The value of the flag, null if flag does not exist or no value. + */ public @Nullable T flagValue(@NotNull CommandFlag flag, @NotNull Class type) { return flagValue(flag.getKey(), type); } @@ -54,7 +74,8 @@ public class ParsedCommandFlags /** * Get the value of a flag. * - * @param key The key of the flag. + * @param key The key of the flag to get the value of. + * @param type The type of the value. * @return The value of the flag, null if flag does not exist or no value. */ public @Nullable T flagValue(@Nullable String key, @NotNull Class type) { @@ -62,10 +83,27 @@ public class ParsedCommandFlags return (T) value; } - public @Nullable T flagValue(@NotNull CommandFlag flag, @NotNull T defaultValue, @NotNull Class type) { - return flagValue(flag.getKey(), defaultValue, type); + /** + * Get the value of a flag. + * + * @param The type of the value. + * @param flag The flag to get the value of. + * @param defaultValue The default value if flag does not exist or no value. + * @return The value of the flag, default value if flag does not exist or no value. + */ + public @NotNull T flagValue(@NotNull CommandValueFlag flag, @NotNull T defaultValue) { + return flagValue(flag.getKey(), defaultValue, flag.getType()); } + /** + * Get the value of a flag. + * + * @param The type of the value. + * @param key The key of the flag to get the value of. + * @param defaultValue The default value if flag does not exist or no value. + * @param type The type of the value. + * @return The value of the flag, default value if flag does not exist or no value. + */ public @NotNull T flagValue(@Nullable String key, @NotNull T defaultValue, @NotNull Class type) { T value = flagValue(key, type); return value != null ? value : defaultValue; From 95a1fddbe5891879fe78a67296613283ae24a281 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Sun, 10 Sep 2023 13:54:44 +0800 Subject: [PATCH 7/8] Fix some regression on command flag registering and completion --- .../commandtools/MVCommandCompletions.java | 8 ++++++-- .../commandtools/MultiverseCommand.java | 5 +++-- .../commandtools/flags/CommandFlag.java | 11 +++++++++++ .../commandtools/flags/CommandValueFlag.java | 2 +- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/onarandombox/MultiverseCore/commandtools/MVCommandCompletions.java b/src/main/java/com/onarandombox/MultiverseCore/commandtools/MVCommandCompletions.java index 75d8d1dd..e1e42bc6 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commandtools/MVCommandCompletions.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commandtools/MVCommandCompletions.java @@ -21,6 +21,7 @@ import com.onarandombox.MultiverseCore.api.MVWorldManager; import com.onarandombox.MultiverseCore.config.MVCoreConfig; import com.onarandombox.MultiverseCore.destination.DestinationsProvider; import com.onarandombox.MultiverseCore.destination.ParsedDestination; +import io.vavr.control.Try; import jakarta.inject.Inject; import org.bukkit.GameRule; import org.jetbrains.annotations.NotNull; @@ -95,8 +96,11 @@ public class MVCommandCompletions extends PaperCommandCompletions { } private Collection suggestFlags(@NotNull BukkitCommandCompletionContext context) { - return this.commandManager.getFlagsManager().suggest( - context.getConfig("groupName", ""), context.getContextValue(String[].class)); + String groupName = context.getConfig("groupName", ""); + + return Try.of(() -> context.getContextValue(String[].class)) + .map(flags -> commandManager.getFlagsManager().suggest(groupName, flags)) + .getOrElse(Collections.emptyList()); } private Collection suggestGamerules() { diff --git a/src/main/java/com/onarandombox/MultiverseCore/commandtools/MultiverseCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commandtools/MultiverseCommand.java index 8d8658f1..1225319f 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commandtools/MultiverseCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commandtools/MultiverseCommand.java @@ -11,7 +11,7 @@ import org.jetbrains.annotations.NotNull; import org.jvnet.hk2.annotations.Contract; @Contract -public abstract class MultiverseCommand extends BaseCommand { +public abstract class MultiverseCommand extends BaseCommand { protected final MVCommandManager commandManager; private String flagGroupName; @@ -33,11 +33,12 @@ public abstract class MultiverseCommand extends BaseCommand { return commandManager.getFlagsManager(); } - protected CommandFlag flag(CommandFlag flag) { + protected T flag(T flag) { if (flagGroupBuilder == null) { flagGroupBuilder = CommandFlagGroup.builder("mv" + getClass().getSimpleName().toLowerCase()); } flagGroupBuilder.add(flag); + Logging.finest("Registered flag: " + flag); return flag; } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/CommandFlag.java b/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/CommandFlag.java index 0604f028..a11582e0 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/CommandFlag.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/CommandFlag.java @@ -52,6 +52,17 @@ public class CommandFlag { return aliases; } + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return "Builder{" + + "key='" + key + '\'' + + ", aliases=" + aliases + + '}'; + } + /** * A builder for a flag. * diff --git a/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/CommandValueFlag.java b/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/CommandValueFlag.java index 558250ee..3c23b450 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/CommandValueFlag.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/CommandValueFlag.java @@ -191,7 +191,7 @@ public class CommandValueFlag extends CommandFlag { * @return The flag. */ @Override - public @NotNull CommandFlag build() { + public @NotNull CommandValueFlag build() { if (context == null && !String.class.equals(type)) { throw new IllegalStateException("Context is required for none-string value flags"); } From b8c10c412dffae4b86dd0fba466e3cf55f0b6a27 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Sun, 10 Sep 2023 13:56:50 +0800 Subject: [PATCH 8/8] Improve gamerules command with filter and page flag --- .../commands/GamerulesCommand.java | 79 ++++++++++++------- 1 file changed, 52 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java index 3025d664..0a18d6b3 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/GamerulesCommand.java @@ -1,22 +1,26 @@ package com.onarandombox.MultiverseCore.commands; -import co.aikar.commands.BukkitCommandIssuer; import co.aikar.commands.CommandIssuer; +import co.aikar.commands.InvalidCommandArgument; import co.aikar.commands.MessageType; import co.aikar.commands.annotation.CommandAlias; import co.aikar.commands.annotation.CommandCompletion; import co.aikar.commands.annotation.CommandPermission; -import co.aikar.commands.annotation.Default; import co.aikar.commands.annotation.Description; +import co.aikar.commands.annotation.Flags; import co.aikar.commands.annotation.Optional; import co.aikar.commands.annotation.Subcommand; import co.aikar.commands.annotation.Syntax; -import com.dumptruckman.minecraft.util.Logging; import com.onarandombox.MultiverseCore.api.MVWorld; -import com.onarandombox.MultiverseCore.api.MVWorldManager; +import com.onarandombox.MultiverseCore.commandtools.MVCommandIssuer; import com.onarandombox.MultiverseCore.commandtools.MVCommandManager; import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand; +import com.onarandombox.MultiverseCore.commandtools.flags.CommandValueFlag; +import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags; import com.onarandombox.MultiverseCore.display.ContentDisplay; +import com.onarandombox.MultiverseCore.display.filters.ContentFilter; +import com.onarandombox.MultiverseCore.display.filters.DefaultContentFilter; +import com.onarandombox.MultiverseCore.display.filters.RegexContentFilter; import com.onarandombox.MultiverseCore.display.handlers.PagedSendHandler; import com.onarandombox.MultiverseCore.display.parsers.MapContentProvider; import com.onarandombox.MultiverseCore.utils.MVCorei18n; @@ -37,50 +41,71 @@ import java.util.Map; @CommandAlias("mv") public class GamerulesCommand extends MultiverseCommand { + private final CommandValueFlag PAGE_FLAG = flag(CommandValueFlag + .builder("--page", Integer.class) + .addAlias("-p") + .context(value -> { + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + throw new InvalidCommandArgument("Invalid page number: " + value); + } + }) + .build()); + + private final CommandValueFlag FILTER_FLAG = flag(CommandValueFlag + .builder("--filter", ContentFilter.class) + .addAlias("-f") + .context(value -> { + try { + return RegexContentFilter.fromString(value); + } catch (IllegalArgumentException e) { + throw new InvalidCommandArgument("Invalid filter: " + value); + } + }) + .build()); + @Inject - public GamerulesCommand(@NotNull MVCommandManager commandManager) { + GamerulesCommand(@NotNull MVCommandManager commandManager) { super(commandManager); } @Subcommand("gamerules|rules") @CommandPermission("multiverse.core.gamerule.list") - @CommandCompletion("@mvworlds @range:1-6") - @Syntax("[world] [page]") + @CommandCompletion("@mvworlds|@flags:groupName=mvgamerulescommand @flags:groupName=mvgamerulescommand") + @Syntax("[world] [--page ] [--filter ]") @Description("{@@mv-core.gamerules.description}") - public void onGamerulesCommand(@NotNull BukkitCommandIssuer issuer, - @Optional + public void onGamerulesCommand( + @NotNull MVCommandIssuer issuer, + + @Flags("resolve=issuerAware") @Syntax("") @Description("{@@mv-core.gamerules.description.world}") MVWorld world, @Optional - @Default("1") - @Syntax("") + @Syntax("[--page ] [--filter ]") @Description("{@@mv-core.gamerules.description.page}") - int page + String[] flags ) { - Logging.finer("Page is: " + page); + ParsedCommandFlags parsedFlags = parseFlags(flags); ContentDisplay.create() - .addContent( - new MapContentProvider<>(getGameRuleMap(world.getCBWorld())) + .addContent(new MapContentProvider<>(getGameRuleMap(world.getCBWorld())) .withKeyColor(ChatColor.AQUA) - .withValueColor(ChatColor.WHITE) - ) - .withSendHandler( - new PagedSendHandler() - .withHeader(this.getTitle(issuer, world.getCBWorld())) - .doPagination(true) - .withLinesPerPage(8) - .withTargetPage(page) - ) - + .withValueColor(ChatColor.WHITE)) + .withSendHandler(new PagedSendHandler() + .withHeader(this.getTitle(issuer, world.getCBWorld())) + .doPagination(true) + .withTargetPage(parsedFlags.flagValue(PAGE_FLAG, 1)) + .withFilter(parsedFlags.flagValue(FILTER_FLAG, DefaultContentFilter.get()))) .send(issuer); } /** - * Gets all the gamerules and their values for a given world - * @param world The world to find gamerules for + * Gets all the gamerules and their values for a given world. + * + * @param world The world to find gamerules for. * @return A map of the gamerules and their values */ private Map getGameRuleMap(World world) {