diff --git a/src/main/java/world/bentobox/challenges/ChallengesAddon.java b/src/main/java/world/bentobox/challenges/ChallengesAddon.java index f4089c6..c1c25d4 100644 --- a/src/main/java/world/bentobox/challenges/ChallengesAddon.java +++ b/src/main/java/world/bentobox/challenges/ChallengesAddon.java @@ -2,13 +2,18 @@ package world.bentobox.challenges; import org.bukkit.Bukkit; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; import world.bentobox.bentobox.api.addons.Addon; +import world.bentobox.bentobox.api.addons.GameModeAddon; import world.bentobox.bentobox.api.configuration.Config; import world.bentobox.bentobox.hooks.VaultHook; import world.bentobox.challenges.commands.ChallengesCommand; +import world.bentobox.challenges.commands.ChallengesUserCommand; import world.bentobox.challenges.commands.admin.Challenges; +import world.bentobox.challenges.commands.admin.ChallengesAdminCommand; import world.bentobox.challenges.listeners.ResetListener; import world.bentobox.challenges.listeners.SaveListener; import world.bentobox.level.Level; @@ -98,14 +103,18 @@ public class ChallengesAddon extends Addon { // Challenge import setup this.importManager = new ChallengesImportManager(this); + List hookedGameModes = new ArrayList<>(); + this.getPlugin().getAddonsManager().getGameModeAddons().forEach(gameModeAddon -> { if (!this.settings.getDisabledGameModes().contains(gameModeAddon.getDescription().getName())) { if (gameModeAddon.getPlayerCommand().isPresent()) { new ChallengesCommand(this, gameModeAddon.getPlayerCommand().get()); - this.hooked = true; - } + this.hooked = true; + + hookedGameModes.add(gameModeAddon); + } if (gameModeAddon.getAdminCommand().isPresent()) { @@ -116,6 +125,19 @@ public class ChallengesAddon extends Addon { }); if (this.hooked) { + + // Create general challenge commands + + if (this.settings.isUseCommonGUI()) + { + new ChallengesUserCommand(this, + this.settings.getUserCommand(), + hookedGameModes); + new ChallengesAdminCommand(this, + this.settings.getAdminCommand(), + hookedGameModes); + } + // Try to find Level addon and if it does not exist, display a warning Optional level = this.getAddonByName("Level"); diff --git a/src/main/java/world/bentobox/challenges/Settings.java b/src/main/java/world/bentobox/challenges/Settings.java index af84260..b125568 100644 --- a/src/main/java/world/bentobox/challenges/Settings.java +++ b/src/main/java/world/bentobox/challenges/Settings.java @@ -18,6 +18,37 @@ import world.bentobox.bentobox.database.objects.DataObject; @ConfigComment("") public class Settings implements DataObject { + @ConfigComment("") + @ConfigComment("Allows to define common challenges command that will open User GUI") + @ConfigComment("with all GameMode selection or Challenges from user world.") + @ConfigComment("This will not affect /{gamemode_user} challenges command.") + @ConfigEntry(path = "commands.user", needsReset = true) + private String userCommand = "challenges c"; + + @ConfigComment("") + @ConfigComment("Allows to define common challenges command that will open Admin GUI") + @ConfigComment("with all GameMode selection.") + @ConfigComment("This will not affect /{gamemode_admin} challenges command.") + @ConfigEntry(path = "commands.admin", needsReset = true) + private String adminCommand = "challengesadmin chadmin"; + + @ConfigComment("") + @ConfigComment("This enables/disables common command that will be independent from") + @ConfigComment("all GameModes. For admins it will open selection with all GameModes") + @ConfigComment("(unless there is one), but for users it will open GUI that corresponds") + @ConfigComment("to their world (unless it is specified other way in Admin GUI).") + @ConfigEntry(path = "commands.single-gui", needsReset = true) + private boolean useCommonGUI = false; + + @ConfigComment("") + @ConfigComment("This allows for admins to define which GUI will be opened for admins") + @ConfigComment("when users calls single-gui command.") + @ConfigComment("Acceptable values:") + @ConfigComment(" - CURRENT_WORLD - will open GUI that corresponds to user location.") + @ConfigComment(" - GAMEMODE_LIST - will open GUI with all installed game modes.") + @ConfigEntry(path = "commands.single-gamemode") + private GuiMode userGuiMode = GuiMode.CURRENT_WORLD; + @ConfigComment("") @ConfigComment("Reset Challenges - if this is true, player's challenges will reset when they") @ConfigComment("reset an island or if they are kicked or leave a team. Prevents exploiting the") @@ -115,7 +146,7 @@ public class Settings implements DataObject * Configuration version */ @ConfigComment("") - private String configVersion = "v1.3"; + private String configVersion = "v1.4"; // --------------------------------------------------------------------- // Section: Methods @@ -243,6 +274,46 @@ public class Settings implements DataObject } + /** + * This method returns the userCommand value. + * @return the value of userCommand. + */ + public String getUserCommand() + { + return userCommand; + } + + + /** + * This method returns the adminCommand value. + * @return the value of adminCommand. + */ + public String getAdminCommand() + { + return adminCommand; + } + + + /** + * This method returns the useCommonGUI value. + * @return the value of useCommonGUI. + */ + public boolean isUseCommonGUI() + { + return useCommonGUI; + } + + + /** + * This method sets the userGuiMode value. + * @param userGuiMode the userGuiMode new value. + */ + public void setUserGuiMode(GuiMode userGuiMode) + { + this.userGuiMode = userGuiMode; + } + + /** * This method sets the configVersion object value. * @param configVersion the configVersion object new value. @@ -362,4 +433,65 @@ public class Settings implements DataObject { this.storeHistory = storeHistory; } + + + /** + * This method sets the userCommand value. + * @param userCommand the userCommand new value. + */ + public void setUserCommand(String userCommand) + { + this.userCommand = userCommand; + } + + + /** + * This method sets the adminCommand value. + * @param adminCommand the adminCommand new value. + */ + public void setAdminCommand(String adminCommand) + { + this.adminCommand = adminCommand; + } + + + /** + * This method sets the useCommonGUI value. + * @param useCommonGUI the useCommonGUI new value. + */ + public void setUseCommonGUI(boolean useCommonGUI) + { + this.useCommonGUI = useCommonGUI; + } + + + /** + * This method returns the userGuiMode value. + * @return the value of userGuiMode. + */ + public GuiMode getUserGuiMode() + { + return userGuiMode; + } + + +// --------------------------------------------------------------------- +// Section: Enums +// --------------------------------------------------------------------- + + + /** + * This enum holds all possible values for Gui Opening for users. + */ + public enum GuiMode + { + /** + * Opens user GUI with list of all GameModes. + */ + GAMEMODE_LIST, + /** + * Opens user GUI with challenges in given world. + */ + CURRENT_WORLD + } } diff --git a/src/main/java/world/bentobox/challenges/commands/ChallengesUserCommand.java b/src/main/java/world/bentobox/challenges/commands/ChallengesUserCommand.java new file mode 100644 index 0000000..45654db --- /dev/null +++ b/src/main/java/world/bentobox/challenges/commands/ChallengesUserCommand.java @@ -0,0 +1,106 @@ +package world.bentobox.challenges.commands; + + +import java.util.List; + +import world.bentobox.bentobox.api.addons.GameModeAddon; +import world.bentobox.bentobox.api.commands.CompositeCommand; +import world.bentobox.bentobox.api.user.User; +import world.bentobox.challenges.ChallengesAddon; +import world.bentobox.challenges.Settings; +import world.bentobox.challenges.panel.GameModesGUI; + + +/** + * This class provides all necessary thing to implement challenges user command + */ +public class ChallengesUserCommand extends CompositeCommand +{ + /** + * Constructor that inits command with given string. + * @param addon Challenges Addon + * @param commands String that contains main command and its alias separated via whitespace. + * @param gameModeAddons List with GameModes where challenges addon operates. + */ + public ChallengesUserCommand(ChallengesAddon addon, String commands, List gameModeAddons) + { + super(addon, + commands.split(" ")[0], + commands.split(" ")); + this.gameModeAddons = gameModeAddons; + this.addon = addon; + } + + + /** + * {@inheritDoc} + */ + @Override + public void setup() + { + this.setOnlyPlayer(true); + this.setPermission("challenges"); + this.setParametersHelp("challenges.commands.user.parameters"); + this.setDescription("challenges.commands.user.description"); + } + + + /** + * {@inheritDoc} + */ + @Override + public boolean execute(User user, String label, List args) + { + // It is not necessary to check 0, as in that case addon will not be hooked. + + if (this.gameModeAddons.size() == 1) + { + this.gameModeAddons.get(0).getPlayerCommand().ifPresent(compositeCommand -> + user.performCommand(compositeCommand.getTopLabel() + " challenges")); + return true; + } + else if (this.addon.getChallengesSettings().getUserGuiMode() == Settings.GuiMode.CURRENT_WORLD) + { + // Find GameMode and run command + for (GameModeAddon addon : this.gameModeAddons) + { + if (addon.inWorld(user.getWorld())) + { + addon.getPlayerCommand().ifPresent(compositeCommand -> + user.performCommand(compositeCommand.getTopLabel() + " challenges")); + + return true; + } + } + } + else if (this.addon.getChallengesSettings().getUserGuiMode() == Settings.GuiMode.GAMEMODE_LIST) + { + new GameModesGUI(this.addon, + this.getWorld(), + user, + this.getTopLabel(), + this.getPermissionPrefix(), + false, + this.gameModeAddons).build(); + return true; + } + + return false; + } + + + // --------------------------------------------------------------------- + // Section: Variables + // --------------------------------------------------------------------- + + + /** + * List with hooked GameMode addons. + */ + private List gameModeAddons; + + /** + * Challenges addon for easier operations. + */ + private ChallengesAddon addon; +} diff --git a/src/main/java/world/bentobox/challenges/commands/admin/ChallengesAdminCommand.java b/src/main/java/world/bentobox/challenges/commands/admin/ChallengesAdminCommand.java new file mode 100644 index 0000000..3137d8c --- /dev/null +++ b/src/main/java/world/bentobox/challenges/commands/admin/ChallengesAdminCommand.java @@ -0,0 +1,87 @@ +package world.bentobox.challenges.commands.admin; + + +import java.util.List; + +import world.bentobox.bentobox.api.addons.GameModeAddon; +import world.bentobox.bentobox.api.commands.CompositeCommand; +import world.bentobox.bentobox.api.user.User; +import world.bentobox.challenges.ChallengesAddon; +import world.bentobox.challenges.panel.GameModesGUI; + + +/** + * This class provides all necessary thing to implement challenges admin command + */ +public class ChallengesAdminCommand extends CompositeCommand +{ + /** + * Constructor that inits command with given string. + * @param addon Challenges Addon + * @param commands String that contains main command and its alias separated via whitespace. + * @param gameModeAddons List with GameModes where challenges addon operates. + */ + public ChallengesAdminCommand(ChallengesAddon addon, String commands, List gameModeAddons) + { + super(addon, + commands.split(" ")[0], + commands.split(" ")); + this.gameModeAddons = gameModeAddons; + this.addon = addon; + } + + + /** + * {@inheritDoc} + */ + @Override + public void setup() + { + this.setPermission("admin.challenges"); + this.setParametersHelp("challenges.commands.admin.main.parameters"); + this.setDescription("challenges.commands.admin.main.description"); + } + + + /** + * {@inheritDoc} + */ + @Override + public boolean execute(User user, String label, List args) + { + // For single game mode just open correct gui. + + if (this.gameModeAddons.size() == 1) + { + this.gameModeAddons.get(0).getAdminCommand().ifPresent(compositeCommand -> + user.performCommand(compositeCommand.getTopLabel() + " challenges")); + } + else + { + new GameModesGUI(this.addon, + this.getWorld(), + user, + this.getTopLabel(), + this.getPermissionPrefix(), + true, + this.gameModeAddons).build(); + } + + return true; + } + + +// --------------------------------------------------------------------- +// Section: Variables +// --------------------------------------------------------------------- + + /** + * This variable stores challenges addon. + */ + private ChallengesAddon addon; + + /** + * This variable stores List with game modes where challenges addon are hooked in. + */ + private List gameModeAddons; +} diff --git a/src/main/java/world/bentobox/challenges/panel/GameModesGUI.java b/src/main/java/world/bentobox/challenges/panel/GameModesGUI.java new file mode 100644 index 0000000..d9acb52 --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/GameModesGUI.java @@ -0,0 +1,138 @@ +package world.bentobox.challenges.panel; + + +import org.bukkit.Material; +import org.bukkit.World; + +import java.util.List; +import java.util.Optional; + +import world.bentobox.bentobox.api.addons.GameModeAddon; +import world.bentobox.bentobox.api.commands.CompositeCommand; +import world.bentobox.bentobox.api.panels.PanelItem; +import world.bentobox.bentobox.api.panels.builders.PanelBuilder; +import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder; +import world.bentobox.bentobox.api.user.User; +import world.bentobox.challenges.ChallengesAddon; +import world.bentobox.challenges.utils.GuiUtils; + + +/** + * This class process GameModeGui opening. + */ +public class GameModesGUI extends CommonGUI +{ + /** + * {@inheritDoc} + * @param adminMode - boolean that indicate if Gui is in admin mode. + * @param gameModeAddons - List with GameModes where Challenges addon is integrated. + */ + public GameModesGUI(ChallengesAddon addon, + World world, + User user, + String topLabel, + String permissionPrefix, + boolean adminMode, + List gameModeAddons) + { + super(addon, world, user, topLabel, permissionPrefix); + this.adminMode = adminMode; + this.gameModeAddons = gameModeAddons; + } + + + @Override + public void build() + { + PanelBuilder panelBuilder = new PanelBuilder().user(this.user). + name("challenges.gui.title.game-modes"); + + GuiUtils.fillBorder(panelBuilder, this.adminMode ? + Material.BLACK_STAINED_GLASS_PANE : + Material.BLUE_STAINED_GLASS_PANE); + + int elementIndex; + + if (this.gameModeAddons.size() < 8) + { + if (this.gameModeAddons.size() == 7) + { + elementIndex = 19; + } + else + { + elementIndex = 22 - this.gameModeAddons.size() / 2; + } + } + else + { + elementIndex = 10; + } + + for (GameModeAddon gameModeAddon : this.gameModeAddons) + { + if (!panelBuilder.slotOccupied(elementIndex)) + { + panelBuilder.item(elementIndex++, this.createGameModeIcon(gameModeAddon)); + } + else + { + // Find first open slot + while (panelBuilder.slotOccupied(elementIndex)) + { + elementIndex++; + } + } + } + + panelBuilder.build(); + } + + + /** + * This method creates icon that will display given GameMode addon. + * @param gameModeAddon GameMode addon. + * @return PanelItem that acts as icon for given GameMode. + */ + private PanelItem createGameModeIcon(GameModeAddon gameModeAddon) + { + return new PanelItemBuilder(). + name(gameModeAddon.getDescription().getName()). + description(gameModeAddon.getDescription().getDescription()). + icon(Material.PAPER). + clickHandler((panel, user, clickType, slot) -> { + Optional command; + + if (this.adminMode) + { + command = gameModeAddon.getAdminCommand(); + } + else + { + command = gameModeAddon.getPlayerCommand(); + } + + command.ifPresent(compositeCommand -> + user.performCommand(compositeCommand.getTopLabel() + " challenges")); + + return true; + }). + build(); + } + + + // --------------------------------------------------------------------- + // Section: Variables + // --------------------------------------------------------------------- + + + /** + * List with game mode addons which must be showed in current GUI. + */ + private List gameModeAddons; + + /** + * Stores if current GUI is in Admin Mode or not. + */ + private boolean adminMode; +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index fcc96de..5a325c9 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -3,6 +3,30 @@ # You cannot edit it while the server is running because changes will # be lost! Use in-game settings GUI or edit when server is offline. # +commands: + # + # Allows to define common challenges command that will open User GUI + # with all GameMode selection or Challenges from user world. + # This will not affect /{gamemode_user} challenges command. + user: challenges c + # + # Allows to define common challenges command that will open Admin GUI + # with all GameMode selection. + # This will not affect /{gamemode_admin} challenges command. + admin: challengesadmin chadmin + # + # This enables/disables common command that will be independent from + # all GameModes. For admins it will open selection with all GameModes + # (unless there is one), but for users it will open GUI that corresponds + # to their world (unless it is specified other way in Admin GUI). + single-gui: false + # + # This allows for admins to define which GUI will be opened for admins + # when users calls single-gui command. + # Acceptable values: + # - CURRENT_WORLD - will open GUI that corresponds to user location. + # - GAMEMODE_LIST - will open GUI with all installed game modes. + single-gamemode: CURRENT_WORLD # # Reset Challenges - if this is true, player's challenges will reset when they # reset an island or if they are kicked or leave a team. Prevents exploiting the @@ -71,4 +95,4 @@ disabled-gamemodes: [] # uniqueId: config # -configVersion: v1.3 \ No newline at end of file +configVersion: v1.4 \ No newline at end of file