From 4887564cf683bfc8629c8ac8517f737730b4e754 Mon Sep 17 00:00:00 2001 From: Zoriot Date: Fri, 9 Oct 2026 12:27:36 +0200 Subject: [PATCH 1/2] feat(navigation): add direct navigator submenu commands Register navigator destinations through the Cloud command tree so users can open explore, continent, country, state, city, warp, build, plot system, and tutorial menus directly. Add greedy, case-insensitive destination arguments with tab suggestions, and apply navigator and warp permissions at command registration. Reuse the main menu's configured actions for direct Build, Plot System, and Tutorials commands. Share state and city destination discovery with the existing state menu logic. Remove the standalone /explore command and its alias configuration so exploring is available through /navigator explore. Closes #62 --- .../common/commands/BttCommandManager.java | 4 +- .../modules/navigation/NavigationModule.java | 2 - .../navigator/commands/ExploreCommand.java | 36 ---- .../navigator/commands/NavigatorCommand.java | 167 +++++++++++++++--- .../modules/navigation/menu/MainMenu.java | 51 ++++-- .../navigation/menu/StateSelectorMenu.java | 43 +++-- .../navigation/menu/TutorialsMenu.java | 2 +- .../buildteamtools/utils/io/MainConfig.java | 1 - .../utils/io/NavigationConfig.java | 4 +- 9 files changed, 219 insertions(+), 91 deletions(-) delete mode 100644 src/main/java/net/buildtheearth/buildteamtools/modules/navigation/components/navigator/commands/ExploreCommand.java diff --git a/src/main/java/net/buildtheearth/buildteamtools/modules/common/commands/BttCommandManager.java b/src/main/java/net/buildtheearth/buildteamtools/modules/common/commands/BttCommandManager.java index c44a4f32..ac91d2a3 100644 --- a/src/main/java/net/buildtheearth/buildteamtools/modules/common/commands/BttCommandManager.java +++ b/src/main/java/net/buildtheearth/buildteamtools/modules/common/commands/BttCommandManager.java @@ -38,7 +38,7 @@ public final class BttCommandManager { private static final Set COMMAND_NAMES = Set.of( "btt", "generate", "kml", "geopoints", "geopath", "georing", "geosurface", - "navigator", "buildteam", "btwarps", "explore", "address", "warp", "blockpalette", + "navigator", "buildteam", "btwarps", "address", "warp", "blockpalette", "help", "communicators", "cache", "debug", "checkforupdates", "reload-config", "update" ); private static final ParserDescriptor ARGUMENT_PARSER = @@ -423,7 +423,6 @@ private List configuredAliases(String name) { case "navigator" -> labels.navigator(); case "buildteam" -> labels.buildteam(); case "btwarps" -> labels.btwarps(); - case "explore" -> labels.explore(); case "address" -> labels.address(); case "warp" -> labels.warp(); case "blockpalette" -> labels.blockpalette(); @@ -475,7 +474,6 @@ private static RichDescription descriptionFor(String name) { case "navigator" -> "Open the build team navigation menu."; case "buildteam" -> "Switch to a build team by name or tag."; case "btwarps" -> "Open the warp menu for a build team."; - case "explore" -> "Explore nearby build team regions."; case "address" -> "Look up the address at your current location."; case "warp" -> "Warp to a saved location."; case "blockpalette" -> "Open the block palette menu."; diff --git a/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/NavigationModule.java b/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/NavigationModule.java index 015c023c..a190f012 100644 --- a/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/NavigationModule.java +++ b/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/NavigationModule.java @@ -9,7 +9,6 @@ import net.buildtheearth.buildteamtools.modules.navigation.components.bluemap.BluemapComponent; import net.buildtheearth.buildteamtools.modules.navigation.components.navigator.NavigatorComponent; import net.buildtheearth.buildteamtools.modules.navigation.components.navigator.commands.BuildteamCommand; -import net.buildtheearth.buildteamtools.modules.navigation.components.navigator.commands.ExploreCommand; import net.buildtheearth.buildteamtools.modules.navigation.components.navigator.commands.NavigatorCommand; import net.buildtheearth.buildteamtools.modules.navigation.components.navigator.listeners.NavigatorJoinListener; import net.buildtheearth.buildteamtools.modules.navigation.components.navigator.listeners.NavigatorOpenListener; @@ -166,7 +165,6 @@ public void registerCommands() { new NavigatorCommand().register(this); new BuildteamCommand().register(this); new BtWarpsCommand().register(this); - new ExploreCommand().register(this); new AddressCommand().register(this); } diff --git a/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/components/navigator/commands/ExploreCommand.java b/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/components/navigator/commands/ExploreCommand.java deleted file mode 100644 index 26affd1e..00000000 --- a/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/components/navigator/commands/ExploreCommand.java +++ /dev/null @@ -1,36 +0,0 @@ -package net.buildtheearth.buildteamtools.modules.navigation.components.navigator.commands; - -import com.alpsbte.alpslib.utils.ChatHelper; -import net.buildtheearth.buildteamtools.modules.navigation.menu.ExploreMenu; -import net.buildtheearth.buildteamtools.BuildTeamTools; -import net.buildtheearth.buildteamtools.modules.Module; -import net.buildtheearth.buildteamtools.modules.network.model.Permissions; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jspecify.annotations.NonNull; - -/** - * Command to open the BuildTeams explore menu. - * Usage: /explore - */ -public class ExploreCommand { - public void register(Module owner) { - BuildTeamTools.getInstance().getCommandManager().registerNoArguments( - owner, "explore", Permissions.NAVIGATOR_USE, this::execute); - } - - private void execute(@NonNull CommandSender sender) { - if (!(sender instanceof Player player)) { - sender.sendMessage(ChatHelper.getErrorString("You must be a %s to %s this command!", "player", "execute")); - return; - } - - if (!player.hasPermission(Permissions.NAVIGATOR_USE)) { - player.sendMessage(ChatHelper.getErrorString("You don't have permission to use this command!")); - return; - } - - // Open the buildteams explore menu with a back reference to the main navigator - new ExploreMenu(player, true); - } -} diff --git a/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/components/navigator/commands/NavigatorCommand.java b/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/components/navigator/commands/NavigatorCommand.java index 235623f9..3e7fb590 100644 --- a/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/components/navigator/commands/NavigatorCommand.java +++ b/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/components/navigator/commands/NavigatorCommand.java @@ -1,48 +1,175 @@ package net.buildtheearth.buildteamtools.modules.navigation.components.navigator.commands; import com.alpsbte.alpslib.utils.ChatHelper; -import net.buildtheearth.buildteamtools.modules.navigation.NavigationModule; +import io.papermc.paper.command.brigadier.CommandSourceStack; import net.buildtheearth.buildteamtools.BuildTeamTools; import net.buildtheearth.buildteamtools.modules.Module; +import net.buildtheearth.buildteamtools.modules.common.commands.BttCommandManager; +import net.buildtheearth.buildteamtools.modules.navigation.NavigationModule; +import net.buildtheearth.buildteamtools.modules.navigation.components.warps.WarpsComponent; +import net.buildtheearth.buildteamtools.modules.navigation.menu.CitySelectorMenu; +import net.buildtheearth.buildteamtools.modules.navigation.menu.CountrySelectorMenu; +import net.buildtheearth.buildteamtools.modules.navigation.menu.ExploreMenu; import net.buildtheearth.buildteamtools.modules.navigation.menu.MainMenu; +import net.buildtheearth.buildteamtools.modules.navigation.menu.StateSelectorMenu; +import net.buildtheearth.buildteamtools.modules.network.NetworkModule; +import net.buildtheearth.buildteamtools.modules.network.model.BuildTeam; +import net.buildtheearth.buildteamtools.modules.network.model.Continent; import net.buildtheearth.buildteamtools.modules.network.model.Permissions; +import net.buildtheearth.buildteamtools.modules.network.model.Region; +import net.kyori.adventure.text.Component; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.incendo.cloud.Command; +import org.incendo.cloud.context.CommandContext; +import org.incendo.cloud.minecraft.extras.RichDescription; +import org.incendo.cloud.parser.standard.StringParser; +import org.incendo.cloud.permission.Permission; +import org.incendo.cloud.suggestion.SuggestionProvider; import org.jspecify.annotations.NonNull; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.function.Consumer; +import java.util.function.UnaryOperator; + public class NavigatorCommand { + private static final String CONTINENT_ARGUMENT = "continent"; + private static final String STATE_ARGUMENT = "state"; + private static final String PLAYER_ONLY_MESSAGE = "You must be a %s to %s this command!"; + public void register(Module owner) { var commandManager = BuildTeamTools.getInstance().getCommandManager(); - commandManager.registerNoArguments(owner, "navigator", Permissions.NAVIGATOR_USE, this::execute); - commandManager.registerSubcommand(owner, "navigator", "toggle", - "Toggle the navigator item on or off.", - builder -> builder.permission(Permissions.NAVIGATOR_USE), - context -> toggle(context.sender().getSender())); + commandManager.registerNoArguments(owner, "navigator", Permissions.NAVIGATOR_USE, this::openNavigator); + registerSubcommand(owner, "explore", "Open the continent selection menu.", + context -> openPlayer(context.sender().getSender(), player -> new ExploreMenu(player, true))); + registerSubcommand(owner, "countries", "Open the country selection menu for a continent.", + builder -> builder + .permission(Permissions.NAVIGATOR_USE) + .required(CONTINENT_ARGUMENT, StringParser.greedyStringParser(), + RichDescription.of(Component.text("Continent name")), + SuggestionProvider.blockingStrings((context, input) -> + BttCommandManager.matchingSuggestions(continentNames(), input.remainingInput()))), + context -> { + CommandSender sender = context.sender().getSender(); + Continent continent = parseContinent(context.get(CONTINENT_ARGUMENT)); + if (continent == null) { + sender.sendMessage(ChatHelper.getErrorString("Unknown continent. Available continents: %s", + String.join(", ", continentNames()))); + return; + } + openPlayer(sender, player -> new CountrySelectorMenu(player, continent, true)); + }); + registerSubcommand(owner, "states", "Open the USA state selection menu.", + context -> openPlayer(context.sender().getSender(), + player -> new StateSelectorMenu(player, Continent.NORTH_AMERICA, true))); + registerSubcommand(owner, "cities", "Open the city selection menu for a supported state.", + builder -> builder + .permission(Permissions.NAVIGATOR_USE) + .required(STATE_ARGUMENT, StringParser.greedyStringParser(), + RichDescription.of(Component.text("State name")), + SuggestionProvider.blockingStrings((context, input) -> + BttCommandManager.matchingSuggestions(cityStateNames(), input.remainingInput()))), + context -> { + CommandSender sender = context.sender().getSender(); + String stateName = context.get(STATE_ARGUMENT).replace('_', ' '); + Region state = StateSelectorMenu.getCityStates().stream() + .filter(region -> region.getName().equalsIgnoreCase(stateName)) + .findFirst().orElse(null); + if (state == null) { + sender.sendMessage(ChatHelper.getErrorString( + "No city menu is available for that state. Available states: %s", + String.join(", ", cityStateNames()))); + return; + } + openPlayer(sender, player -> new CitySelectorMenu( + state, StateSelectorMenu.getCityTeamsForState(state), player, true)); + }); + registerSubcommand(owner, "warps", "Open this build team's warp menu.", + builder -> builder.permission(Permission.allOf( + Permission.of(Permissions.NAVIGATOR_USE), + Permission.of(Permissions.WARP_USE))), + context -> openWarps(context.sender().getSender())); + registerSubcommand(owner, "build", "Run the configured Build menu action.", + context -> openPlayer(context.sender().getSender(), MainMenu::openBuild)); + registerSubcommand(owner, "plotsystem", "Run the configured Plot System menu action.", + context -> openPlayer(context.sender().getSender(), MainMenu::openPlotSystem)); + registerSubcommand(owner, "tutorials", "Open the tutorial menu or run its configured action.", + context -> openPlayer(context.sender().getSender(), MainMenu::openTutorials)); + registerSubcommand(owner, "toggle", "Toggle the navigator hotbar item.", + context -> openPlayer(context.sender().getSender(), + NavigationModule.getInstance().getNavigatorComponent()::toggle)); + } + + private void registerSubcommand( + Module owner, + String name, + String description, + Consumer> handler + ) { + registerSubcommand(owner, name, description, + builder -> builder.permission(Permissions.NAVIGATOR_USE), handler); } - private void execute(@NonNull CommandSender sender) { + private void registerSubcommand( + Module owner, + String name, + String description, + UnaryOperator> argumentBuilder, + Consumer> handler + ) { + BuildTeamTools.getInstance().getCommandManager().registerSubcommand( + owner, "navigator", name, description, + argumentBuilder, + handler); + } + + private void openNavigator(@NonNull CommandSender sender) { + openPlayer(sender, MainMenu::new); + } + + private void openWarps(@NonNull CommandSender sender) { if (!(sender instanceof Player player)) { - sender.sendMessage(ChatHelper.getErrorString("You must be a %s to %s this command!", "player", "execute")); + sendPlayerOnlyMessage(sender); return; } - - if (!player.hasPermission(Permissions.NAVIGATOR_USE)) { - player.sendMessage(ChatHelper.getErrorString("You don't have permission to use this command!")); + BuildTeam team = NetworkModule.getInstance().getBuildTeam(); + if (team == null || team.getWarpGroups() == null) { + player.sendMessage(ChatHelper.getErrorString("The build team's warps are currently unavailable.")); return; } - - new MainMenu(player); + WarpsComponent.openWarpMenu(player, team, new MainMenu(player, false)); } - private void toggle(@NonNull CommandSender sender) { + private void openPlayer(@NonNull CommandSender sender, Consumer action) { if (!(sender instanceof Player player)) { - sender.sendMessage(ChatHelper.getErrorString("You must be a %s to %s this command!", "player", "execute")); - return; - } - if (!player.hasPermission(Permissions.NAVIGATOR_USE)) { - player.sendMessage(ChatHelper.getErrorString("You don't have permission to use this command!")); + sendPlayerOnlyMessage(sender); return; } - NavigationModule.getInstance().getNavigatorComponent().toggle(player); + action.accept(player); + } + + private void sendPlayerOnlyMessage(@NonNull CommandSender sender) { + sender.sendMessage(ChatHelper.getErrorString(PLAYER_ONLY_MESSAGE, "player", "execute")); + } + + private static List continentNames() { + return Arrays.stream(Continent.values()) + .map(continent -> continent.name().toLowerCase(Locale.ROOT)) + .toList(); + } + + private static Continent parseContinent(String name) { + String normalized = name.replace('_', ' ').replace('-', ' '); + return Arrays.stream(Continent.values()) + .filter(continent -> continent.getLabel().equalsIgnoreCase(normalized)) + .findFirst().orElse(null); + } + + private static List cityStateNames() { + return StateSelectorMenu.getCityStates().stream() + .map(region -> region.getName().replace(' ', '_')) + .distinct().toList(); } } diff --git a/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/menu/MainMenu.java b/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/menu/MainMenu.java index 6ab01f59..87ff99a7 100644 --- a/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/menu/MainMenu.java +++ b/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/menu/MainMenu.java @@ -36,7 +36,11 @@ public class MainMenu extends AbstractMenu { private static final String INVENTORY_NAME = "BuildTheEarth Navigator"; public MainMenu(Player menuPlayer) { - super(3, INVENTORY_NAME, menuPlayer); + this(menuPlayer, true); + } + + public MainMenu(Player menuPlayer, boolean autoLoad) { + super(3, INVENTORY_NAME, menuPlayer, autoLoad); } @Override @@ -87,7 +91,7 @@ protected void setItemClickEventsAsync() { getMenu().getSlot(Objects.requireNonNull(slots.pollFirst())) .setClickHandler((clickPlayer, clickInformation) -> { clickPlayer.closeInventory(); - performClickAction(clickPlayer, config().mainMenuItems().buildItem().action().replace("&", "§"), "build"); + openBuild(clickPlayer); }); } @@ -96,7 +100,7 @@ protected void setItemClickEventsAsync() { getMenu().getSlot(Objects.requireNonNull(slots.pollFirst())) .setClickHandler((clickPlayer, clickInformation) -> { clickPlayer.closeInventory(); - performClickAction(clickPlayer, config().mainMenuItems().plotsystemItem().action().replace("&", "§"), "plotsystem"); + openPlotSystem(clickPlayer); }); } @@ -118,15 +122,7 @@ protected void setItemClickEventsAsync() { if (config().mainMenuItems().tutorialItem().enabled()) { getMenu().getSlot(Objects.requireNonNull(slots.pollFirst())).setClickHandler((clickPlayer, clickInformation) -> { clickPlayer.closeInventory(); - String action = config().mainMenuItems().tutorialItem().action(); - - // If no command or message is set, open the tutorial menu - if (action == null || action.equals("/command") || action.equals("message")) { - new TutorialsMenu(clickPlayer); - return; - } - - performClickAction(clickPlayer, action.replace("&", "§"), "tutorial"); + openTutorials(clickPlayer); }); } } @@ -189,7 +185,7 @@ protected Mask getMask() { return slots; } - private @NotNull NavigationConfig config() { + private static @NotNull NavigationConfig config() { NavigationModule navigationModule = NavigationModule.getInstance(); if (navigationModule == null) { throw new IllegalStateException("Navigation module is not initialized"); @@ -197,7 +193,34 @@ protected Mask getMask() { return navigationModule.getConfig(); } - private void performClickAction(Player p, String action, String type) { + public static void openBuild(Player player) { + openConfiguredItem(player, config().mainMenuItems().buildItem(), "build"); + } + + public static void openPlotSystem(Player player) { + openConfiguredItem(player, config().mainMenuItems().plotsystemItem(), "plotsystem"); + } + + public static void openTutorials(Player player) { + openConfiguredItem(player, config().mainMenuItems().tutorialItem(), "tutorial"); + } + + static void openConfiguredItem(Player player, NavigationConfig.MenuItem item, String type) { + if (!item.enabled()) { + player.sendMessage(ChatHelper.getErrorString("The %s item is disabled in the navigation config.", type)); + return; + } + String action = item.action(); + if (type.equals("tutorial") && (action == null || action.equals("/command") || action.equals("message"))) { + new TutorialsMenu(player); + } else if (action == null) { + player.sendMessage(ChatHelper.getErrorString("No action is set for the %s item in the config yet! Please contact an %s.", type, "admin")); + } else { + performClickAction(player, action.replace("&", "§"), type); + } + } + + private static void performClickAction(Player p, String action, String type) { // Check if an action is set in the config if (action.startsWith("transfer:")) { NavUtils.transferPlayer(p, action.substring(9)); diff --git a/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/menu/StateSelectorMenu.java b/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/menu/StateSelectorMenu.java index ca9167d5..666cd4d8 100644 --- a/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/menu/StateSelectorMenu.java +++ b/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/menu/StateSelectorMenu.java @@ -52,13 +52,15 @@ public StateSelectorMenu(Player menuPlayer, @NonNull Continent continent, boolea this.stateEntries = loadStateEntries(continent); } - private @NonNull List loadStateEntries(@NonNull Continent continent) { - List entries = new ArrayList<>(); - + private static @NonNull List loadStateEntries(@NonNull Continent continent) { NetworkModule networkModule = NetworkModule.getInstance(); - BuildTeam currentTeam = networkModule.getBuildTeam(); + return loadStateEntries(continent, networkModule.getBuildTeams(), networkModule.getBuildTeam()); + } - for (BuildTeam team : networkModule.getBuildTeams()) { + private static @NonNull List loadStateEntries( + @NonNull Continent continent, @NonNull List teams, BuildTeam currentTeam) { + List entries = new ArrayList<>(); + for (BuildTeam team : teams) { if (shouldSkipTeam(team, currentTeam)) { continue; } @@ -70,7 +72,7 @@ public StateSelectorMenu(Player menuPlayer, @NonNull Continent continent, boolea return entries; } - private boolean shouldSkipTeam(BuildTeam team, BuildTeam currentTeam) { + private static boolean shouldSkipTeam(BuildTeam team, BuildTeam currentTeam) { if (team == null || team.getID() == null) { return true; } @@ -82,7 +84,7 @@ private boolean shouldSkipTeam(BuildTeam team, BuildTeam currentTeam) { return team.getID().equals(currentTeam.getID()); } - private void addStateEntriesForTeam( + private static void addStateEntriesForTeam( @NonNull List entries, @NonNull BuildTeam team, @NonNull Continent continent @@ -96,7 +98,7 @@ private void addStateEntriesForTeam( } } - private boolean isStateInContinent(@NonNull Region region, @NonNull Continent continent) { + private static boolean isStateInContinent(@NonNull Region region, @NonNull Continent continent) { return region.getType() == RegionType.STATE && region.getContinent() == continent; } @@ -106,18 +108,35 @@ private boolean isStateInContinent(@NonNull Region region, @NonNull Continent co * Temporary workaround: city-to-state relationships are not available yet, * so New York is treated as the only state with city-level build teams. */ - private boolean hasCitiesForState(@NonNull Region stateRegion) { + private static boolean hasCitiesForState(@NonNull Region stateRegion) { return NEW_YORK_STATE_NAME.equals(stateRegion.getName()); } - private @NonNull List getCityTeamsForState(@NonNull Region stateRegion) { + public static @NonNull List getCityStates() { + NetworkModule networkModule = NetworkModule.getInstance(); + return getCityStates(networkModule.getBuildTeams(), networkModule.getBuildTeam()); + } + + static @NonNull List getCityStates(@NonNull List teams, BuildTeam currentTeam) { + return loadStateEntries(Continent.NORTH_AMERICA, teams, currentTeam).stream() + .filter(StateEntry::hasSubCities) + .map(StateEntry::stateRegion) + .toList(); + } + + public static @NonNull List getCityTeamsForState(@NonNull Region stateRegion) { + return getCityTeamsForState(stateRegion, NetworkModule.getInstance().getBuildTeams()); + } + + static @NonNull List getCityTeamsForState( + @NonNull Region stateRegion, @NonNull List teams) { if (!hasCitiesForState(stateRegion)) { return List.of(); } List cityTeams = new ArrayList<>(); - for (BuildTeam team : NetworkModule.getInstance().getBuildTeams()) { + for (BuildTeam team : teams) { if (team == null || team.getID() == null) { continue; } @@ -130,7 +149,7 @@ private boolean hasCitiesForState(@NonNull Region stateRegion) { return cityTeams; } - private boolean hasNewYorkCityRegion(@NonNull BuildTeam team) { + private static boolean hasNewYorkCityRegion(@NonNull BuildTeam team) { for (Region region : team.getRegions()) { if (region.getType() != RegionType.CITY) { continue; diff --git a/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/menu/TutorialsMenu.java b/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/menu/TutorialsMenu.java index b19977b9..e985ff66 100644 --- a/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/menu/TutorialsMenu.java +++ b/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/menu/TutorialsMenu.java @@ -23,7 +23,7 @@ public TutorialsMenu(Player player) { @Override protected void setPreviewItems() { - setBackItem(BACK_BUTTON_SLOT, new MainMenu(getMenuPlayer())); + setBackItem(BACK_BUTTON_SLOT, new MainMenu(getMenuPlayer(), false)); super.setPreviewItems(); } diff --git a/src/main/java/net/buildtheearth/buildteamtools/utils/io/MainConfig.java b/src/main/java/net/buildtheearth/buildteamtools/utils/io/MainConfig.java index 81bdb694..88f798fc 100644 --- a/src/main/java/net/buildtheearth/buildteamtools/utils/io/MainConfig.java +++ b/src/main/java/net/buildtheearth/buildteamtools/utils/io/MainConfig.java @@ -72,7 +72,6 @@ interface Labels { default List navigator() { return List.of("navigator", "nav", "navigate"); } default List buildteam() { return List.of("buildteam", "bt"); } default List btwarps() { return List.of("btwarps", "btwarp", "wbt", "wpt", "buildteamwarps"); } - default List explore() { return List.of("explore"); } default List address() { return List.of("address"); } default List warp() { return List.of("warp", "warps", "wp"); } default List blockpalette() { return List.of("blockpalette", "bp", "blocks"); } diff --git a/src/main/java/net/buildtheearth/buildteamtools/utils/io/NavigationConfig.java b/src/main/java/net/buildtheearth/buildteamtools/utils/io/NavigationConfig.java index bcd70295..513f74d6 100644 --- a/src/main/java/net/buildtheearth/buildteamtools/utils/io/NavigationConfig.java +++ b/src/main/java/net/buildtheearth/buildteamtools/utils/io/NavigationConfig.java @@ -68,10 +68,10 @@ interface MainMenuItems { } interface MenuItem { - @Comments("Enable or disable this menu item.") + @Comments("Enable or disable this menu item and its Build, PlotSystem, or Tutorials navigator shortcut.") default boolean enabled() { return false; } - @Comments("Command or action executed when this menu item is clicked.") + @Comments("Command or action executed when this menu item is clicked. Also used by the Build, PlotSystem, and Tutorials navigator shortcuts.") default String action() { return "/command"; } } From 89802d7f392a25a6e2fe0e20cf09e3c628466982 Mon Sep 17 00:00:00 2001 From: Zoriot Date: Sun, 11 Oct 2026 22:49:05 +0200 Subject: [PATCH 2/2] refactor(navigation): drop nav warps and gate item commands on config Remove /btt nav warps since /btt warp already opens the warp menu. Only register the nav build, plotsystem and tutorials subcommands when their menu item is enabled in the navigation config. Adds BuildTeamTools#getNavigationConfig so commands can read the config at registration time, before the module's own config field is set. --- .../buildteamtools/BuildTeamTools.java | 4 ++ .../navigator/commands/NavigatorCommand.java | 43 +++++++------------ 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/src/main/java/net/buildtheearth/buildteamtools/BuildTeamTools.java b/src/main/java/net/buildtheearth/buildteamtools/BuildTeamTools.java index e9314e42..153f7435 100644 --- a/src/main/java/net/buildtheearth/buildteamtools/BuildTeamTools.java +++ b/src/main/java/net/buildtheearth/buildteamtools/BuildTeamTools.java @@ -90,6 +90,10 @@ public MainConfig getMainConfig() { return mainConfigLoader.getConfig(); } + public NavigationConfig getNavigationConfig() { + return navigationConfigLoader.getConfig(); + } + @Override public void saveConfig() { } diff --git a/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/components/navigator/commands/NavigatorCommand.java b/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/components/navigator/commands/NavigatorCommand.java index 3e7fb590..9d9517ad 100644 --- a/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/components/navigator/commands/NavigatorCommand.java +++ b/src/main/java/net/buildtheearth/buildteamtools/modules/navigation/components/navigator/commands/NavigatorCommand.java @@ -6,17 +6,15 @@ import net.buildtheearth.buildteamtools.modules.Module; import net.buildtheearth.buildteamtools.modules.common.commands.BttCommandManager; import net.buildtheearth.buildteamtools.modules.navigation.NavigationModule; -import net.buildtheearth.buildteamtools.modules.navigation.components.warps.WarpsComponent; import net.buildtheearth.buildteamtools.modules.navigation.menu.CitySelectorMenu; import net.buildtheearth.buildteamtools.modules.navigation.menu.CountrySelectorMenu; import net.buildtheearth.buildteamtools.modules.navigation.menu.ExploreMenu; import net.buildtheearth.buildteamtools.modules.navigation.menu.MainMenu; import net.buildtheearth.buildteamtools.modules.navigation.menu.StateSelectorMenu; -import net.buildtheearth.buildteamtools.modules.network.NetworkModule; -import net.buildtheearth.buildteamtools.modules.network.model.BuildTeam; import net.buildtheearth.buildteamtools.modules.network.model.Continent; import net.buildtheearth.buildteamtools.modules.network.model.Permissions; import net.buildtheearth.buildteamtools.modules.network.model.Region; +import net.buildtheearth.buildteamtools.utils.io.NavigationConfig; import net.kyori.adventure.text.Component; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -24,7 +22,6 @@ import org.incendo.cloud.context.CommandContext; import org.incendo.cloud.minecraft.extras.RichDescription; import org.incendo.cloud.parser.standard.StringParser; -import org.incendo.cloud.permission.Permission; import org.incendo.cloud.suggestion.SuggestionProvider; import org.jspecify.annotations.NonNull; @@ -86,17 +83,20 @@ public void register(Module owner) { openPlayer(sender, player -> new CitySelectorMenu( state, StateSelectorMenu.getCityTeamsForState(state), player, true)); }); - registerSubcommand(owner, "warps", "Open this build team's warp menu.", - builder -> builder.permission(Permission.allOf( - Permission.of(Permissions.NAVIGATOR_USE), - Permission.of(Permissions.WARP_USE))), - context -> openWarps(context.sender().getSender())); - registerSubcommand(owner, "build", "Run the configured Build menu action.", - context -> openPlayer(context.sender().getSender(), MainMenu::openBuild)); - registerSubcommand(owner, "plotsystem", "Run the configured Plot System menu action.", - context -> openPlayer(context.sender().getSender(), MainMenu::openPlotSystem)); - registerSubcommand(owner, "tutorials", "Open the tutorial menu or run its configured action.", - context -> openPlayer(context.sender().getSender(), MainMenu::openTutorials)); + // The module constructor registers commands before its own config field is set + NavigationConfig.MainMenuItems items = BuildTeamTools.getInstance().getNavigationConfig().mainMenuItems(); + if (items.buildItem().enabled()) { + registerSubcommand(owner, "build", "Run the configured Build menu action.", + context -> openPlayer(context.sender().getSender(), MainMenu::openBuild)); + } + if (items.plotsystemItem().enabled()) { + registerSubcommand(owner, "plotsystem", "Run the configured Plot System menu action.", + context -> openPlayer(context.sender().getSender(), MainMenu::openPlotSystem)); + } + if (items.tutorialItem().enabled()) { + registerSubcommand(owner, "tutorials", "Open the tutorial menu or run its configured action.", + context -> openPlayer(context.sender().getSender(), MainMenu::openTutorials)); + } registerSubcommand(owner, "toggle", "Toggle the navigator hotbar item.", context -> openPlayer(context.sender().getSender(), NavigationModule.getInstance().getNavigatorComponent()::toggle)); @@ -129,19 +129,6 @@ private void openNavigator(@NonNull CommandSender sender) { openPlayer(sender, MainMenu::new); } - private void openWarps(@NonNull CommandSender sender) { - if (!(sender instanceof Player player)) { - sendPlayerOnlyMessage(sender); - return; - } - BuildTeam team = NetworkModule.getInstance().getBuildTeam(); - if (team == null || team.getWarpGroups() == null) { - player.sendMessage(ChatHelper.getErrorString("The build team's warps are currently unavailable.")); - return; - } - WarpsComponent.openWarpMenu(player, team, new MainMenu(player, false)); - } - private void openPlayer(@NonNull CommandSender sender, Consumer action) { if (!(sender instanceof Player player)) { sendPlayerOnlyMessage(sender);