From 8649409cbb5b1b6ef758a7c8a2d90b63d477d172 Mon Sep 17 00:00:00 2001 From: BONNe1704 Date: Mon, 18 Feb 2019 15:25:45 +0200 Subject: [PATCH] Add Single Challenges GUI. (#89) Add ability to enable Single GUI in config. Add configurable admin and player method (in config) that will open GUI with GameModes. Add ability to define default player GameMode GUI. Add new commands that will process config options. --- .../bentobox/challenges/ChallengesAddon.java | 26 +++- .../world/bentobox/challenges/Settings.java | 134 ++++++++++++++++- .../commands/ChallengesUserCommand.java | 106 ++++++++++++++ .../admin/ChallengesAdminCommand.java | 87 +++++++++++ .../challenges/panel/GameModesGUI.java | 138 ++++++++++++++++++ src/main/resources/config.yml | 26 +++- 6 files changed, 513 insertions(+), 4 deletions(-) create mode 100644 src/main/java/world/bentobox/challenges/commands/ChallengesUserCommand.java create mode 100644 src/main/java/world/bentobox/challenges/commands/admin/ChallengesAdminCommand.java create mode 100644 src/main/java/world/bentobox/challenges/panel/GameModesGUI.java 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