From 3ee89af5df136ee24caf82b1a5aa630b24ca3b3f Mon Sep 17 00:00:00 2001 From: BONNe Date: Sat, 18 Sep 2021 12:56:44 +0300 Subject: [PATCH] Update all admin panels. Admin panels will not contain better locales codding and easier-to-improve design. Remove old and unused GUIs. --- .../bentobox/challenges/panel/CommonGUI.java | 1150 ---------- .../challenges/panel/CommonPagedPanel.java | 183 ++ .../challenges/panel/ConversationUtils.java | 558 +++++ .../challenges/panel/GameModesGUI.java | 143 -- .../challenges/panel/admin/AdminGUI.java | 736 ------- .../challenges/panel/admin/AdminPanel.java | 549 +++++ .../panel/admin/EditChallengeGUI.java | 1752 --------------- .../panel/admin/EditChallengePanel.java | 1870 +++++++++++++++++ .../challenges/panel/admin/EditLevelGUI.java | 764 ------- .../panel/admin/EditLevelPanel.java | 876 ++++++++ .../challenges/panel/admin/EditLoreGUI.java | 638 ------ .../panel/admin/EditSettingsGUI.java | 606 ------ .../panel/admin/EditSettingsPanel.java | 576 +++++ ...engesGUI.java => ListChallengesPanel.java} | 145 +- ...istLevelsGUI.java => ListLevelsPanel.java} | 151 +- ...tLibraryGUI.java => ListLibraryPanel.java} | 241 ++- .../challenges/panel/admin/ListUsersGUI.java | 334 --- .../panel/admin/ListUsersPanel.java | 376 ++++ .../panel/admin/ManageBlocksGUI.java | 241 --- .../panel/admin/ManageBlocksPanel.java | 282 +++ .../panel/admin/ManageEntitiesGUI.java | 258 --- .../panel/admin/ManageEntitiesPanel.java | 302 +++ .../challenges/panel/user/ChallengesGUI.java | 528 ----- .../challenges/panel/user/MultipleGUI.java | 215 -- .../panel/util/ConfirmationGUI.java | 114 - .../challenges/panel/util/NumberGUI.java | 559 ----- .../challenges/panel/util/StringListGUI.java | 366 ---- .../bentobox/challenges/utils/Constants.java | 291 +++ .../bentobox/challenges/utils/GuiUtils.java | 69 +- .../bentobox/challenges/utils/Utils.java | 106 + 30 files changed, 6233 insertions(+), 8746 deletions(-) delete mode 100644 src/main/java/world/bentobox/challenges/panel/CommonGUI.java create mode 100644 src/main/java/world/bentobox/challenges/panel/CommonPagedPanel.java create mode 100644 src/main/java/world/bentobox/challenges/panel/ConversationUtils.java delete mode 100644 src/main/java/world/bentobox/challenges/panel/GameModesGUI.java delete mode 100644 src/main/java/world/bentobox/challenges/panel/admin/AdminGUI.java create mode 100644 src/main/java/world/bentobox/challenges/panel/admin/AdminPanel.java delete mode 100644 src/main/java/world/bentobox/challenges/panel/admin/EditChallengeGUI.java create mode 100644 src/main/java/world/bentobox/challenges/panel/admin/EditChallengePanel.java delete mode 100644 src/main/java/world/bentobox/challenges/panel/admin/EditLevelGUI.java create mode 100644 src/main/java/world/bentobox/challenges/panel/admin/EditLevelPanel.java delete mode 100644 src/main/java/world/bentobox/challenges/panel/admin/EditLoreGUI.java delete mode 100644 src/main/java/world/bentobox/challenges/panel/admin/EditSettingsGUI.java create mode 100644 src/main/java/world/bentobox/challenges/panel/admin/EditSettingsPanel.java rename src/main/java/world/bentobox/challenges/panel/admin/{ListChallengesGUI.java => ListChallengesPanel.java} (54%) rename src/main/java/world/bentobox/challenges/panel/admin/{ListLevelsGUI.java => ListLevelsPanel.java} (53%) rename src/main/java/world/bentobox/challenges/panel/admin/{ListLibraryGUI.java => ListLibraryPanel.java} (53%) delete mode 100644 src/main/java/world/bentobox/challenges/panel/admin/ListUsersGUI.java create mode 100644 src/main/java/world/bentobox/challenges/panel/admin/ListUsersPanel.java delete mode 100644 src/main/java/world/bentobox/challenges/panel/admin/ManageBlocksGUI.java create mode 100644 src/main/java/world/bentobox/challenges/panel/admin/ManageBlocksPanel.java delete mode 100644 src/main/java/world/bentobox/challenges/panel/admin/ManageEntitiesGUI.java create mode 100644 src/main/java/world/bentobox/challenges/panel/admin/ManageEntitiesPanel.java delete mode 100644 src/main/java/world/bentobox/challenges/panel/user/ChallengesGUI.java delete mode 100644 src/main/java/world/bentobox/challenges/panel/user/MultipleGUI.java delete mode 100644 src/main/java/world/bentobox/challenges/panel/util/ConfirmationGUI.java delete mode 100644 src/main/java/world/bentobox/challenges/panel/util/NumberGUI.java delete mode 100644 src/main/java/world/bentobox/challenges/panel/util/StringListGUI.java create mode 100644 src/main/java/world/bentobox/challenges/utils/Constants.java diff --git a/src/main/java/world/bentobox/challenges/panel/CommonGUI.java b/src/main/java/world/bentobox/challenges/panel/CommonGUI.java deleted file mode 100644 index 7e1b7d8..0000000 --- a/src/main/java/world/bentobox/challenges/panel/CommonGUI.java +++ /dev/null @@ -1,1150 +0,0 @@ -package world.bentobox.challenges.panel; - - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; - -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.conversations.Conversation; -import org.bukkit.conversations.ConversationContext; -import org.bukkit.conversations.ConversationFactory; -import org.bukkit.conversations.Prompt; -import org.bukkit.conversations.StringPrompt; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.BookMeta; -import org.bukkit.inventory.meta.EnchantmentStorageMeta; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.inventory.meta.KnowledgeBookMeta; -import org.bukkit.inventory.meta.LeatherArmorMeta; -import org.bukkit.inventory.meta.PotionMeta; -import org.bukkit.inventory.meta.SkullMeta; -import org.bukkit.inventory.meta.SpawnEggMeta; -import org.bukkit.inventory.meta.TropicalFishBucketMeta; -import org.bukkit.potion.PotionData; -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; - -import net.md_5.bungee.api.chat.ClickEvent; -import net.md_5.bungee.api.chat.TextComponent; -import world.bentobox.bentobox.BentoBox; -import world.bentobox.bentobox.api.panels.PanelItem; -import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder; -import world.bentobox.bentobox.api.user.User; -import world.bentobox.bentobox.util.Util; -import world.bentobox.challenges.ChallengesAddon; -import world.bentobox.challenges.managers.ChallengesManager; -import world.bentobox.challenges.database.object.Challenge; -import world.bentobox.challenges.database.object.ChallengeLevel; -import world.bentobox.challenges.database.object.requirements.InventoryRequirements; -import world.bentobox.challenges.database.object.requirements.IslandRequirements; -import world.bentobox.challenges.database.object.requirements.OtherRequirements; -import world.bentobox.challenges.database.object.requirements.StatisticRequirements; -import world.bentobox.challenges.utils.GuiUtils; -import world.bentobox.challenges.utils.LevelStatus; -import world.bentobox.challenges.utils.Utils; - - -/** - * This class contains common methods that will be used over all GUIs. It also allows - * easier navigation between different GUIs. - */ -public abstract class CommonGUI -{ - // --------------------------------------------------------------------- - // Section: Variables - // --------------------------------------------------------------------- - - /** - * This variable stores parent gui. - */ - protected CommonGUI parentGUI; - - /** - * Variable stores Challenges addon. - */ - protected ChallengesAddon addon; - - /** - * Variable stores world in which panel is referred to. - */ - protected World world; - - /** - * Variable stores user who created this panel. - */ - protected User user; - - /** - * Variable stores top label of command from which panel was called. - */ - protected String topLabel; - - /** - * Variable stores permission prefix of command from which panel was called. - */ - protected String permissionPrefix; - - /** - * Variable stores any value. - */ - protected Object valueObject; - - /** - * This object holds current page index. - */ - protected int pageIndex; - - /** - * This object holds PanelItem that allows to return to previous panel. - */ - protected PanelItem returnButton; - - - /** - * This enum contains buttons that is offten used in multiple GUIs. - */ - protected enum CommonButtons - { - NEXT, - PREVIOUS, - RETURN - } - - - // --------------------------------------------------------------------- - // Section: Constants - // --------------------------------------------------------------------- - - - protected static final String ADMIN = "admin"; - - protected static final String CHALLENGES = "challenges"; - - protected static final String IMPORT = "import"; - - protected static final String DEFAULT = "defaults"; - - protected static final String GENERATE = "generate"; - - protected static final String SETTINGS = "settings"; - - protected static final String DELETE = "delete"; - - protected static final String WIPE = "wipe"; - - protected static final String EDIT = "edit"; - - protected static final String ADD = "add"; - - protected static final String RESET = "reset"; - - protected static final String COMPLETE = "complete"; - - protected static final String DOWNLOAD = "download"; - - // --------------------------------------------------------------------- - // Section: Constructors - // --------------------------------------------------------------------- - - - /** - * Default constructor that inits panels with minimal requirements, without parent panel. - * - * @param addon Addon where panel operates. - * @param world World from which panel was created. - * @param user User who created panel. - * @param topLabel Command top label which creates panel (f.e. island or ai) - * @param permissionPrefix Command permission prefix (f.e. bskyblock.) - */ - public CommonGUI(ChallengesAddon addon, - World world, - User user, - String topLabel, - String permissionPrefix) - { - this(addon, world, user, topLabel, permissionPrefix, null); - } - - - /** - * Default constructor that inits panels with minimal requirements. - * - * @param addon Addon where panel operates. - * @param world World from which panel was created. - * @param user User who created panel. - * @param topLabel Command top label which creates panel (f.e. island or ai) - * @param permissionPrefix Command permission prefix (f.e. bskyblock.) - * @param parentGUI Parent panel for current panel. - */ - public CommonGUI(ChallengesAddon addon, - World world, - User user, - String topLabel, - String permissionPrefix, - CommonGUI parentGUI) - { - this.addon = addon; - this.world = world; - this.user = user; - - this.topLabel = topLabel; - this.permissionPrefix = permissionPrefix; - - this.parentGUI = parentGUI; - - this.pageIndex = 0; - - this.returnButton = new PanelItemBuilder(). - name(this.user.getTranslation("challenges.gui.buttons.return")). - icon(Material.OAK_DOOR). - clickHandler((panel, user1, clickType, i) -> { - if (this.parentGUI == null) - { - this.user.closeInventory(); - return true; - } - - this.parentGUI.build(); - return true; - }).build(); - } - - - /** - * Default constructor that inits panels with minimal requirements. - * @param parentGUI Parent panel for current panel. - */ - public CommonGUI(CommonGUI parentGUI) - { - this.addon = parentGUI.addon; - this.world = parentGUI.world; - this.user = parentGUI.user; - - this.topLabel = parentGUI.topLabel; - this.permissionPrefix = parentGUI.permissionPrefix; - - this.parentGUI = parentGUI; - - this.pageIndex = 0; - - this.returnButton = new PanelItemBuilder(). - name(this.user.getTranslation("challenges.gui.buttons.return")). - icon(Material.OAK_DOOR). - clickHandler((panel, user1, clickType, i) -> { - - if (this.parentGUI == null) - { - this.user.closeInventory(); - return true; - } - - this.parentGUI.build(); - return true; - }).build(); - } - - - // --------------------------------------------------------------------- - // Section: Common methods - // --------------------------------------------------------------------- - - - /** - * This method builds all necessary elements in GUI panel. - */ - public abstract void build(); - - - /** - * This method returns PanelItem that represents given Button. - * @param button Button that must be returned. - * @return PanelItem with requested functionality. - */ - protected PanelItem getButton(CommonButtons button) - { - ItemStack icon; - String name; - List description; - PanelItem.ClickHandler clickHandler; - - switch (button) - { - case NEXT: - { - name = this.user.getTranslation("challenges.gui.buttons.next"); - description = Collections.emptyList(); - icon = new ItemStack(Material.OAK_SIGN); - clickHandler = (panel, user, clickType, slot) -> { - this.pageIndex++; - this.build(); - return true; - }; - - break; - } - case PREVIOUS: - { - name = this.user.getTranslation("challenges.gui.buttons.previous"); - description = Collections.emptyList(); - icon = new ItemStack(Material.OAK_SIGN); - clickHandler = (panel, user, clickType, slot) -> { - this.pageIndex--; - this.build(); - return true; - }; - - break; - } - case RETURN: - return this.returnButton; - default: - return null; - } - - return new PanelItemBuilder(). - icon(icon). - name(name). - description(description). - glow(false). - clickHandler(clickHandler). - build(); - } - - - /** - * This method sets new value to ValueObject variable. - * @param value new Value of valueObject. - */ - public void setValue(Object value) - { - this.valueObject = value; - } - - - // --------------------------------------------------------------------- - // Section: Generate Challenge Description - // --------------------------------------------------------------------- - - - /** - * This method generates and returns given challenge description. It is used here to avoid multiple - * duplicates, as it would be nice to have single place where challenge could be generated. - * @param challenge Challenge which description must be generated. - * @return List of strings that will be used in challenges description. - */ - protected List generateChallengeDescription(Challenge challenge, Player user) - { - List result = new ArrayList<>(); - - // Some values to avoid overchecking. - ChallengesManager manager = this.addon.getChallengesManager(); - - final boolean isCompletedOnce = - manager.isChallengeComplete(user.getUniqueId(), world, challenge); - final long doneTimes = challenge.isRepeatable() ? - manager.getChallengeTimes(this.user, this.world, challenge) : isCompletedOnce ? 0 : 1; - - boolean isCompletedAll = isCompletedOnce && challenge.isRepeatable() && - challenge.getMaxTimes() > 0 && - doneTimes >= challenge.getMaxTimes(); - - this.addon.getChallengesSettings().getChallengeLoreMessage().forEach(messagePart -> { - switch (messagePart) - { - case LEVEL: - { - ChallengeLevel level = manager.getLevel(challenge); - - if (level == null) - { - result.add(this.user.getTranslation("challenges.errors.missing-level", - "[level]", challenge.getLevel())); - } - else - { - result.add(this.user - .getTranslation("challenges.gui.challenge-description.level", - "[level]", level.getFriendlyName())); - } - break; - } - case STATUS: - { - if (isCompletedOnce) - { - result.add(this.user - .getTranslation("challenges.gui.challenge-description.completed")); - } - break; - } - case COUNT: - { - if (challenge.isRepeatable()) - { - if (challenge.getMaxTimes() > 0) - { - if (isCompletedAll) - { - result.add(this.user.getTranslation( - "challenges.gui.challenge-description.maxed-reached", - "[donetimes]", - String.valueOf(doneTimes), - "[maxtimes]", - String.valueOf(challenge.getMaxTimes()))); - } - else - { - result.add(this.user.getTranslation( - "challenges.gui.challenge-description.completed-times-of", - "[donetimes]", - String.valueOf(doneTimes), - "[maxtimes]", - String.valueOf(challenge.getMaxTimes()))); - } - } - else - { - result.add(this.user.getTranslation( - "challenges.gui.challenge-description.completed-times", - "[donetimes]", - String.valueOf(doneTimes))); - } - } - break; - } - case DESCRIPTION: - { - result.addAll(challenge.getDescription()); - break; - } - case WARNINGS: - { - if (!isCompletedAll) - { - if (challenge.getChallengeType().equals(Challenge.ChallengeType.INVENTORY)) - { - if (challenge.getRequirements().isTakeItems()) - { - result.add(this.user.getTranslation( - "challenges.gui.challenge-description.warning-items-take")); - } - } - else if (challenge.getChallengeType().equals(Challenge.ChallengeType.ISLAND)) - { - result.add(this.user.getTranslation( - "challenges.gui.challenge-description.objects-close-by")); - - IslandRequirements requirements = challenge.getRequirements(); - - if (requirements.isRemoveEntities() && !requirements.getRequiredEntities().isEmpty()) - { - result.add(this.user.getTranslation( - "challenges.gui.challenge-description.warning-entities-kill")); - } - - if (requirements.isRemoveBlocks() && !requirements.getRequiredBlocks().isEmpty()) - { - result.add(this.user.getTranslation( - "challenges.gui.challenge-description.warning-blocks-remove")); - } - } - } - break; - } - case ENVIRONMENT: - { - // Display only if there are limited environments - - if (!isCompletedAll && - !challenge.getEnvironment().isEmpty() && - challenge.getEnvironment().size() != 3) - { - result.add(this.user.getTranslation("challenges.gui.challenge-description.environment")); - - if (challenge.getEnvironment().contains(World.Environment.NORMAL)) - { - result.add(this.user.getTranslation("challenges.gui.descriptions.normal")); - } - - if (challenge.getEnvironment().contains(World.Environment.NETHER)) - { - result.add(this.user.getTranslation("challenges.gui.descriptions.nether")); - } - - if (challenge.getEnvironment().contains(World.Environment.THE_END)) - { - result.add(this.user.getTranslation("challenges.gui.descriptions.the-end")); - } - } - break; - } - case REQUIREMENTS: - { - if (!isCompletedAll) - { - switch (challenge.getChallengeType()) - { - case INVENTORY: - result.addAll(this.getInventoryRequirements(challenge.getRequirements())); - break; - case ISLAND: - result.addAll(this.getIslandRequirements(challenge.getRequirements())); - break; - case OTHER: - result.addAll(this.getOtherRequirements(challenge.getRequirements())); - break; - case STATISTIC: - result.addAll(this.getStatisticRequirements(challenge.getRequirements())); - break; - } - } - - break; - } - case REWARD_TEXT: - { - if (isCompletedAll) - { - result.add(this.user.getTranslation("challenges.gui.challenge-description.not-repeatable")); - } - else - { - // Show a title to the rewards - result.add(this.user.getTranslation("challenges.gui.challenge-description.rewards-title")); - if (isCompletedOnce) - { - result.add(challenge.getRepeatRewardText()); - } - else - { - result.add(challenge.getRewardText()); - } - } - break; - } - case REWARD_OTHER: - { - if (!isCompletedAll) - { - result.addAll(this.getChallengeRewardOthers(challenge, isCompletedOnce)); - } - break; - } - case REWARD_ITEMS: - { - if (!isCompletedAll) - { - result.addAll(this.getChallengeRewardItems(challenge, isCompletedOnce)); - } - break; - } - case REWARD_COMMANDS: - { - if (!isCompletedAll) - { - result.addAll(this.getChallengeRewardCommands(challenge, isCompletedOnce, user)); - } - break; - } - } - }); - - result.replaceAll(x -> x.replace("[label]", this.topLabel)); - - return result; - } - - - /** - * This method returns list of strings that contains basic information about challenge rewards. - * @param challenge which reward message must be created. - * @param isCompletedOnce indicate if must use repeat rewards - * @return list of strings that contains rewards message. - */ - private List getChallengeRewardOthers(Challenge challenge, boolean isCompletedOnce) - { - double rewardMoney; - int rewardExperience; - - - if (!isCompletedOnce) - { - rewardMoney = challenge.getRewardMoney(); - rewardExperience = challenge.getRewardExperience(); - } - else - { - rewardMoney = challenge.getRepeatMoneyReward(); - rewardExperience = challenge.getRepeatExperienceReward(); - } - - List result = new ArrayList<>(); - - // Add message about reward XP - if (rewardExperience > 0) - { - result.add(this.user.getTranslation("challenges.gui.challenge-description.experience-reward", - "[value]", Integer.toString(rewardExperience))); - } - - // Add message about reward money - if (this.addon.getPlugin().getSettings().isUseEconomy() && rewardMoney > 0) - { - result.add(this.user.getTranslation("challenges.gui.challenge-description.money-reward", - "[value]", Double.toString(rewardMoney))); - } - - return result; - } - - - /** - * This method returns list of strings that contains reward items from given challenge. - * @param challenge Challenge which reward items and commands must be returned. - * @param isCompletedOnce Boolean that indicate if must use repeat rewards. - * @return List of strings that contains message from challenges. - */ - private List getChallengeRewardItems(Challenge challenge, boolean isCompletedOnce) - { - List result = new ArrayList<>(); - - List rewardItems; - - if (isCompletedOnce) - { - rewardItems = challenge.getRepeatItemReward(); - } - else - { - rewardItems = challenge.getRewardItems(); - } - - // Add message about reward items - if (!rewardItems.isEmpty()) - { - result.add(this.user.getTranslation("challenges.gui.challenge-description.reward-items")); - - Utils.groupEqualItems(rewardItems).forEach(itemStack -> - result.addAll(this.generateItemStackDescription(itemStack))); - } - - return result; - } - - - /** - * This method returns list of strings that contains reward commands from given challenge. - * @param challenge Challenge which reward items and commands must be returned. - * @param isCompletedOnce Boolean that indicate if must use repeat rewards. - * @param user Target user for command string. - * @return List of strings that contains message from challenges. - */ - private List getChallengeRewardCommands(Challenge challenge, boolean isCompletedOnce, Player user) - { - List result = new ArrayList<>(); - - List rewardCommands; - - if (isCompletedOnce) - { - rewardCommands = challenge.getRepeatRewardCommands(); - } - else - { - rewardCommands = challenge.getRewardCommands(); - } - - // Add message about reward commands - if (!rewardCommands.isEmpty()) - { - result.add(this.user.getTranslation("challenges.gui.challenge-description.reward-commands")); - - for (String command : rewardCommands) - { - result.add(this.user.getTranslation("challenges.gui.descriptions.command", - "[command]", command.replace("[player]", user.getName()).replace("[SELF]", ""))); - } - } - - return result; - } - - - /** - * This method returns list of strings that contains basic information about requirements. - * @param requirements which requirements message must be created. - * @return list of strings that contains requirements message. - */ - private List getOtherRequirements(OtherRequirements requirements) - { - List result = new ArrayList<>(); - - // Add message about required exp - if (requirements.getRequiredExperience() > 0) - { - result.add(this.user.getTranslation("challenges.gui.challenge-description.required-experience", - "[value]", Integer.toString(requirements.getRequiredExperience()))); - } - - // Add message about required money - if (this.addon.isEconomyProvided() && requirements.getRequiredMoney() > 0) - { - result.add(this.user.getTranslation("challenges.gui.challenge-description.required-money", - "[value]", Double.toString(requirements.getRequiredMoney()))); - } - - // Add message about required island level - if (this.addon.isLevelProvided() && requirements.getRequiredIslandLevel() > 0) - { - result.add(this.user.getTranslation("challenges.gui.challenge-description.required-island-level", - "[value]", Long.toString(requirements.getRequiredIslandLevel()))); - } - - return result; - } - - - /** - * This method returns list of strings that contains basic information about requirements. - * @param requirements which requirements message must be created. - * @return list of strings that contains requirements message. - */ - private List getInventoryRequirements(InventoryRequirements requirements) - { - List result = new ArrayList<>(); - - // Add message about required items - if (!requirements.getRequiredItems().isEmpty()) - { - result.add(this.user.getTranslation("challenges.gui.challenge-description.required-items")); - - Utils.groupEqualItems(requirements.getRequiredItems()).forEach(itemStack -> - result.addAll(this.generateItemStackDescription(itemStack))); - } - - return result; - } - - - /** - * This method returns list of strings that contains basic information about requirements. - * @param requirements which requirements message must be created. - * @return list of strings that contains requirements message. - */ - private List getStatisticRequirements(StatisticRequirements requirements) - { - List result = new ArrayList<>(); - - result.add(this.user.getTranslation("challenges.gui.challenge-description.required-stats", - "[stat]", GuiUtils.sanitizeInput(requirements.getStatistic().name()))); - - switch (requirements.getStatistic().getType()) - { - case ITEM -> { - result.add(this.user.getTranslation("challenges.gui.challenge-description.stat-item", - "[material]", GuiUtils.sanitizeInput(requirements.getMaterial().name()), - "[amount]", String.valueOf(requirements.getAmount()))); - } - case BLOCK -> { - result.add(this.user.getTranslation("challenges.gui.challenge-description.stat-block", - "[material]", GuiUtils.sanitizeInput(requirements.getMaterial().name()), - "[amount]", String.valueOf(requirements.getAmount()))); - } - case ENTITY -> { - result.add(this.user.getTranslation("challenges.gui.challenge-description.stat-entity", - "[entity]", GuiUtils.sanitizeInput(requirements.getEntity().name()), - "[amount]", String.valueOf(requirements.getAmount()))); - } - case UNTYPED -> { - result.add(this.user.getTranslation("challenges.gui.challenge-description.stat-amount", - "[amount]", String.valueOf(requirements.getAmount()))); - } - } - - return result; - } - - - /** - * This method returns list of strings that contains required items, entities and blocks from given challenge. - * @param challenge Challenge which requirement items, entities and blocks must be returned. - * @return List of strings that contains message from challenges. - */ - private List getIslandRequirements(IslandRequirements challenge) - { - List result = new ArrayList<>(); - - if (!challenge.getRequiredBlocks().isEmpty() || !challenge.getRequiredEntities().isEmpty()) - { - // Add required blocks - if (!challenge.getRequiredBlocks().isEmpty()) - { - result.add(this.user.getTranslation("challenges.gui.challenge-description.required-blocks")); - - for (Map.Entry entry : challenge.getRequiredBlocks().entrySet()) - { - result.add(this.user.getTranslation("challenges.gui.descriptions.block", - "[block]", Util.prettifyText(entry.getKey().name()), - "[count]", Integer.toString(entry.getValue()))); - } - } - - // Add required entities - if (!challenge.getRequiredEntities().isEmpty()) - { - result.add(this.user.getTranslation("challenges.gui.challenge-description.required-entities")); - - for (Map.Entry entry : challenge.getRequiredEntities().entrySet()) - { - result.add(this.user.getTranslation("challenges.gui.descriptions.entity", - "[entity]", Util.prettifyText(entry.getKey().name()), - "[count]", Integer.toString(entry.getValue()))); - } - } - } - - return result; - } - - - // --------------------------------------------------------------------- - // Section: Generate Level Description - // --------------------------------------------------------------------- - - - /** - * This method generates level description string. - * @param level Level which string must be generated. - * @param user User who calls generation. - * @return List with generated description. - */ - protected List generateLevelDescription(ChallengeLevel level, Player user) - { - List result = new ArrayList<>(); - - ChallengesManager manager = this.addon.getChallengesManager(); - LevelStatus status = manager.getChallengeLevelStatus(user.getUniqueId(), this.world, level); - - // Check if unlock message should appear. - boolean hasCompletedOne = status.isComplete() || status.isUnlocked() && - level.getChallenges().stream().anyMatch(challenge -> - this.addon.getChallengesManager().isChallengeComplete(user.getUniqueId(), world, challenge)); - - this.addon.getChallengesSettings().getLevelLoreMessage().forEach(messagePart -> { - switch (messagePart) - { - case LEVEL_STATUS: - { - if (status.isComplete()) - { - result.add(this.user.getTranslation("challenges.gui.level-description.completed")); - } - break; - } - case CHALLENGE_COUNT: - { - if (!status.isComplete() && status.isUnlocked()) - { - int doneChallengeCount = (int) level.getChallenges().stream(). - filter(challenge -> this.addon.getChallengesManager().isChallengeComplete(user.getUniqueId(), world, challenge)). - count(); - - result.add(this.user.getTranslation("challenges.gui.level-description.completed-challenges-of", - "[number]", Integer.toString(doneChallengeCount), - "[max]", Integer.toString(level.getChallenges().size()))); - } - - break; - } - case UNLOCK_MESSAGE: - { - if (!hasCompletedOne) - { - result.add(level.getUnlockMessage()); - } - - break; - } - case WAIVER_AMOUNT: - { - if (status.isUnlocked() && !status.isComplete()) - { - result.add(this.user.getTranslation("challenges.gui.level-description.waver-amount", - "[value]", Integer.toString(level.getWaiverAmount()))); - } - - break; - } - case LEVEL_REWARD_TEXT: - { - if (status.isUnlocked() && !status.isComplete()) - { - result.add(level.getRewardText()); - } - break; - } - case LEVEL_REWARD_OTHER: - { - if (status.isUnlocked() && !status.isComplete()) - { - if (level.getRewardExperience() > 0) - { - result.add(this.user.getTranslation("challenges.gui.level-description.experience-reward", - "[value]", Integer.toString(level.getRewardExperience()))); - } - - if (this.addon.isEconomyProvided() && level.getRewardMoney() > 0) - { - result.add(this.user.getTranslation("challenges.gui.level-description.money-reward", - "[value]", Integer.toString(level.getRewardMoney()))); - } - } - break; - } - case LEVEL_REWARD_ITEMS: - { - if (status.isUnlocked() && !status.isComplete() && !level.getRewardItems().isEmpty()) - { - result.add(this.user.getTranslation("challenges.gui.level-description.reward-items")); - - Utils.groupEqualItems(level.getRewardItems()).forEach(itemStack -> - result.addAll(this.generateItemStackDescription(itemStack))); - } - break; - } - case LEVEL_REWARD_COMMANDS: - { - if (status.isUnlocked() && !status.isComplete() && !level.getRewardCommands().isEmpty()) - { - result.add(this.user.getTranslation("challenges.gui.level-description.reward-commands")); - - for (String command : level.getRewardCommands()) - { - result.add(this.user.getTranslation("challenges.gui.descriptions.command", - "[command]", command.replace("[player]", user.getName()).replace("[SELF]", ""))); - } - } - break; - } - } - }); - - result.replaceAll(x -> x.replace("[label]", this.topLabel)); - - return result; - } - - - // --------------------------------------------------------------------- - // Section: ItemStack Description - // --------------------------------------------------------------------- - - - /** - * This method generates description for given item stack object. - * @param itemStack Object which lore must be generated - * @return List with generated description - */ - @SuppressWarnings("deprecation") - protected List generateItemStackDescription(ItemStack itemStack) - { - List result = new ArrayList<>(); - - result.add(this.user.getTranslation("challenges.gui.item-description.item", - "[item]", Util.prettifyText(itemStack.getType().name()), - "[count]", Integer.toString(itemStack.getAmount()))); - - if (itemStack.hasItemMeta()) - { - ItemMeta meta = itemStack.getItemMeta(); - - if (meta.hasDisplayName()) - { - result.add(this.user.getTranslation("challenges.gui.item-description.item-name", - "[name]", meta.getDisplayName())); - } - - if (meta.hasLore()) - { - result.add(this.user.getTranslation("challenges.gui.item-description.item-lore")); - result.addAll(meta.getLore()); - } - - if (meta instanceof BookMeta) - { - result.add(this.user.getTranslation("challenges.gui.item-description.book-meta", - "[author]", ((BookMeta) meta).getAuthor(), - "[title]", ((BookMeta) meta).getTitle())); - } - else if (meta instanceof EnchantmentStorageMeta) - { - ((EnchantmentStorageMeta) meta).getStoredEnchants().forEach(((enchantment, level) -> { - result.add(this.user.getTranslation("challenges.gui.item-description.item-enchant", - "[enchant]", enchantment.getKey().getKey(), "[level]", Integer.toString(level))); - })); - } - else if (meta instanceof KnowledgeBookMeta) - { - result.add(this.user.getTranslation("challenges.gui.item-description.recipe-count", - "[count]", Integer.toString(((KnowledgeBookMeta) meta).getRecipes().size()))); - } - else if (meta instanceof LeatherArmorMeta) - { - result.add(this.user.getTranslation("challenges.gui.item-description.armor-color", - "[color]", ((LeatherArmorMeta) meta).getColor().toString())); - } - else if (meta instanceof PotionMeta) - { - PotionData data = ((PotionMeta) meta).getBasePotionData(); - - if (data.isExtended() && data.isUpgraded()) - { - result.add(this.user.getTranslation("challenges.gui.item-description.potion-type-extended-upgraded", - "[name]", Util.prettifyText(data.getType().name()))); - } - else if (data.isUpgraded()) - { - result.add(this.user.getTranslation("challenges.gui.item-description.potion-type-upgraded", - "[name]", Util.prettifyText(data.getType().name()))); - } - else if (data.isExtended()) - { - result.add(this.user.getTranslation("challenges.gui.item-description.potion-type-extended", - "[name]", Util.prettifyText(data.getType().name()))); - } - else - { - result.add(this.user.getTranslation("challenges.gui.item-description.potion-type", - "[name]", Util.prettifyText(data.getType().name()))); - } - - if (((PotionMeta) meta).hasCustomEffects()) - { - result.add(this.user.getTranslation("challenges.gui.item-description.custom-effects")); - - ((PotionMeta) meta).getCustomEffects().forEach(potionEffect -> - result.add(this.user.getTranslation("challenges.gui.item-description.potion-effect", - "[effect]", Util.prettifyText(potionEffect.getType().getName()), - "[duration]", Integer.toString(potionEffect.getDuration()), - "[amplifier]", Integer.toString(potionEffect.getAmplifier())))); - } - } - else if (meta instanceof SkullMeta) - { - if (((SkullMeta) meta).getOwningPlayer() != null) - { - result.add(this.user.getTranslation("challenges.gui.item-description.skull-owner", - "[owner]", ((SkullMeta) meta).getOwningPlayer().getName())); - } - } - else if (meta instanceof SpawnEggMeta) - { - result.add(this.user.getTranslation("challenges.gui.item-description.egg-meta", - "[mob]", Util.prettifyText(((SpawnEggMeta) meta).getSpawnedType().name()))); - } - else if (meta instanceof TropicalFishBucketMeta) - { - if (((TropicalFishBucketMeta) meta).hasVariant()) - { - result.add(this.user.getTranslation("challenges.gui.item-description.fish-meta", - "[pattern]", Util.prettifyText(((TropicalFishBucketMeta) meta).getPattern().name()), - "[pattern-color]", Util.prettifyText(((TropicalFishBucketMeta) meta).getPatternColor().name()), - "[body-color]", Util.prettifyText(((TropicalFishBucketMeta) meta).getBodyColor().name()))); - } - } - - if (meta.hasEnchants()) - { - itemStack.getEnchantments().forEach((enchantment, level) -> { - result.add(this.user.getTranslation("challenges.gui.item-description.item-enchant", - "[enchant]", - enchantment.getKey().getKey(), - "[level]", - Integer.toString(level))); - }); - } - } - - return result; - } - - - // --------------------------------------------------------------------- - // Section: Chat Input Methods - // --------------------------------------------------------------------- - - - /** - * This method will close opened gui and writes inputText in chat. After players answers on inputText in - * chat, message will trigger consumer and gui will reopen. - * @param consumer Consumer that accepts player output text. - * @param question Message that will be displayed in chat when player triggers conversion. - * @param message Message that will be set in player text field when clicked on question. - */ - protected void getFriendlyName(Consumer consumer, @NonNull String question, @Nullable String message) - { - final User user = this.user; - - Conversation conversation = - new ConversationFactory(BentoBox.getInstance()).withFirstPrompt( - new StringPrompt() - { - /** - * @see Prompt#getPromptText(ConversationContext) - */ - @Override - public String getPromptText(ConversationContext conversationContext) - { - // Close input GUI. - user.closeInventory(); - - if (message != null) - { - // Create Edit Text message. - TextComponent component = new TextComponent(user.getTranslation("challenges.gui.descriptions.admin.click-to-edit")); - component.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, message)); - // Send question and message to player. - user.getPlayer().spigot().sendMessage(component); - } - - // There are no editable message. Just return question. - return question; - } - - - /** - * @see Prompt#acceptInput(ConversationContext, String) - */ - @Override - public Prompt acceptInput(ConversationContext conversationContext, String answer) - { - // Add answer to consumer. - consumer.accept(answer); - // End conversation - return Prompt.END_OF_CONVERSATION; - } - }). - withLocalEcho(false). - // On cancel conversation will be closed. - withEscapeSequence("cancel"). - // Use null value in consumer to detect if user has abandoned conversation. - addConversationAbandonedListener(abandonedEvent -> - { - if (!abandonedEvent.gracefulExit()) - { - consumer.accept(null); - } - }). - withPrefix(context -> user.getTranslation("challenges.gui.questions.prefix")). - buildConversation(user.getPlayer()); - - conversation.begin(); - } -} - diff --git a/src/main/java/world/bentobox/challenges/panel/CommonPagedPanel.java b/src/main/java/world/bentobox/challenges/panel/CommonPagedPanel.java new file mode 100644 index 0000000..d9f8df9 --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/CommonPagedPanel.java @@ -0,0 +1,183 @@ +// +// Created by BONNe +// Copyright - 2021 +// + + +package world.bentobox.challenges.panel; + + +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.inventory.ItemStack; +import org.eclipse.jdt.annotation.NonNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +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.Constants; + + +/** + * This panel implements common things for Paged pages. + */ +public abstract class CommonPagedPanel extends CommonPanel +{ + /** + * Instantiates a new Common paged panel. + * + * @param addon the addon + * @param user the user + * @param world the world + * @param topLabel the top label + * @param permissionPrefix the permission prefix + */ + protected CommonPagedPanel(ChallengesAddon addon, + User user, + World world, String topLabel, String permissionPrefix) + { + super(addon, user, world, topLabel, permissionPrefix); + } + + + /** + * Instantiates a new Common paged panel. + * + * @param parentPanel the parent panel + */ + protected CommonPagedPanel(@NonNull CommonPanel parentPanel) + { + super(parentPanel); + } + + + /** + * Populate elements. + * + * @param panelBuilder the panel builder + * @param objectList the object list + * @param buttonBuilder the button builder + */ + protected void populateElements(PanelBuilder panelBuilder, + List objectList, + Function buttonBuilder) + { + final int MAX_ELEMENTS = 21; + final int size = objectList.size(); + + if (this.pageIndex < 0) + { + this.pageIndex = size / MAX_ELEMENTS; + } + else if (this.pageIndex > (size / MAX_ELEMENTS)) + { + this.pageIndex = 0; + } + + int objectIndex = MAX_ELEMENTS * this.pageIndex; + + // I want first row to be only for navigation and return button. + int index = 10; + + while (objectIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) && + objectIndex < size && + index < 36) + { + if (!panelBuilder.slotOccupied(index)) + { + panelBuilder.item(index, buttonBuilder.apply(objectList.get(objectIndex++))); + } + + index++; + } + + if (size > MAX_ELEMENTS && !(1.0 * size / MAX_ELEMENTS <= this.pageIndex + 1)) + { + panelBuilder.item(26, this.getButton(CommonButtons.NEXT)); + + } + + if (this.pageIndex > 0) + { + panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS)); + } + } + + + /** + * This method returns PanelItem that represents given Button. + * @param button Button that must be returned. + * @return PanelItem with requested functionality. + */ + protected PanelItem getButton(CommonButtons button) + { + final String reference = Constants.BUTTON + button.name().toLowerCase() + "."; + + final String name = this.user.getTranslation(reference + "name"); + final List description = new ArrayList<>(3); + + ItemStack icon; + PanelItem.ClickHandler clickHandler; + + if (button == CommonButtons.NEXT) + { + description.add(this.user.getTranslation(reference + "description", + Constants.NUMBER, String.valueOf(this.pageIndex + 2))); + + icon = new ItemStack(Material.OAK_SIGN, this.pageIndex + 2); + clickHandler = (panel, user, clickType, slot) -> + { + this.pageIndex++; + this.build(); + return true; + }; + } + else if (button == CommonButtons.PREVIOUS) + { + description.add(this.user.getTranslation(reference + "description", + Constants.NUMBER, String.valueOf(this.pageIndex))); + + icon = new ItemStack(Material.OAK_SIGN, Math.max(1, this.pageIndex)); + clickHandler = (panel, user, clickType, slot) -> + { + this.pageIndex--; + this.build(); + return true; + }; + } + else + { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + clickHandler(clickHandler). + build(); + } + + + /** + * Next and Previous Buttons. + */ + private enum CommonButtons + { + NEXT, + PREVIOUS + } + + + /** + * Current page index. + */ + private int pageIndex; +} diff --git a/src/main/java/world/bentobox/challenges/panel/ConversationUtils.java b/src/main/java/world/bentobox/challenges/panel/ConversationUtils.java new file mode 100644 index 0000000..4b481f2 --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/ConversationUtils.java @@ -0,0 +1,558 @@ +// +// Created by BONNe +// Copyright - 2020 +// + + +package world.bentobox.challenges.panel; + + +import org.apache.commons.lang.ArrayUtils; +import org.bukkit.ChatColor; +import org.bukkit.conversations.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; + +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.api.user.User; +import world.bentobox.challenges.utils.Constants; +import world.bentobox.challenges.utils.Utils; + + +public class ConversationUtils +{ + // --------------------------------------------------------------------- + // Section: Conversation API implementation + // --------------------------------------------------------------------- + + + /** + * This method will close opened gui and writes question in chat. After players answers on question in chat, message + * will trigger consumer and gui will reopen. Success and fail messages can be implemented like that, as user's chat + * options are disabled while it is in conversation. + * + * @param consumer Consumer that accepts player output text. + * @param question Message that will be displayed in chat when player triggers conversion. + * @param successMessage Message that will be displayed on successful operation. + * @param user User who is targeted with current confirmation. + */ + public static void createConfirmation(Consumer consumer, + User user, + @NotNull String question, + @Nullable String successMessage) + { + ValidatingPrompt confirmationPrompt = new ValidatingPrompt() + { + /** + * Is input valid boolean. + * + * @param context the context + * @param input the input + * @return the boolean + */ + @Override + protected boolean isInputValid(@NotNull ConversationContext context, @NotNull String input) + { + // Get valid strings from translations + String validEntry = user.getTranslation(Constants.CONVERSATIONS + "confirm-string") + + "," + user.getTranslation(Constants.CONVERSATIONS + "deny-string") + + "," + user.getTranslation(Constants.CONVERSATIONS + "exit-string") + + "," + user.getTranslation(Constants.CONVERSATIONS + "cancel-string"); + + // Split and check if they exist in valid entries. + String[] accepted = validEntry.toLowerCase().replaceAll("\\s", "").split(","); + return ArrayUtils.contains(accepted, input.toLowerCase()); + } + + + /** + * Accept validated input prompt. + * + * @param context the context + * @param input the input + * @return the prompt + */ + @Override + @Nullable + protected Prompt acceptValidatedInput(@NotNull ConversationContext context, @NotNull String input) + { + String validEntry = user.getTranslation(Constants.CONVERSATIONS + "confirm-string").toLowerCase(); + + if (ArrayUtils.contains(validEntry.replaceAll("\\s", "").split(","), input.toLowerCase())) + { + // Add answer to consumer. + consumer.accept(true); + // Return message about success. + return ConversationUtils.endMessagePrompt(successMessage); + } + else + { + // Add answer to consumer. + consumer.accept(false); + + // Return message about failed operation. + return ConversationUtils.endMessagePrompt( + user.getTranslation(Constants.CONVERSATIONS + "cancelled")); + } + } + + + /** + * @see Prompt#getPromptText(ConversationContext) + */ + @Override + public @NotNull String getPromptText(@NotNull ConversationContext conversationContext) + { + // Close input GUI. + user.closeInventory(); + // There are no editable message. Just return question. + return question; + } + }; + + new ConversationFactory(BentoBox.getInstance()). + withPrefix(context -> user.getTranslation(Constants.CONVERSATIONS + "prefix")). + withFirstPrompt(confirmationPrompt). + withLocalEcho(false). + withTimeout(90). + buildConversation(user.getPlayer()). + begin(); + } + + + /** + * This method will close opened gui and writes question in chat. After players answers on question in chat, message + * will trigger consumer and gui will reopen. Be aware, consumer does not return (and validate) sanitized value, + * while sanitization is done in failure for better informing. Proper implementation would be with adding new + * consumer for failure message. + * + * @param consumer Consumer that accepts player output text. + * @param validation Function that validates if input value is acceptable. + * @param question Message that will be displayed in chat when player triggers conversion. + * @param failTranslationLocation Message that will be displayed on failed operation. + * @param user User who is targeted with current confirmation. + */ + public static void createIDStringInput(Consumer consumer, + Function validation, + User user, + @NotNull String question, + @Nullable String successMessage, + @Nullable String failTranslationLocation) + { + ValidatingPrompt validatingPrompt = new ValidatingPrompt() + { + /** + * Gets the text to display to the user when + * this prompt is first presented. + * + * @param context Context information about the + * conversation. + * @return The text to display. + */ + @Override + public String getPromptText(ConversationContext context) + { + // Close input GUI. + user.closeInventory(); + + // There are no editable message. Just return question. + return question; + } + + + /** + * Override this method to check the validity of + * the player's input. + * + * @param context Context information about the + * conversation. + * @param input The player's raw console input. + * @return True or false depending on the + * validity of the input. + */ + @Override + protected boolean isInputValid(ConversationContext context, String input) + { + return validation.apply(input); + } + + + /** + * Optionally override this method to + * display an additional message if the + * user enters an invalid input. + * + * @param context Context information + * about the conversation. + * @param invalidInput The invalid input + * provided by the user. + * @return A message explaining how to + * correct the input. + */ + @Override + protected String getFailedValidationText(ConversationContext context, + String invalidInput) + { + return user.getTranslation(failTranslationLocation, + Constants.ID, + Utils.sanitizeInput(invalidInput)); + } + + + /** + * Override this method to accept and processes + * the validated input from the user. Using the + * input, the next Prompt in the prompt graph + * should be returned. + * + * @param context Context information about the + * conversation. + * @param input The validated input text from + * the user. + * @return The next Prompt in the prompt graph. + */ + @Override + protected Prompt acceptValidatedInput(ConversationContext context, String input) + { + // Add answer to consumer. + consumer.accept(input); + // Send message that it is accepted. + return ConversationUtils.endMessagePrompt(successMessage); + } + }; + + new ConversationFactory(BentoBox.getInstance()). + withPrefix(context -> user.getTranslation(Constants.CONVERSATIONS + "prefix")). + withFirstPrompt(validatingPrompt). + withLocalEcho(false). + withTimeout(90). + // On cancel conversation will be closed. + withEscapeSequence(user.getTranslation(Constants.CONVERSATIONS + "cancel-string")). + // Use null value in consumer to detect if user has abandoned conversation. + addConversationAbandonedListener(ConversationUtils.getAbandonListener(consumer, user)). + buildConversation(user.getPlayer()). + begin(); + } + + + /** + * This method will close opened gui and writes inputText in chat. After players answers on inputText in chat, + * message will trigger consumer and gui will reopen. + * + * @param consumer Consumer that accepts player output text. + * @param question Message that will be displayed in chat when player triggers conversion. + */ + public static void createNumericInput(Consumer consumer, + @NotNull User user, + @NotNull String question, + Number minValue, + Number maxValue) + { + // Create NumericPromt instance that will validate and process input. + NumericPrompt numberPrompt = new NumericPrompt() + { + /** + * Override this method to perform some action + * with the user's integer response. + * + * @param context Context information about the + * conversation. + * @param input The user's response as a {@link + * Number}. + * @return The next {@link Prompt} in the prompt + * graph. + */ + @Override + protected Prompt acceptValidatedInput(ConversationContext context, Number input) + { + // Add answer to consumer. + consumer.accept(input); + // End conversation + return Prompt.END_OF_CONVERSATION; + } + + + /** + * Override this method to do further validation on the numeric player + * input after the input has been determined to actually be a number. + * + * @param context Context information about the conversation. + * @param input The number the player provided. + * @return The validity of the player's input. + */ + @Override + protected boolean isNumberValid(ConversationContext context, Number input) + { + return input.doubleValue() >= minValue.doubleValue() && + input.doubleValue() <= maxValue.doubleValue(); + } + + + /** + * Optionally override this method to display an additional message if the + * user enters an invalid number. + * + * @param context Context information about the conversation. + * @param invalidInput The invalid input provided by the user. + * @return A message explaining how to correct the input. + */ + @Override + protected String getInputNotNumericText(ConversationContext context, String invalidInput) + { + return user.getTranslation(Constants.CONVERSATIONS + "numeric-only", Constants.VALUE, invalidInput); + } + + + /** + * Optionally override this method to display an additional message if the + * user enters an invalid numeric input. + * + * @param context Context information about the conversation. + * @param invalidInput The invalid input provided by the user. + * @return A message explaining how to correct the input. + */ + @Override + protected String getFailedValidationText(ConversationContext context, Number invalidInput) + { + return user.getTranslation(Constants.CONVERSATIONS + "not-valid-value", + Constants.VALUE, invalidInput.toString(), + Constants.MIN, Double.toString(minValue.doubleValue()), + Constants.MAX, Double.toString(maxValue.doubleValue())); + } + + + /** + * @see Prompt#getPromptText(ConversationContext) + */ + @Override + public String getPromptText(ConversationContext conversationContext) + { + // Close input GUI. + user.closeInventory(); + // There are no editable message. Just return question. + return question; + } + }; + + // Init conversation api. + new ConversationFactory(BentoBox.getInstance()). + withPrefix(context -> user.getTranslation(Constants.CONVERSATIONS + "prefix")). + withFirstPrompt(numberPrompt). + withLocalEcho(false). + withTimeout(90). + withEscapeSequence(user.getTranslation(Constants.CONVERSATIONS + "cancel-string")). + // Use null value in consumer to detect if user has abandoned conversation. + addConversationAbandonedListener(ConversationUtils.getAbandonListener(consumer, user)). + buildConversation(user.getPlayer()). + begin(); + } + + + /** + * This method will close opened gui and writes question in chat. After players answers on question in chat, message + * will trigger consumer and gui will reopen. Be aware, consumer does not return (and validate) sanitized value, + * while sanitization is done in failure for better informing. Proper implementation would be with adding new + * consumer for failure message. + * + * @param consumer Consumer that accepts player output text. + * @param question Message that will be displayed in chat when player triggers conversion. + * @param user User who is targeted with current confirmation. + */ + public static void createStringListInput(Consumer> consumer, + User user, + @NotNull String question, + @NotNull String successMessage) + { + final String SESSION_CONSTANT = Constants.CONVERSATIONS + user.getUniqueId(); + + // Successful message about completing. + MessagePrompt messagePrompt = new MessagePrompt() + { + @Override + public @NotNull String getPromptText(@NotNull ConversationContext context) + { + List description = (List) context.getSessionData(SESSION_CONSTANT); + + if (description != null) + { + consumer.accept(description); + return successMessage; + } + else + { + return user.getTranslation(Constants.CONVERSATIONS + "cancelled"); + } + } + + + @Override + protected @Nullable Prompt getNextPrompt(@NotNull ConversationContext context) + { + return Prompt.END_OF_CONVERSATION; + } + }; + + // Text input message. + StringPrompt stringPrompt = new StringPrompt() + { + @Override + public @NotNull String getPromptText(@NotNull ConversationContext context) + { + user.closeInventory(); + + if (context.getSessionData(SESSION_CONSTANT) != null) + { + StringBuilder sb = new StringBuilder(); + sb.append(user.getTranslation(Constants.CONVERSATIONS + "written-text")); + sb.append(System.getProperty("line.separator")); + + for (String line : ((List) context.getSessionData(SESSION_CONSTANT))) + { + sb.append(line); + sb.append(System.getProperty("line.separator")); + } + + return sb.toString(); + } + + return question; + } + + + @Override + public @Nullable Prompt acceptInput(@NotNull ConversationContext context, @Nullable String input) + { + String[] exit = user.getTranslation(Constants.CONVERSATIONS + "exit-string"). + toLowerCase().replaceAll("\\s", ""). + split(","); + + if (input != null && ArrayUtils.contains(exit, input.toLowerCase())) + { + return messagePrompt; + } + + List desc = new ArrayList<>(); + + if (context.getSessionData(SESSION_CONSTANT) != null) + { + desc = ((List) context.getSessionData(SESSION_CONSTANT)); + } + if (input != null) { + desc.add(ChatColor.translateAlternateColorCodes('&', input)); + } + context.setSessionData(SESSION_CONSTANT, desc); + return this; + } + }; + + new ConversationFactory(BentoBox.getInstance()). + withPrefix(context -> user.getTranslation(Constants.CONVERSATIONS + "prefix")). + withFirstPrompt(stringPrompt). + withModality(true). + withLocalEcho(false). + withTimeout(90). + withEscapeSequence(user.getTranslation(Constants.CONVERSATIONS + "cancel-string")). + addConversationAbandonedListener(ConversationUtils.getAbandonListener(consumer, user)). + buildConversation(user.getPlayer()). + begin(); + } + + + /** + * This method will close opened gui and writes question in chat. After players answers on question in chat, message + * will trigger consumer and gui will reopen. + * + * @param consumer Consumer that accepts player output text. + * @param question Message that will be displayed in chat when player triggers conversion. + * @param user User who is targeted with current confirmation. + */ + public static void createStringInput(Consumer consumer, + User user, + @NotNull String question, + @Nullable String successMessage) + { + // Text input message. + StringPrompt stringPrompt = new StringPrompt() + { + @Override + public @NotNull String getPromptText(@NotNull ConversationContext context) + { + user.closeInventory(); + return question; + } + + + @Override + public @NotNull Prompt acceptInput(@NotNull ConversationContext context, @Nullable String input) + { + consumer.accept(input); + return ConversationUtils.endMessagePrompt(successMessage); + } + }; + + new ConversationFactory(BentoBox.getInstance()). + withPrefix(context -> user.getTranslation(Constants.CONVERSATIONS + "prefix")). + withFirstPrompt(stringPrompt). + // On cancel conversation will be closed. + withLocalEcho(false). + withTimeout(90). + withEscapeSequence(user.getTranslation(Constants.CONVERSATIONS + "cancel-string")). + // Use null value in consumer to detect if user has abandoned conversation. + addConversationAbandonedListener(ConversationUtils.getAbandonListener(consumer, user)). + buildConversation(user.getPlayer()). + begin(); + } + + + /** + * This is just a simple end message prompt that displays requested message. + * + * @param message Message that will be displayed. + * @return MessagePrompt that displays given message and exists from conversation. + */ + private static MessagePrompt endMessagePrompt(@Nullable String message) + { + return new MessagePrompt() + { + @Override + public @NotNull String getPromptText(@NotNull ConversationContext context) + { + return message == null ? "" : message; + } + + + @Override + protected @Nullable Prompt getNextPrompt(@NotNull ConversationContext context) + { + return Prompt.END_OF_CONVERSATION; + } + }; + } + + + /** + * This method creates and returns abandon listener for every conversation. + * + * @param consumer Consumer which must return null value. + * @param user User who was using conversation. + * @return ConversationAbandonedListener instance. + */ + private static ConversationAbandonedListener getAbandonListener(Consumer consumer, User user) + { + return abandonedEvent -> + { + if (!abandonedEvent.gracefulExit()) + { + consumer.accept(null); + // send cancell message + abandonedEvent.getContext().getForWhom().sendRawMessage( + user.getTranslation(Constants.CONVERSATIONS + "prefix") + + user.getTranslation(Constants.CONVERSATIONS + "cancelled")); + } + }; + } +} diff --git a/src/main/java/world/bentobox/challenges/panel/GameModesGUI.java b/src/main/java/world/bentobox/challenges/panel/GameModesGUI.java deleted file mode 100644 index d60e7a4..0000000 --- a/src/main/java/world/bentobox/challenges/panel/GameModesGUI.java +++ /dev/null @@ -1,143 +0,0 @@ -package world.bentobox.challenges.panel; - - -import java.util.List; -import java.util.Optional; - -import org.bukkit.Material; -import org.bukkit.World; - -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 -{ - /** - * @param adminMode - boolean that indicate if Gui is in admin mode. - * @param gameModeAddons - List with GameModes where Challenges addon is integrated. - * @param addon Addon where panel operates. - * @param world World from which panel was created. - * @param user User who created panel. - * @param topLabel Command top label which creates panel (f.e. island or ai) - * @param permissionPrefix Command permission prefix (f.e. bskyblock.) - - */ - 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/java/world/bentobox/challenges/panel/admin/AdminGUI.java b/src/main/java/world/bentobox/challenges/panel/admin/AdminGUI.java deleted file mode 100644 index 216d6f1..0000000 --- a/src/main/java/world/bentobox/challenges/panel/admin/AdminGUI.java +++ /dev/null @@ -1,736 +0,0 @@ -package world.bentobox.challenges.panel.admin; - - -import java.util.Locale; -import java.util.function.Consumer; -import java.util.function.Function; - -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.conversations.*; -import org.bukkit.inventory.ItemStack; -import org.eclipse.jdt.annotation.NonNull; - -import world.bentobox.bentobox.BentoBox; -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.panel.CommonGUI; -import world.bentobox.challenges.panel.util.ChallengeTypeGUI; -import world.bentobox.challenges.panel.util.ConfirmationGUI; -import world.bentobox.challenges.utils.GuiUtils; -import world.bentobox.challenges.utils.Utils; -import world.bentobox.challenges.web.WebManager; - - -/** - * This class contains Main - */ -public class AdminGUI extends CommonGUI -{ - // --------------------------------------------------------------------- - // Section: Variables - // --------------------------------------------------------------------- - - /** - * This boolean holds if import should overwrite existing challenges. - */ - private boolean overwriteMode; - - /** - * This indicate if Reset Challenges must work as reset all. - */ - private boolean resetAllMode; - - /** - * This indicate if wipe button should clear all data, or only challenges. - */ - private boolean wipeAll; - - - // --------------------------------------------------------------------- - // Section: Enums - // --------------------------------------------------------------------- - - - /** - * This enum contains all button variations. Just for cleaner code. - */ - private enum Button - { - COMPLETE_USER_CHALLENGES, - RESET_USER_CHALLENGES, - ADD_CHALLENGE, - ADD_LEVEL, - EDIT_CHALLENGE, - EDIT_LEVEL, - DELETE_CHALLENGE, - DELETE_LEVEL, - EDIT_SETTINGS, - DEFAULT_IMPORT_CHALLENGES, - DEFAULT_EXPORT_CHALLENGES, - /** - * Allows to remove whole database - */ - COMPLETE_WIPE, - /** - * Allows to remove only challenges and levels - */ - CHALLENGE_WIPE, - /** - * Allows to remove only players data - */ - USER_WIPE, - /** - * Allows to access Web Library - */ - LIBRARY - } - - - // --------------------------------------------------------------------- - // Section: Constructor - // --------------------------------------------------------------------- - - /** - * @param addon Addon where panel operates. - * @param world World from which panel was created. - * @param user User who created panel. - * @param topLabel Command top label which creates panel (f.e. island or ai) - * @param permissionPrefix Command permission prefix (f.e. bskyblock.) - */ - public AdminGUI(ChallengesAddon addon, - World world, - User user, - String topLabel, - String permissionPrefix) - { - super(addon, world, user, topLabel, permissionPrefix); - } - - - // --------------------------------------------------------------------- - // Section: Methods - // --------------------------------------------------------------------- - - - /** - * {@inheritDoc} - */ - @Override - public void build() - { - PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name( - this.user.getTranslation("challenges.gui.title.admin.gui-title")); - - GuiUtils.fillBorder(panelBuilder); - - panelBuilder.item(10, this.createButton(Button.COMPLETE_USER_CHALLENGES)); - panelBuilder.item(19, this.createButton(Button.RESET_USER_CHALLENGES)); - - // Add All Player Data removal. - panelBuilder.item(28, this.createButton(Button.USER_WIPE)); - - // Add Challenges - panelBuilder.item(12, this.createButton(Button.ADD_CHALLENGE)); - panelBuilder.item(13, this.createButton(Button.ADD_LEVEL)); - - // Edit Challenges - panelBuilder.item(21, this.createButton(Button.EDIT_CHALLENGE)); - panelBuilder.item(22, this.createButton(Button.EDIT_LEVEL)); - - // Remove Challenges - panelBuilder.item(30, this.createButton(Button.DELETE_CHALLENGE)); - panelBuilder.item(31, this.createButton(Button.DELETE_LEVEL)); - - - // Import Challenges - panelBuilder.item(15, this.createButton(Button.DEFAULT_IMPORT_CHALLENGES)); - panelBuilder.item(24, this.createButton(Button.LIBRARY)); - - // Not added as I do not think admins should use it. It still will be able via command. - // panelBuilder.item(33, this.createButton(Button.DEFAULT_EXPORT_CHALLENGES)); - - // Edit Addon Settings - panelBuilder.item(16, this.createButton(Button.EDIT_SETTINGS)); - - // Button that deletes everything from challenges addon - - if (this.wipeAll) - { - panelBuilder.item(34, this.createButton(Button.COMPLETE_WIPE)); - } - else - { - panelBuilder.item(34, this.createButton(Button.CHALLENGE_WIPE)); - } - - panelBuilder.item(44, this.returnButton); - - panelBuilder.build(); - } - - - /** - * This method is used to create PanelItem for each button type. - * @param button Button which must be created. - * @return PanelItem with necessary functionality. - */ - private PanelItem createButton(Button button) - { - ItemStack icon; - String name; - String description; - boolean glow; - PanelItem.ClickHandler clickHandler; - - String permissionSuffix; - - switch (button) - { - case COMPLETE_USER_CHALLENGES: - permissionSuffix = COMPLETE; - - name = this.user.getTranslation("challenges.gui.buttons.admin.complete"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.complete"); - icon = new ItemStack(Material.WRITTEN_BOOK); - clickHandler = (panel, user, clickType, slot) -> { - new ListUsersGUI(this.addon, - this.world, - this.user, - ListUsersGUI.Mode.COMPLETE, - this.topLabel, - this.permissionPrefix, - this).build(); - - return true; - }; - glow = false; - - break; - case RESET_USER_CHALLENGES: - permissionSuffix = RESET; - - name = this.user.getTranslation("challenges.gui.buttons.admin.reset"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.reset"); - icon = new ItemStack(Material.WRITABLE_BOOK); - - glow = this.resetAllMode; - - clickHandler = (panel, user, clickType, slot) -> { - if (clickType.isRightClick()) - { - this.resetAllMode = !this.resetAllMode; - this.build(); - } - else - { - new ListUsersGUI(this.addon, - this.world, - this.user, - this.resetAllMode ? ListUsersGUI.Mode.RESET_ALL : ListUsersGUI.Mode.RESET, - this.topLabel, - this.permissionPrefix, - this).build(); - } - - return true; - }; - - break; - case ADD_CHALLENGE: - permissionSuffix = ADD; - - name = this.user.getTranslation("challenges.gui.buttons.admin.create-challenge"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.create-challenge"); - icon = new ItemStack(Material.BOOK); - clickHandler = (panel, user, clickType, slot) -> { - - this.getNewUniqueID(challenge -> - { - if (challenge == null) - { - // Build Admin Gui if input is null. - this.build(); - } - else - { - String uniqueId = Utils.getGameMode(this.world) + "_" + challenge; - - ChallengeTypeGUI.open(user, - this.addon.getChallengesSettings().getLoreLineLength(), - (type, requirements) -> new EditChallengeGUI(this.addon, - this.world, - this.user, - this.addon.getChallengesManager().createChallenge(uniqueId, type, requirements), - this.topLabel, - this.permissionPrefix, - this).build()); - } - }, - input -> { - String uniqueId = Utils.getGameMode(this.world) + "_" + input; - return !this.addon.getChallengesManager().containsChallenge(uniqueId); - }, - this.user.getTranslation("challenges.gui.questions.admin.unique-id") - ); - - return true; - }; - glow = false; - - break; - case ADD_LEVEL: - permissionSuffix = ADD; - - name = this.user.getTranslation("challenges.gui.buttons.admin.create-level"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.create-level"); - icon = new ItemStack(Material.BOOK); - clickHandler = (panel, user, clickType, slot) -> { - - this.getNewUniqueID(level -> - { - if (level == null) - { - // Build Admin Gui if input is null. - this.build(); - } - else - { - String newName = Utils.getGameMode(this.world) + "_" + level; - - new EditLevelGUI(this.addon, - this.world, - this.user, - this.addon.getChallengesManager().createLevel(newName, this.world), - this.topLabel, - this.permissionPrefix, - this).build(); - } - }, - input -> { - String newName = Utils.getGameMode(this.world) + "_" + input; - return !this.addon.getChallengesManager().containsLevel(newName); - }, - this.user.getTranslation("challenges.gui.questions.admin.unique-id") - ); - - return true; - }; - glow = false; - - break; - case EDIT_CHALLENGE: - permissionSuffix = EDIT; - - name = this.user.getTranslation("challenges.gui.buttons.admin.edit-challenge"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.edit-challenge"); - icon = new ItemStack(Material.ANVIL); - clickHandler = (panel, user, clickType, slot) -> { - new ListChallengesGUI(this.addon, - this.world, - this.user, - ListChallengesGUI.Mode.EDIT, - this.topLabel, - this.permissionPrefix, - this).build(); - - return true; - }; - glow = false; - - break; - case EDIT_LEVEL: - { - permissionSuffix = EDIT; - - name = this.user.getTranslation("challenges.gui.buttons.admin.edit-level"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.edit-level"); - icon = new ItemStack(Material.ANVIL); - clickHandler = (panel, user, clickType, slot) -> { - new ListLevelsGUI(this.addon, - this.world, - this.user, - ListLevelsGUI.Mode.EDIT, - this.topLabel, - this.permissionPrefix, - this).build(); - - return true; - }; - glow = false; - - break; - } - case DELETE_CHALLENGE: - { - permissionSuffix = DELETE; - - name = this.user.getTranslation("challenges.gui.buttons.admin.delete-challenge"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.delete-challenge"); - icon = new ItemStack(Material.LAVA_BUCKET); - clickHandler = (panel, user, clickType, slot) -> { - new ListChallengesGUI(this.addon, - this.world, - this.user, - ListChallengesGUI.Mode.DELETE, - this.topLabel, - this.permissionPrefix, - this).build(); - - return true; - }; - glow = false; - - break; - } - case DELETE_LEVEL: - { - permissionSuffix = DELETE; - - name = this.user.getTranslation("challenges.gui.buttons.admin.delete-level"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.delete-level"); - icon = new ItemStack(Material.LAVA_BUCKET); - clickHandler = (panel, user, clickType, slot) -> { - new ListLevelsGUI(this.addon, - this.world, - this.user, - ListLevelsGUI.Mode.DELETE, - this.topLabel, - this.permissionPrefix, - this).build(); - - return true; - }; - glow = false; - - break; - } - case DEFAULT_IMPORT_CHALLENGES: - { - permissionSuffix = DEFAULT; - - name = this.user.getTranslation("challenges.gui.buttons.admin.default-import"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.default-import"); - icon = new ItemStack(Material.HOPPER); - clickHandler = (panel, user, clickType, slot) -> { - // Run import command. - this.user.performCommand(this.topLabel + " " + CHALLENGES + " " + DEFAULT + " " + IMPORT); - - return true; - }; - glow = false; - - break; - } - case DEFAULT_EXPORT_CHALLENGES: - { - permissionSuffix = DEFAULT; - - name = this.user.getTranslation("challenges.gui.buttons.admin.default-export"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.default-export"); - icon = new ItemStack(Material.HOPPER); - clickHandler = (panel, user, clickType, slot) -> { - if (clickType.isRightClick()) - { - this.overwriteMode = !this.overwriteMode; - this.build(); - } - else - { - // Run import command. - this.user.performCommand(this.topLabel + " " + CHALLENGES + " " + DEFAULT + " " + GENERATE + - (this.overwriteMode ? " overwrite" : "")); - } - return true; - }; - glow = this.overwriteMode; - - break; - } - case EDIT_SETTINGS: - { - permissionSuffix = SETTINGS; - - name = this.user.getTranslation("challenges.gui.buttons.admin.settings"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.settings"); - icon = new ItemStack(Material.CRAFTING_TABLE); - clickHandler = (panel, user, clickType, slot) -> { - new EditSettingsGUI(this.addon, - this.world, - this.user, - this.topLabel, - this.permissionPrefix, - this).build(); - - return true; - }; - glow = false; - - break; - } - case COMPLETE_WIPE: - { - permissionSuffix = WIPE; - - name = this.user.getTranslation("challenges.gui.buttons.admin.complete-wipe"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.complete-wipe"); - icon = new ItemStack(Material.TNT); - clickHandler = (panel, user, clickType, slot) -> { - - if (clickType.isRightClick()) - { - this.wipeAll = false; - this.build(); - } - else - { - new ConfirmationGUI(this.user, value -> { - if (value) - { - this.addon.getChallengesManager().wipeDatabase(false); - this.user.sendMessage("challenges.messages.admin.complete-wipe"); - } - - this.build(); - }); - } - - return true; - }; - glow = true; - - break; - } - case CHALLENGE_WIPE: - { - permissionSuffix = WIPE; - - name = this.user.getTranslation("challenges.gui.buttons.admin.challenge-wipe"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.challenge-wipe"); - icon = new ItemStack(Material.TNT); - clickHandler = (panel, user, clickType, slot) -> { - - if (clickType.isRightClick()) - { - this.wipeAll = true; - this.build(); - } - else - { - new ConfirmationGUI(this.user, value -> { - if (value) - { - this.addon.getChallengesManager().wipeDatabase(false); - this.user.sendMessage("challenges.messages.admin.challenge-wipe"); - } - - this.build(); - }); - } - - return true; - }; - glow = false; - - break; - } - case USER_WIPE: - { - permissionSuffix = WIPE; - - name = this.user.getTranslation("challenges.gui.buttons.admin.players-wipe"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.players-wipe"); - icon = new ItemStack(Material.TNT); - clickHandler = (panel, user, clickType, slot) -> { - - new ConfirmationGUI(this.user, value -> { - if (value) - { - this.addon.getChallengesManager().wipePlayers(); - this.user.sendMessage("challenges.messages.admin.players-wipe"); - } - - this.build(); - }); - - return true; - }; - glow = false; - - break; - } - case LIBRARY: - { - permissionSuffix = DOWNLOAD; - - name = this.user.getTranslation("challenges.gui.buttons.admin.library"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.library"); - - if (WebManager.isEnabled()) - { - icon = new ItemStack(Material.COBWEB); - } - else - { - description += "|" + this.user.getTranslation("challenges.gui.descriptions.admin.download-disabled"); - icon = new ItemStack(Material.STRUCTURE_VOID); - } - - clickHandler = (panel, user, clickType, slot) -> { - if (WebManager.isEnabled()) - { - ListLibraryGUI.open(this); - } - - return true; - }; - glow = false; - - break; - } - default: - // This should never happen. - return null; - } - - // If user does not have permission to run command, then change icon and clickHandler. - final String actionPermission = this.permissionPrefix + ADMIN + "." + CHALLENGES + "." + permissionSuffix; - - if (!this.user.hasPermission(actionPermission)) - { - icon = new ItemStack(Material.BARRIER); - clickHandler = (panel, user, clickType, slot) -> { - this.user.sendMessage("general.errors.no-permission", "[permission]", actionPermission); - return true; - }; - } - - return new PanelItemBuilder(). - icon(icon). - name(name). - description(GuiUtils.stringSplit(description, this.addon.getChallengesSettings().getLoreLineLength())). - glow(glow). - clickHandler(clickHandler). - build(); - } - - -// --------------------------------------------------------------------- -// Section: Conversation -// --------------------------------------------------------------------- - - - /** - * This method will close opened gui and writes inputText in chat. After players answers on - * inputText in chat, message will trigger consumer and gui will reopen. - * @param consumer Consumer that accepts player output text. - * @param question Message that will be displayed in chat when player triggers conversion. - */ - private void getNewUniqueID(Consumer consumer, - Function stringValidation, - @NonNull String question) - { - final User user = this.user; - - Conversation conversation = - new ConversationFactory(BentoBox.getInstance()).withFirstPrompt( - new ValidatingPrompt() - { - - /** - * Gets the text to display to the user when - * this prompt is first presented. - * - * @param context Context information about the - * conversation. - * @return The text to display. - */ - @Override - public String getPromptText(ConversationContext context) - { - // Close input GUI. - user.closeInventory(); - - // There are no editable message. Just return question. - return question; - } - - - /** - * Override this method to check the validity of - * the player's input. - * - * @param context Context information about the - * conversation. - * @param input The player's raw console input. - * @return True or false depending on the - * validity of the input. - */ - @Override - protected boolean isInputValid(ConversationContext context, String input) - { - return stringValidation.apply(GuiUtils.sanitizeInput(input)); - } - - - /** - * Optionally override this method to - * display an additional message if the - * user enters an invalid input. - * - * @param context Context information - * about the conversation. - * @param invalidInput The invalid input - * provided by the user. - * @return A message explaining how to - * correct the input. - */ - @Override - protected String getFailedValidationText(ConversationContext context, - String invalidInput) - { - return user.getTranslation("challenges.errors.unique-id", "[id]", GuiUtils.sanitizeInput(invalidInput)); - } - - - /** - * Override this method to accept and processes - * the validated input from the user. Using the - * input, the next Prompt in the prompt graph - * should be returned. - * - * @param context Context information about the - * conversation. - * @param input The validated input text from - * the user. - * @return The next Prompt in the prompt graph. - */ - @Override - protected Prompt acceptValidatedInput(ConversationContext context, String input) - { - // Add answer to consumer. - consumer.accept(GuiUtils.sanitizeInput(input)); - // End conversation - return Prompt.END_OF_CONVERSATION; - } - }). - // On cancel conversation will be closed. - withEscapeSequence("cancel"). - // Use null value in consumer to detect if user has abandoned conversation. - addConversationAbandonedListener(abandonedEvent -> - { - if (!abandonedEvent.gracefulExit()) - { - consumer.accept(null); - } - }). - withLocalEcho(false). - withPrefix(context -> user.getTranslation("challenges.gui.questions.prefix")). - buildConversation(user.getPlayer()); - - conversation.begin(); - } -} \ No newline at end of file diff --git a/src/main/java/world/bentobox/challenges/panel/admin/AdminPanel.java b/src/main/java/world/bentobox/challenges/panel/admin/AdminPanel.java new file mode 100644 index 0000000..b80277b --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/admin/AdminPanel.java @@ -0,0 +1,549 @@ +package world.bentobox.challenges.panel.admin; + + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; + +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.inventory.ItemStack; + +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.panel.CommonPanel; +import world.bentobox.challenges.panel.ConversationUtils; +import world.bentobox.challenges.panel.util.ChallengeTypeSelector; +import world.bentobox.challenges.utils.Constants; +import world.bentobox.challenges.utils.GuiUtils; +import world.bentobox.challenges.utils.Utils; +import world.bentobox.challenges.web.WebManager; + + +/** + * This class contains Main + */ +public class AdminPanel extends CommonPanel +{ + // --------------------------------------------------------------------- + // Section: Constructor + // --------------------------------------------------------------------- + + /** + * @param addon Addon where panel operates. + * @param world World from which panel was created. + * @param user User who created panel. + * @param topLabel Command top label which creates panel (f.e. island or ai) + * @param permissionPrefix Command permission prefix (f.e. bskyblock.) + */ + private AdminPanel(ChallengesAddon addon, + World world, + User user, + String topLabel, + String permissionPrefix) + { + super(addon, user, world, topLabel, permissionPrefix); + } + + + /** + * Open the Challenges Admin GUI. + * + * @param addon the addon + * @param world the world + * @param user the user + * @param topLabel the top label + * @param permissionPrefix the permission prefix + */ + public static void open(ChallengesAddon addon, + World world, + User user, + String topLabel, + String permissionPrefix) + { + new AdminPanel(addon, world, user, topLabel, permissionPrefix).build(); + } + + + // --------------------------------------------------------------------- + // Section: Methods + // --------------------------------------------------------------------- + + + /** + * {@inheritDoc} + */ + @Override + protected void build() + { + PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name( + this.user.getTranslation(Constants.TITLE + "admin-gui")); + + GuiUtils.fillBorder(panelBuilder); + + panelBuilder.item(10, this.createButton(Button.COMPLETE_USER_CHALLENGES)); + panelBuilder.item(19, this.createButton(Button.RESET_USER_CHALLENGES)); + + // Add All Player Data removal. + panelBuilder.item(28, this.createButton(Button.USER_WIPE)); + + // Add Challenges + panelBuilder.item(12, this.createButton(Button.ADD_CHALLENGE)); + panelBuilder.item(13, this.createButton(Button.ADD_LEVEL)); + + // Edit Challenges + panelBuilder.item(21, this.createButton(Button.EDIT_CHALLENGE)); + panelBuilder.item(22, this.createButton(Button.EDIT_LEVEL)); + + // Remove Challenges + panelBuilder.item(30, this.createButton(Button.DELETE_CHALLENGE)); + panelBuilder.item(31, this.createButton(Button.DELETE_LEVEL)); + + // Import Challenges + panelBuilder.item(15, this.createButton(Button.IMPORT_CHALLENGES)); + panelBuilder.item(24, this.createButton(Button.LIBRARY)); + + // Not added as I do not think admins should use it. It still will be able via command. + // panelBuilder.item(33, this.createButton(Button.DEFAULT_EXPORT_CHALLENGES)); + + // Edit Addon Settings + panelBuilder.item(16, this.createButton(Button.EDIT_SETTINGS)); + + // Button that deletes everything from challenges addon + + if (this.wipeAll) + { + panelBuilder.item(34, this.createButton(Button.COMPLETE_WIPE)); + } + else + { + panelBuilder.item(34, this.createButton(Button.CHALLENGE_WIPE)); + } + + panelBuilder.item(44, this.returnButton); + + panelBuilder.build(); + } + + + /** + * This method is used to create PanelItem for each button type. + * @param button Button which must be created. + * @return PanelItem with necessary functionality. + */ + private PanelItem createButton(Button button) + { + final String name = this.user.getTranslation(Constants.BUTTON + button.name().toLowerCase() + ".name"); + List description = new ArrayList<>(3); + description.add(this.user.getTranslation(Constants.BUTTON + button.name().toLowerCase() + ".description")); + + ItemStack icon; + boolean glow; + PanelItem.ClickHandler clickHandler; + + + switch (button) + { + case COMPLETE_USER_CHALLENGES -> { + icon = new ItemStack(Material.WRITTEN_BOOK); + clickHandler = (panel, user, clickType, slot) -> { + ListUsersPanel.open(this, ListUsersPanel.Mode.COMPLETE); + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-open")); + } + case RESET_USER_CHALLENGES -> { + icon = new ItemStack(Material.WRITABLE_BOOK); + clickHandler = (panel, user, clickType, slot) -> { + if (clickType.isRightClick()) + { + this.resetAllMode = !this.resetAllMode; + this.build(); + } + else + { + ListUsersPanel.open(this, + this.resetAllMode ? ListUsersPanel.Mode.RESET_ALL : ListUsersPanel.Mode.RESET); + } + + return true; + }; + glow = this.resetAllMode; + + description.add(""); + description.add(this.user.getTranslationOrNothing(Constants.TIPS + "left-click-to-open")); + description.add(this.user.getTranslationOrNothing(Constants.TIPS + "right-click-to-reset-all")); + } + case ADD_CHALLENGE -> { + icon = new ItemStack(Material.BOOK); + clickHandler = (panel, user, clickType, slot) -> { + + String gameModePrefix = Utils.getGameMode(this.world).toLowerCase() + "_"; + + // This consumer process new bundle creating with a name and id from given + // consumer value.. + Consumer challengeIdConsumer = value -> { + if (value != null) + { + ChallengeTypeSelector.open(this.user, + (type, requirements) -> EditChallengePanel.open(this, + this.addon.getChallengesManager().createChallenge( + gameModePrefix + Utils.sanitizeInput(value), + value, + type, + requirements))); + } + else + { + // Operation is canceled. Open this panel again. + this.build(); + } + }; + + // This function checks if generator with a given ID already exist. + Function validationFunction = uniqueId -> + !this.addon.getChallengesManager().containsChallenge(gameModePrefix + Utils.sanitizeInput(uniqueId)); + + // Call a conversation API to get input string. + ConversationUtils.createIDStringInput(challengeIdConsumer, + validationFunction, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "write-name"), + this.user.getTranslation(Constants.CONVERSATIONS + "new-object-created", + Constants.WORLD, this.world.getName()), + Constants.CONVERSATIONS + "object-already-exists"); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-create")); + } + case ADD_LEVEL -> { + icon = new ItemStack(Material.BOOK); + clickHandler = (panel, user, clickType, slot) -> { + + String gameModePrefix = Utils.getGameMode(this.world).toLowerCase() + "_"; + + // This consumer process new bundle creating with a name and id from given + // consumer value.. + Consumer levelIdConsumer = value -> { + if (value != null) + { + EditLevelPanel.open(this, + this.addon.getChallengesManager().createLevel( + gameModePrefix + Utils.sanitizeInput(value), + value, + world)); + } + else + { + // Operation is canceled. Open this panel again. + this.build(); + } + }; + + // This function checks if generator with a given ID already exist. + Function validationFunction = uniqueId -> + !this.addon.getChallengesManager().containsLevel(gameModePrefix + Utils.sanitizeInput(uniqueId)); + + // Call a conversation API to get input string. + ConversationUtils.createIDStringInput(levelIdConsumer, + validationFunction, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "write-name"), + this.user.getTranslation(Constants.CONVERSATIONS + "new-object-created", + Constants.GAMEMODE, Utils.getGameMode(this.world)), + Constants.CONVERSATIONS + "object-already-exists"); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-create")); + } + case EDIT_CHALLENGE -> { + icon = new ItemStack(Material.ANVIL); + clickHandler = (panel, user, clickType, slot) -> { + ListChallengesPanel.open(this, ListChallengesPanel.Mode.EDIT); + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-open")); + } + case EDIT_LEVEL -> { + icon = new ItemStack(Material.ANVIL); + clickHandler = (panel, user, clickType, slot) -> { + ListLevelsPanel.open(this, ListLevelsPanel.Mode.EDIT); + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-open")); + } + case DELETE_CHALLENGE -> { + icon = new ItemStack(Material.LAVA_BUCKET); + clickHandler = (panel, user, clickType, slot) -> { + ListChallengesPanel.open(this, ListChallengesPanel.Mode.DELETE); + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-open")); + } + case DELETE_LEVEL -> { + icon = new ItemStack(Material.LAVA_BUCKET); + clickHandler = (panel, user, clickType, slot) -> { + ListLevelsPanel.open(this, ListLevelsPanel.Mode.DELETE); + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-open")); + } + case EDIT_SETTINGS -> { + icon = new ItemStack(Material.CRAFTING_TABLE); + clickHandler = (panel, user, clickType, slot) -> { + EditSettingsPanel.open(this); + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-open")); + } + case IMPORT_CHALLENGES -> { + icon = new ItemStack(Material.HOPPER); + clickHandler = (panel, user, clickType, slot) -> { + // TODO: Importing GUI. + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-open")); + } + case EXPORT_CHALLENGES -> { + icon = new ItemStack(Material.HOPPER); + clickHandler = (panel, user, clickType, slot) -> { + // TODO: Exporting GUI. + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-export")); + } + case LIBRARY -> { + if (WebManager.isEnabled()) + { + icon = new ItemStack(Material.COBWEB); + } + else + { + icon = new ItemStack(Material.STRUCTURE_VOID); + } + + clickHandler = (panel, user, clickType, slot) -> { + if (WebManager.isEnabled()) + { + ListLibraryPanel.open(this); + } + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-open")); + } + case COMPLETE_WIPE -> { + icon = new ItemStack(Material.TNT); + clickHandler = (panel, user, clickType, slot) -> { + + if (clickType.isRightClick()) + { + this.wipeAll = false; + this.build(); + } + else + { + Consumer consumer = value -> { + if (value) + { + this.addon.getChallengesManager().wipeDatabase(this.wipeAll); + } + + this.build(); + }; + + // Create conversation that gets user acceptance to delete generator data. + ConversationUtils.createConfirmation( + consumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "confirm-all-data-deletion", + Constants.GAMEMODE, Utils.getGameMode(this.world)), + this.user.getTranslation(Constants.CONVERSATIONS + "all-data-removed", + Constants.GAMEMODE, Utils.getGameMode(this.world))); + } + + return true; + }; + glow = true; + + description.add(""); + description.add(this.user.getTranslationOrNothing(Constants.TIPS + "left-click-to-wipe")); + description.add(this.user.getTranslationOrNothing(Constants.TIPS + "right-click-to-switch")); + } + case CHALLENGE_WIPE -> { + icon = new ItemStack(Material.TNT); + clickHandler = (panel, user, clickType, slot) -> { + + if (clickType.isRightClick()) + { + this.wipeAll = true; + this.build(); + } + else + { + Consumer consumer = value -> { + if (value) + { + this.addon.getChallengesManager().wipeDatabase(this.wipeAll); + } + + this.build(); + }; + + // Create conversation that gets user acceptance to delete generator data. + ConversationUtils.createConfirmation( + consumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "confirm-challenge-data-deletion", + Constants.GAMEMODE, Utils.getGameMode(this.world)), + this.user.getTranslation(Constants.CONVERSATIONS + "challenge-data-removed", + Constants.GAMEMODE, Utils.getGameMode(this.world))); + } + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslationOrNothing(Constants.TIPS + "left-click-to-wipe")); + description.add(this.user.getTranslationOrNothing(Constants.TIPS + "right-click-to-switch")); + } + case USER_WIPE -> { + icon = new ItemStack(Material.TNT); + clickHandler = (panel, user, clickType, slot) -> { + + Consumer consumer = value -> { + if (value) + { + this.addon.getChallengesManager().wipePlayers(); + } + + this.build(); + }; + + // Create conversation that gets user acceptance to delete generator data. + ConversationUtils.createConfirmation( + consumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "confirm-user-data-deletion", + Constants.GAMEMODE, Utils.getGameMode(this.world)), + this.user.getTranslation(Constants.CONVERSATIONS + "user-data-removed", + Constants.GAMEMODE, Utils.getGameMode(this.world))); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-wipe")); + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + glow = false; + } + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + glow(glow). + clickHandler(clickHandler). + build(); + } + + + // --------------------------------------------------------------------- + // Section: Enums + // --------------------------------------------------------------------- + + + /** + * This enum contains all button variations. Just for cleaner code. + */ + private enum Button + { + COMPLETE_USER_CHALLENGES, + RESET_USER_CHALLENGES, + ADD_CHALLENGE, + ADD_LEVEL, + EDIT_CHALLENGE, + EDIT_LEVEL, + DELETE_CHALLENGE, + DELETE_LEVEL, + EDIT_SETTINGS, + IMPORT_CHALLENGES, + EXPORT_CHALLENGES, + /** + * Allows to remove whole database + */ + COMPLETE_WIPE, + /** + * Allows to remove only challenges and levels + */ + CHALLENGE_WIPE, + /** + * Allows to remove only players data + */ + USER_WIPE, + /** + * Allows to access Web Library + */ + LIBRARY + } + + + // --------------------------------------------------------------------- + // Section: Variables + // --------------------------------------------------------------------- + + /** + * This indicate if Reset Challenges must work as reset all. + */ + private boolean resetAllMode; + + /** + * This indicate if wipe button should clear all data, or only challenges. + */ + private boolean wipeAll; +} \ No newline at end of file diff --git a/src/main/java/world/bentobox/challenges/panel/admin/EditChallengeGUI.java b/src/main/java/world/bentobox/challenges/panel/admin/EditChallengeGUI.java deleted file mode 100644 index c6f4663..0000000 --- a/src/main/java/world/bentobox/challenges/panel/admin/EditChallengeGUI.java +++ /dev/null @@ -1,1752 +0,0 @@ -package world.bentobox.challenges.panel.admin; - - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.entity.EntityType; -import org.bukkit.inventory.ItemStack; - -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.bentobox.util.Util; -import world.bentobox.challenges.ChallengesAddon; -import world.bentobox.challenges.database.object.Challenge; -import world.bentobox.challenges.database.object.requirements.InventoryRequirements; -import world.bentobox.challenges.database.object.requirements.IslandRequirements; -import world.bentobox.challenges.database.object.requirements.OtherRequirements; -import world.bentobox.challenges.database.object.requirements.StatisticRequirements; -import world.bentobox.challenges.panel.CommonGUI; -import world.bentobox.challenges.panel.util.*; -import world.bentobox.challenges.utils.GuiUtils; -import world.bentobox.challenges.utils.Utils; - - -/** - * This class contains all necessary methods that creates GUI and allow to edit challenges - * properties. - */ -public class EditChallengeGUI extends CommonGUI -{ - // --------------------------------------------------------------------- - // Section: Constructors - // --------------------------------------------------------------------- - - - /** - * @param addon Addon where panel operates. - * @param world World from which panel was created. - * @param user User who created panel. - * @param topLabel Command top label which creates panel (f.e. island or ai) - * @param permissionPrefix Command permission prefix (f.e. bskyblock.) - * @param challenge - challenge that needs editing - */ - public EditChallengeGUI(ChallengesAddon addon, - World world, - User user, - Challenge challenge, - String topLabel, - String permissionPrefix) - { - this(addon, world, user, challenge, topLabel, permissionPrefix, null); - } - - - /** - * @param addon Addon where panel operates. - * @param world World from which panel was created. - * @param user User who created panel. - * @param topLabel Command top label which creates panel (f.e. island or ai) - * @param permissionPrefix Command permission prefix (f.e. bskyblock.) - * @param challenge challenge that needs editing. - */ - public EditChallengeGUI(ChallengesAddon addon, - World world, - User user, - Challenge challenge, - String topLabel, - String permissionPrefix, - CommonGUI parentGUI) - { - super(addon, world, user, topLabel, permissionPrefix, parentGUI); - this.challenge = challenge; - - // Default panel should be Properties. - this.currentMenuType = MenuType.PROPERTIES; - - // Set line length. - this.lineLength = this.addon.getChallengesSettings().getLoreLineLength(); - } - - - // --------------------------------------------------------------------- - // Section: Panel Creation related methods - // --------------------------------------------------------------------- - - - /** - * {@inheritDoc} - */ - @Override - public void build() - { - PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name( - this.user.getTranslation("challenges.gui.title.admin.edit-challenge-title")); - - GuiUtils.fillBorder(panelBuilder); - - panelBuilder.item(2, this.createMenuButton(MenuType.PROPERTIES)); - panelBuilder.item(4, this.createMenuButton(MenuType.REQUIREMENTS)); - panelBuilder.item(6, this.createMenuButton(MenuType.REWARDS)); - - if (this.currentMenuType.equals(MenuType.PROPERTIES)) - { - this.buildMainPropertiesPanel(panelBuilder); - } - else if (this.currentMenuType.equals(MenuType.REQUIREMENTS)) - { - switch (this.challenge.getChallengeType()) - { - case INVENTORY -> this.buildInventoryRequirementsPanel(panelBuilder); - case ISLAND -> this.buildIslandRequirementsPanel(panelBuilder); - case OTHER -> this.buildOtherRequirementsPanel(panelBuilder); - case STATISTIC -> this.buildStatisticRequirementsPanel(panelBuilder); - } - } - else if (this.currentMenuType.equals(MenuType.REWARDS)) - { - this.buildRewardsPanel(panelBuilder); - } - - panelBuilder.item(44, this.returnButton); - - // Every time when this GUI is build, save challenge - // This will ensure that all main things will be always stored - this.addon.getChallengesManager().saveChallenge(this.challenge); - // If for some reason challenge is not loaded, do it. - this.addon.getChallengesManager().loadChallenge(this.challenge, false, null, true); - - panelBuilder.build(); - } - - - /** - * This class populate ChallengesEditGUI with main challenge settings. - * @param panelBuilder PanelBuilder where icons must be added. - */ - private void buildMainPropertiesPanel(PanelBuilder panelBuilder) - { - panelBuilder.item(10, this.createButton(Button.NAME)); - panelBuilder.item(16, this.createButton(Button.DEPLOYED)); - - panelBuilder.item(19, this.createButton(Button.ICON)); - panelBuilder.item(22, this.createButton(Button.DESCRIPTION)); - panelBuilder.item(25, this.createButton(Button.ORDER)); - - panelBuilder.item(28, this.createButton(Button.ENVIRONMENT)); - panelBuilder.item(31, this.createButton(Button.REMOVE_ON_COMPLETE)); - } - - - /** - * This class populates ChallengesEditGUI with island challenges requirement elements. - * @param panelBuilder PanelBuilder where icons must be added. - */ - private void buildIslandRequirementsPanel(PanelBuilder panelBuilder) - { - panelBuilder.item(19, this.createRequirementButton(RequirementButton.REQUIRED_ENTITIES)); - panelBuilder.item(28, this.createRequirementButton(RequirementButton.REMOVE_ENTITIES)); - - panelBuilder.item(21, this.createRequirementButton(RequirementButton.REQUIRED_BLOCKS)); - panelBuilder.item(30, this.createRequirementButton(RequirementButton.REMOVE_BLOCKS)); - - panelBuilder.item(23, this.createRequirementButton(RequirementButton.SEARCH_RADIUS)); - panelBuilder.item(25, this.createRequirementButton(RequirementButton.REQUIRED_PERMISSIONS)); - } - - - /** - * This class populates ChallengesEditGUI with inventory challenges requirement elements. - * @param panelBuilder PanelBuilder where icons must be added. - */ - private void buildInventoryRequirementsPanel(PanelBuilder panelBuilder) - { - panelBuilder.item(10, this.createRequirementButton(RequirementButton.REQUIRED_ITEMS)); - panelBuilder.item(19, this.createRequirementButton(RequirementButton.REMOVE_ITEMS)); - - panelBuilder.item(25, this.createRequirementButton(RequirementButton.REQUIRED_PERMISSIONS)); - } - - - /** - * This class populates ChallengesEditGUI with other challenges requirement elements. - * @param panelBuilder PanelBuilder where icons must be added. - */ - private void buildOtherRequirementsPanel(PanelBuilder panelBuilder) - { - panelBuilder.item(10, this.createRequirementButton(RequirementButton.REQUIRED_EXPERIENCE)); - panelBuilder.item(19, this.createRequirementButton(RequirementButton.REMOVE_EXPERIENCE)); - - panelBuilder.item(12, this.createRequirementButton(RequirementButton.REQUIRED_MONEY)); - panelBuilder.item(21, this.createRequirementButton(RequirementButton.REMOVE_MONEY)); - - panelBuilder.item(23, this.createRequirementButton(RequirementButton.REQUIRED_LEVEL)); - - panelBuilder.item(25, this.createRequirementButton(RequirementButton.REQUIRED_PERMISSIONS)); - } - - - /** - * This class populates ChallengesEditGUI with other challenges requirement elements. - * @param panelBuilder PanelBuilder where icons must be added. - */ - private void buildStatisticRequirementsPanel(PanelBuilder panelBuilder) - { - panelBuilder.item(10, this.createRequirementButton(RequirementButton.STATISTIC)); - panelBuilder.item(19, this.createRequirementButton(RequirementButton.REMOVE_STATISTIC)); - - panelBuilder.item(11, this.createRequirementButton(RequirementButton.STATISTIC_AMOUNT)); - - StatisticRequirements requirements = this.challenge.getRequirements(); - - if (requirements.getStatistic() != null) - { - switch (requirements.getStatistic().getType()) - { - case ITEM -> panelBuilder.item(13, this.createRequirementButton(RequirementButton.STATISTIC_ITEMS)); - case BLOCK -> panelBuilder.item(13, this.createRequirementButton(RequirementButton.STATISTIC_BLOCKS)); - case ENTITY -> panelBuilder.item(13, this.createRequirementButton(RequirementButton.STATISTIC_ENTITIES)); - } - } - - panelBuilder.item(25, this.createRequirementButton(RequirementButton.REQUIRED_PERMISSIONS)); - } - - - /** - * This class populates ChallengesEditGUI with challenges reward elements. - * @param panelBuilder PanelBuilder where icons must be added. - */ - private void buildRewardsPanel(PanelBuilder panelBuilder) - { - panelBuilder.item(10, this.createRewardButton(RewardButton.REWARD_TEXT)); - panelBuilder.item(19, this.createRewardButton(RewardButton.REWARD_COMMANDS)); - - panelBuilder.item(11, this.createRewardButton(RewardButton.REWARD_ITEM)); - panelBuilder.item(20, this.createRewardButton(RewardButton.REWARD_EXPERIENCE)); - panelBuilder.item(29, this.createRewardButton(RewardButton.REWARD_MONEY)); - - panelBuilder.item(22, this.createRewardButton(RewardButton.REPEATABLE)); - - if (this.challenge.isRepeatable()) - { - panelBuilder.item(31, this.createRewardButton(RewardButton.REPEAT_COUNT)); - - panelBuilder.item(15, this.createRewardButton(RewardButton.REPEAT_REWARD_TEXT)); - panelBuilder.item(24, this.createRewardButton(RewardButton.REPEAT_REWARD_COMMANDS)); - - panelBuilder.item(16, this.createRewardButton(RewardButton.REPEAT_REWARD_ITEM)); - panelBuilder.item(25, this.createRewardButton(RewardButton.REPEAT_REWARD_EXPERIENCE)); - panelBuilder.item(34, this.createRewardButton(RewardButton.REPEAT_REWARD_MONEY)); - } - } - - - // --------------------------------------------------------------------- - // Section: Other methods - // --------------------------------------------------------------------- - - - /** - * This method creates top menu buttons, that allows to switch "tabs". - * @param menuType Menu Type which button must be constructed. - * @return PanelItem that represents given menu type. - */ - private PanelItem createMenuButton(MenuType menuType) - { - ItemStack icon; - String name; - String description; - boolean glow; - PanelItem.ClickHandler clickHandler; - - switch (menuType) - { - case PROPERTIES: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.properties"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.properties"); - icon = new ItemStack(Material.CRAFTING_TABLE); - clickHandler = (panel, user, clickType, slot) -> { - this.currentMenuType = MenuType.PROPERTIES; - this.build(); - - return true; - }; - glow = this.currentMenuType.equals(MenuType.PROPERTIES); - break; - } - case REQUIREMENTS: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.requirements"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.requirements"); - icon = new ItemStack(Material.HOPPER); - clickHandler = (panel, user, clickType, slot) -> { - this.currentMenuType = MenuType.REQUIREMENTS; - this.build(); - - return true; - }; - glow = this.currentMenuType.equals(MenuType.REQUIREMENTS); - break; - } - case REWARDS: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.rewards"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.rewards"); - icon = new ItemStack(Material.DROPPER); - clickHandler = (panel, user, clickType, slot) -> { - this.currentMenuType = MenuType.REWARDS; - this.build(); - - return true; - }; - glow = this.currentMenuType.equals(MenuType.REWARDS); - break; - } - default: - return null; - } - - return new PanelItemBuilder(). - icon(icon). - name(name). - description(GuiUtils.stringSplit(description, this.lineLength)). - glow(glow). - clickHandler(clickHandler). - build(); - } - - - /** - * This method creates buttons for default main menu. - * @param button Button which panel item must be created. - * @return PanelItem that represents given button. - */ - private PanelItem createButton(Button button) - { - ItemStack icon; - String name; - List description; - boolean glow; - PanelItem.ClickHandler clickHandler; - - switch (button) - { - case DEPLOYED: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.deployment"); - - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.deployment")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - this.challenge.isDeployed() ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - - icon = new ItemStack(Material.LEVER); - clickHandler = (panel, user, clickType, slot) -> { - if (this.challenge.isValid()) - { - this.challenge.setDeployed(!this.challenge.isDeployed()); - } - else - { - this.user.sendMessage("challenges.errors.invalid-challenge", - "[challenge]", this.challenge.getFriendlyName()); - this.challenge.setDeployed(false); - } - - this.build(); - return true; - }; - glow = this.challenge.isDeployed(); - break; - } - case ICON: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.icon"); - description = Collections.singletonList(this.user.getTranslation( - "challenges.gui.descriptions.admin.icon-challenge")); - icon = this.challenge.getIcon(); - clickHandler = (panel, user, clickType, slot) -> { - - new SelectBlocksGUI(this.user, true, (status, materials) -> { - if (status) - { - materials.forEach(material -> - this.challenge.setIcon(new ItemStack(material))); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case DESCRIPTION: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.description"); - description = Collections.singletonList( - this.user.getTranslation("challenges.gui.descriptions.admin.description")); - icon = new ItemStack(Material.WRITTEN_BOOK); - clickHandler = (panel, user, clickType, slot) -> { - new StringListGUI(this.user, - this.challenge.getDescription(), - this.lineLength, - (status, value) -> { - if (status) - { - this.challenge.setDescription(value); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case ORDER: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.order"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.order")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", Integer.toString(this.challenge.getOrder()))); - - icon = new ItemStack(Material.DROPPER); - clickHandler = (panel, user, clickType, slot) -> { - new NumberGUI(this.user, - this.challenge.getOrder(), - -1, - 9999, - this.lineLength, - (status, value) -> { - if (status) - { - this.challenge.setOrder(value); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case ENVIRONMENT: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.environment"); - - description = new ArrayList<>(4); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.environment")); - - description.add((this.challenge.getEnvironment().contains(World.Environment.NORMAL) ? "&2" : "&c") + - this.user.getTranslation("challenges.gui.descriptions.normal")); - description.add((this.challenge.getEnvironment().contains(World.Environment.NETHER) ? "&2" : "&c") + - this.user.getTranslation("challenges.gui.descriptions.nether")); - description.add((this.challenge.getEnvironment().contains(World.Environment.THE_END) ? "&2" : "&c") + - this.user.getTranslation("challenges.gui.descriptions.the-end")); - - icon = new ItemStack(Material.DROPPER); - clickHandler = (panel, user, clickType, slot) -> { - new SelectEnvironmentGUI(this.user, - this.challenge.getEnvironment(), - (status, value) -> { - if (status) - { - this.challenge.setEnvironment(value); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case REMOVE_ON_COMPLETE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.remove-on-complete"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.remove-on-complete")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - this.challenge.isRemoveWhenCompleted() ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - - if (this.challenge.isRemoveWhenCompleted()) - { - icon = new ItemStack(Material.LAVA_BUCKET); - } - else - { - icon = new ItemStack(Material.BUCKET); - } - - clickHandler = (panel, user, clickType, slot) -> { - this.challenge.setRemoveWhenCompleted(!this.challenge.isRemoveWhenCompleted()); - this.build(); - - return true; - }; - glow = this.challenge.isRemoveWhenCompleted(); - break; - } - case NAME: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.name"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.name-challenge")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", this.challenge.getFriendlyName())); - - icon = new ItemStack(Material.DROPPER); - clickHandler = (panel, user, clickType, slot) -> { - - this.getFriendlyName(reply -> { - if (reply != null) - { - this.challenge.setFriendlyName(reply); - } - - this.build(); - }, - this.user.getTranslation("challenges.gui.questions.admin.challenge-name"), - this.challenge.getFriendlyName() - ); - - return true; - }; - glow = false; - break; - } - - default: - return null; - } - - return new PanelItemBuilder(). - icon(icon). - name(name). - description(GuiUtils.stringSplit(description, this.lineLength)). - glow(glow). - clickHandler(clickHandler). - build(); - } - - - /** - * This method creates buttons for requirements menu. - * @param button Button which panel item must be created. - * @return PanelItem that represents given button. - */ - private PanelItem createRequirementButton(RequirementButton button) - { - ItemStack icon; - String name; - List description; - boolean glow; - PanelItem.ClickHandler clickHandler; - - switch (button) - { - case REQUIRED_PERMISSIONS -> { - name = this.user.getTranslation("challenges.gui.buttons.admin.required-permissions"); - description = new ArrayList<>(this.challenge.getRequirements().getRequiredPermissions().size() + 1); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.required-permissions")); - - for (String permission : this.challenge.getRequirements().getRequiredPermissions()) - { - description.add(this.user.getTranslation("challenges.gui.descriptions.permission", - "[permission]", permission)); - } - - icon = new ItemStack(Material.REDSTONE_LAMP); - clickHandler = (panel, user, clickType, slot) -> - { - new StringListGUI(this.user, - this.challenge.getRequirements().getRequiredPermissions(), - lineLength, - (status, value) -> - { - if (status) - { - this.challenge.getRequirements().setRequiredPermissions(new HashSet<>(value)); - } - - this.build(); - }); - - return true; - }; - glow = false; - } - // Buttons for Island Requirements - case REQUIRED_ENTITIES, REMOVE_ENTITIES, REQUIRED_BLOCKS, REMOVE_BLOCKS, SEARCH_RADIUS -> { - return this.createIslandRequirementButton(button); - } - // Buttons for Inventory Requirements - case REQUIRED_ITEMS, REMOVE_ITEMS -> { - return this.createInventoryRequirementButton(button); - } - // Buttons for Other Requirements - case REQUIRED_EXPERIENCE, REMOVE_EXPERIENCE, REQUIRED_LEVEL, REQUIRED_MONEY, REMOVE_MONEY -> { - return this.createOtherRequirementButton(button); - } - // Buttons for Statistic Requirements - case STATISTIC, STATISTIC_BLOCKS, STATISTIC_ITEMS, STATISTIC_ENTITIES, STATISTIC_AMOUNT, REMOVE_STATISTIC -> { - return this.createStatisticRequirementButton(button); - } - // Default behaviour. - default -> { - return null; - } - } - - return new PanelItemBuilder(). - icon(icon). - name(name). - description(GuiUtils.stringSplit(description, this.lineLength)). - glow(glow). - clickHandler(clickHandler). - build(); - } - - - /** - * This method creates buttons for island requirements menu. - * @param button Button which panel item must be created. - * @return PanelItem that represents given button. - */ - private PanelItem createIslandRequirementButton(RequirementButton button) - { - ItemStack icon; - String name; - List description; - boolean glow; - PanelItem.ClickHandler clickHandler; - - final IslandRequirements requirements = this.challenge.getRequirements(); - - switch (button) - { - case REQUIRED_ENTITIES: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.required-entities"); - - description = new ArrayList<>(requirements.getRequiredEntities().size() + 1); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.required-entities")); - - for (Map.Entry entry : requirements.getRequiredEntities().entrySet()) - { - description.add(this.user.getTranslation("challenges.gui.descriptions.entity", - "[entity]", Util.prettifyText(entry.getKey().name()), - "[count]", Integer.toString(entry.getValue()))); - } - - icon = new ItemStack(Material.CREEPER_HEAD); - clickHandler = (panel, user, clickType, slot) -> { - new ManageEntitiesGUI(this.addon, - this.world, - this.user, - requirements.getRequiredEntities(), - this.topLabel, - this.permissionPrefix, - this).build(); - - return true; - }; - glow = false; - break; - } - case REMOVE_ENTITIES: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.remove-entities"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.remove-entities")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - requirements.isRemoveEntities() ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - - icon = new ItemStack(Material.LEVER); - clickHandler = (panel, user, clickType, slot) -> { - requirements.setRemoveEntities(!requirements.isRemoveEntities()); - - this.build(); - return true; - }; - glow = requirements.isRemoveEntities(); - break; - } - case REQUIRED_BLOCKS: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.required-blocks"); - - description = new ArrayList<>(requirements.getRequiredBlocks().size() + 1); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.required-blocks")); - - for (Map.Entry entry : requirements.getRequiredBlocks().entrySet()) - { - description.add(this.user.getTranslation("challenges.gui.descriptions.block", - "[block]", entry.getKey().name(), - "[count]", Integer.toString(entry.getValue()))); - } - - icon = new ItemStack(Material.STONE); - clickHandler = (panel, user, clickType, slot) -> { - new ManageBlocksGUI(this.addon, - this.world, - this.user, - requirements.getRequiredBlocks(), - this.topLabel, - this.permissionPrefix, - this).build(); - - return true; - }; - glow = false; - break; - } - case REMOVE_BLOCKS: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.remove-blocks"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.remove-blocks")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - requirements.isRemoveBlocks() ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - - icon = new ItemStack(Material.LEVER); - clickHandler = (panel, user, clickType, slot) -> { - requirements.setRemoveBlocks(!requirements.isRemoveBlocks()); - - this.build(); - return true; - }; - glow = requirements.isRemoveBlocks(); - break; - } - case SEARCH_RADIUS: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.search-radius"); - description = new ArrayList<>(2); - description.add(this.user - .getTranslation("challenges.gui.descriptions.admin.search-radius")); - description - .add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", Integer.toString(requirements.getSearchRadius()))); - - icon = new ItemStack(Material.COBBLESTONE_WALL); - - // Search radius should not be larger then island radius. - int maxSearchDistance = - this.addon.getPlugin().getIWM().getAddon(this.world).map(gameModeAddon -> - gameModeAddon.getWorldSettings().getIslandDistance()).orElse(100); - - clickHandler = (panel, user, clickType, slot) -> { - new NumberGUI(this.user, - requirements.getSearchRadius(), - 0, - maxSearchDistance, - this.lineLength, - (status, value) -> { - if (status) - { - requirements.setSearchRadius(value); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - default: - return null; - } - - return new PanelItemBuilder(). - icon(icon). - name(name). - description(GuiUtils.stringSplit(description, this.lineLength)). - glow(glow). - clickHandler(clickHandler). - build(); - } - - - /** - * This method creates buttons for inventory requirements menu. - * @param button Button which panel item must be created. - * @return PanelItem that represents given button. - */ - private PanelItem createInventoryRequirementButton(RequirementButton button) - { - ItemStack icon; - String name; - List description; - boolean glow; - PanelItem.ClickHandler clickHandler; - - final InventoryRequirements requirements = this.challenge.getRequirements(); - - switch (button) - { - case REQUIRED_ITEMS: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.required-items"); - - description = new ArrayList<>(requirements.getRequiredItems().size() + 1); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.required-items")); - - Utils.groupEqualItems(requirements.getRequiredItems()).forEach(itemStack -> - description.addAll(this.generateItemStackDescription(itemStack))); - - icon = new ItemStack(Material.CHEST); - clickHandler = (panel, user, clickType, slot) -> { - new ItemSwitchGUI(this.user, - requirements.getRequiredItems(), - this.lineLength, - (status, value) -> { - if (status) - { - requirements.setRequiredItems(value); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case REMOVE_ITEMS: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.remove-items"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.remove-items")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - requirements.isTakeItems() ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - - icon = new ItemStack(Material.LEVER); - clickHandler = (panel, user, clickType, slot) -> { - requirements.setTakeItems(!requirements.isTakeItems()); - - this.build(); - return true; - }; - glow = requirements.isTakeItems(); - break; - } - default: - return null; - } - - return new PanelItemBuilder(). - icon(icon). - name(name). - description(GuiUtils.stringSplit(description, this.lineLength)). - glow(glow). - clickHandler(clickHandler). - build(); - } - - - /** - * This method creates buttons for other requirements menu. - * @param button Button which panel item must be created. - * @return PanelItem that represents given button. - */ - private PanelItem createOtherRequirementButton(RequirementButton button) - { - ItemStack icon; - String name; - List description; - boolean glow; - PanelItem.ClickHandler clickHandler; - - final OtherRequirements requirements = this.challenge.getRequirements(); - - switch (button) - { - case REQUIRED_EXPERIENCE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.required-experience"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.required-experience")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", Integer.toString(requirements.getRequiredExperience()))); - - icon = new ItemStack(Material.EXPERIENCE_BOTTLE); - clickHandler = (panel, user, clickType, slot) -> { - new NumberGUI(this.user, - requirements.getRequiredExperience(), - 0, - this.lineLength, - (status, value) -> { - if (status) - { - requirements.setRequiredExperience(value); - } - - this.build(); - }); - return true; - }; - glow = false; - break; - } - case REMOVE_EXPERIENCE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.remove-experience"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.remove-experience")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - requirements.isTakeExperience() ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - - icon = new ItemStack(Material.LEVER); - clickHandler = (panel, user, clickType, slot) -> { - requirements.setTakeExperience(!requirements.isTakeExperience()); - - this.build(); - return true; - }; - glow = requirements.isTakeExperience(); - break; - } - case REQUIRED_LEVEL: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.required-level"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.required-level")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", Long.toString(requirements.getRequiredIslandLevel()))); - - icon = new ItemStack(this.addon.isLevelProvided() ? Material.BEACON : Material.BARRIER); - clickHandler = (panel, user, clickType, slot) -> { - new NumberGUI(this.user, - (int) requirements.getRequiredIslandLevel(), - lineLength, - (status, value) -> { - if (status) - { - requirements.setRequiredIslandLevel(value); - } - - this.build(); - }); - - return true; - }; - - glow = false; - break; - } - case REQUIRED_MONEY: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.required-money"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.required-money")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", Double.toString(requirements.getRequiredMoney()))); - - icon = new ItemStack(this.addon.isEconomyProvided() ? Material.GOLD_INGOT : Material.BARRIER); - clickHandler = (panel, user, clickType, slot) -> { - new NumberGUI(this.user, - (int) requirements.getRequiredMoney(), - 0, - lineLength, - (status, value) -> { - if (status) - { - requirements.setRequiredMoney(value); - } - - this.build(); - }); - return true; - }; - - glow = false; - break; - } - case REMOVE_MONEY: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.remove-money"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.remove-money")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - requirements.isTakeMoney() ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - - icon = new ItemStack(this.addon.isEconomyProvided() ? Material.LEVER : Material.BARRIER); - clickHandler = (panel, user, clickType, slot) -> { - requirements.setTakeMoney(!requirements.isTakeMoney()); - - this.build(); - return true; - }; - - glow = requirements.isTakeMoney(); - break; - } - default: - return null; - } - - return new PanelItemBuilder(). - icon(icon). - name(name). - description(GuiUtils.stringSplit(description, this.lineLength)). - glow(glow). - clickHandler(clickHandler). - build(); - } - - - /** - * Creates a button for statistic requirements. - * @param button Button that must be created. - * @return PanelItem button. - */ - private PanelItem createStatisticRequirementButton(RequirementButton button) - { - ItemStack icon; - String name; - List description; - boolean glow; - PanelItem.ClickHandler clickHandler; - - final StatisticRequirements requirements = this.challenge.getRequirements(); - - switch (button) - { - case STATISTIC: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.required-statistic"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.required-statistic")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", String.valueOf(requirements.getStatistic()))); - - icon = new ItemStack(Material.PAPER); - clickHandler = (panel, user, clickType, slot) -> { - new SelectStatisticGUI(this.user, (status, statistic) -> { - if (status) - { - requirements.setStatistic(statistic); - } - - this.build(); - }); - return true; - }; - glow = false; - break; - } - case STATISTIC_AMOUNT: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.required-amount"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.required-amount")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", Integer.toString(requirements.getAmount()))); - - icon = new ItemStack(Material.CHEST); - clickHandler = (panel, user, clickType, slot) -> { - new NumberGUI(this.user, - requirements.getAmount(), - 0, - this.lineLength, - (status, value) -> { - if (status) - { - requirements.setAmount(value); - } - - this.build(); - }); - return true; - }; - glow = false; - break; - } - case REMOVE_STATISTIC: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.remove-statistic"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.remove-statistic")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - requirements.isReduceStatistic() ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - - icon = new ItemStack(Material.LEVER); - clickHandler = (panel, user, clickType, slot) -> { - requirements.setReduceStatistic(!requirements.isReduceStatistic()); - - this.build(); - return true; - }; - glow = requirements.isReduceStatistic(); - break; - } - case STATISTIC_BLOCKS: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.statistic-block"); - - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.statistic-block")); - description.add(this.user.getTranslation("challenges.gui.descriptions.statistic-block", - "[material]", String.valueOf(requirements.getMaterial()))); - - icon = requirements.getMaterial() == null ? - new ItemStack(Material.BARRIER) : - new ItemStack(requirements.getMaterial()); - - clickHandler = (panel, user, clickType, slot) -> { - new SelectBlocksGUI(this.user, - true, - Collections.emptySet(), - (status, block) -> { - if (status) - { - requirements.setMaterial(block.iterator().next()); - } - - this.build(); - }); - - return true; - }; - - glow = false; - break; - } - case STATISTIC_ITEMS: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.statistic-item"); - - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.statistic-item")); - description.add(this.user.getTranslation("challenges.gui.descriptions.statistic-item", - "[material]", String.valueOf(requirements.getMaterial()))); - - icon = requirements.getMaterial() == null ? - new ItemStack(Material.BARRIER) : - new ItemStack(requirements.getMaterial()); - - clickHandler = (panel, user, clickType, slot) -> { - new SelectBlocksGUI(this.user, - true, - (status, block) -> { - if (status) - { - requirements.setMaterial(block.iterator().next()); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case STATISTIC_ENTITIES: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.statistic-entity"); - - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.statistic-entity")); - description.add(this.user.getTranslation("challenges.gui.descriptions.statistic-entity", - "[entity]", String.valueOf(requirements.getEntity()))); - - icon = requirements.getEntity() == null ? - new ItemStack(Material.BARRIER) : - new ItemStack(GuiUtils.getEntityEgg(requirements.getEntity())); - - clickHandler = (panel, user, clickType, slot) -> { - new SelectEntityGUI(this.user, Collections.emptySet(), true, (status, entities) -> { - if (status) - { - requirements.setEntity(entities.iterator().next()); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - default: - return null; - } - - return new PanelItemBuilder(). - icon(icon). - name(name). - description(GuiUtils.stringSplit(description, this.lineLength)). - glow(glow). - clickHandler(clickHandler). - build(); - } - - - /** - * This method creates buttons for rewards menu. - * @param button Button which panel item must be created. - * @return PanelItem that represents given button. - */ - private PanelItem createRewardButton(RewardButton button) - { - ItemStack icon; - String name; - List description; - boolean glow; - PanelItem.ClickHandler clickHandler; - - switch (button) - { - case REWARD_TEXT: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.reward-text"); - description = new ArrayList<>(2); - description - .add(this.user.getTranslation("challenges.gui.descriptions.admin.reward-text")); - description - .add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", "|" + this.challenge.getRewardText())); - - icon = new ItemStack(Material.WRITTEN_BOOK); - clickHandler = (panel, user, clickType, slot) -> { - new StringListGUI(this.user, - this.challenge.getRewardText(), - lineLength, - (status, value) -> { - if (status) - { - String singleLineMessage = value.stream(). - map(s -> s + "|"). - collect(Collectors.joining()); - - if (singleLineMessage.endsWith("|")) - { - singleLineMessage = singleLineMessage - .substring(0, singleLineMessage.length() - 1); - } - - this.challenge.setRewardText(singleLineMessage); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case REWARD_ITEM: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.reward-items"); - - description = new ArrayList<>(this.challenge.getRewardItems().size() + 1); - description.add(this.user - .getTranslation("challenges.gui.descriptions.admin.reward-items")); - - Utils.groupEqualItems(this.challenge.getRewardItems()).forEach(itemStack -> - description.addAll(this.generateItemStackDescription(itemStack))); - - icon = new ItemStack(Material.CHEST); - clickHandler = (panel, user, clickType, slot) -> { - new ItemSwitchGUI(this.user, - this.challenge.getRewardItems(), - lineLength, - (status, value) -> { - if (status) - { - this.challenge.setRewardItems(value); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case REWARD_EXPERIENCE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.reward-experience"); - description = new ArrayList<>(2); - description.add(this.user - .getTranslation("challenges.gui.descriptions.admin.reward-experience")); - description - .add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", Integer.toString(this.challenge.getRewardExperience()))); - icon = new ItemStack(Material.EXPERIENCE_BOTTLE); - clickHandler = (panel, user, clickType, slot) -> { - new NumberGUI(this.user, - this.challenge.getRewardExperience(), - 0, - lineLength, - (status, value) -> { - if (status) - { - this.challenge.setRewardExperience(value); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case REWARD_MONEY: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.reward-money"); - description = new ArrayList<>(2); - description.add(this.user - .getTranslation("challenges.gui.descriptions.admin.reward-money")); - description - .add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", Integer.toString(this.challenge.getRewardMoney()))); - - icon = new ItemStack( - this.addon.isEconomyProvided() ? Material.GOLD_INGOT : Material.BARRIER); - clickHandler = (panel, user, clickType, slot) -> { - new NumberGUI(this.user, - this.challenge.getRewardMoney(), - 0, - lineLength, - (status, value) -> { - if (status) - { - this.challenge.setRewardMoney(value); - } - - this.build(); - }); - - return true; - }; - - - glow = false; - break; - } - case REWARD_COMMANDS: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.reward-commands"); - description = new ArrayList<>(this.challenge.getRewardCommands().size() + 1); - description.add(this.user - .getTranslation("challenges.gui.descriptions.admin.reward-commands")); - - for (String command : this.challenge.getRewardCommands()) - { - description.add(this.user.getTranslation("challenges.gui.descriptions.command", - "[command]", command)); - } - - icon = new ItemStack(Material.COMMAND_BLOCK); - clickHandler = (panel, user, clickType, slot) -> { - new StringListGUI(this.user, - this.challenge.getRewardCommands(), - lineLength, - (status, value) -> { - if (status) - { - this.challenge.setRewardCommands(value); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - - case REPEATABLE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.repeatable"); - description = new ArrayList<>(2); - description - .add(this.user.getTranslation("challenges.gui.descriptions.admin.repeatable")); - description - .add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - this.challenge.isRepeatable() ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - - icon = new ItemStack(Material.LEVER); - clickHandler = (panel, user, clickType, slot) -> { - this.challenge.setRepeatable(!this.challenge.isRepeatable()); - - this.build(); - return true; - }; - glow = this.challenge.isRepeatable(); - break; - } - case REPEAT_COUNT: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.repeat-count"); - description = new ArrayList<>(2); - description.add(this.user - .getTranslation("challenges.gui.descriptions.admin.repeat-count")); - description - .add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", Integer.toString(this.challenge.getMaxTimes()))); - - icon = new ItemStack(Material.COBBLESTONE_WALL); - clickHandler = (panel, user, clickType, slot) -> { - new NumberGUI(this.user, - this.challenge.getMaxTimes(), - 0, - lineLength, - (status, value) -> { - if (status) - { - this.challenge.setMaxTimes(value); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - - case REPEAT_REWARD_TEXT: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.repeat-reward-text"); - description = new ArrayList<>(2); - description.add(this.user - .getTranslation("challenges.gui.descriptions.admin.repeat-reward-text")); - description - .add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", "|" + this.challenge.getRepeatRewardText())); - - icon = new ItemStack(Material.WRITTEN_BOOK); - clickHandler = (panel, user, clickType, slot) -> { - new StringListGUI(this.user, - this.challenge.getRepeatRewardText(), - lineLength, - (status, value) -> { - if (status) - { - String singleLineMessage = value.stream(). - map(s -> s + "|"). - collect(Collectors.joining()); - - if (singleLineMessage.endsWith("|")) - { - singleLineMessage = singleLineMessage - .substring(0, singleLineMessage.length() - 1); - } - - this.challenge.setRepeatRewardText(singleLineMessage); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case REPEAT_REWARD_ITEM: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.repeat-reward-items"); - - description = new ArrayList<>(this.challenge.getRepeatItemReward().size() + 1); - description.add(this.user - .getTranslation("challenges.gui.descriptions.admin.repeat-reward-items")); - - Utils.groupEqualItems(this.challenge.getRepeatItemReward()).forEach(itemStack -> - description.addAll(this.generateItemStackDescription(itemStack))); - - icon = new ItemStack(Material.TRAPPED_CHEST); - clickHandler = (panel, user, clickType, slot) -> { - new ItemSwitchGUI(this.user, - this.challenge.getRepeatItemReward(), - lineLength, - (status, value) -> { - if (status) - { - this.challenge.setRepeatItemReward(value); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case REPEAT_REWARD_EXPERIENCE: - { - name = this.user - .getTranslation("challenges.gui.buttons.admin.repeat-reward-experience"); - description = new ArrayList<>(2); - description.add(this.user - .getTranslation("challenges.gui.descriptions.admin.repeat-reward-experience")); - description - .add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", Integer.toString(this.challenge.getRepeatExperienceReward()))); - - icon = new ItemStack(Material.GLASS_BOTTLE); - clickHandler = (panel, user, clickType, slot) -> { - new NumberGUI(this.user, - this.challenge.getRepeatExperienceReward(), - 0, - lineLength, - (status, value) -> { - if (status) - { - this.challenge.setRepeatExperienceReward(value); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case REPEAT_REWARD_MONEY: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.repeat-reward-money"); - description = new ArrayList<>(2); - description.add(this.user - .getTranslation("challenges.gui.descriptions.admin.repeat-reward-money")); - description - .add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", Integer.toString(this.challenge.getRepeatMoneyReward()))); - - icon = new ItemStack( - this.addon.isEconomyProvided() ? Material.GOLD_NUGGET : Material.BARRIER); - clickHandler = (panel, user, clickType, slot) -> { - new NumberGUI(this.user, - this.challenge.getRepeatMoneyReward(), - 0, - lineLength, - (status, value) -> { - if (status) - { - this.challenge.setRepeatMoneyReward(value); - } - - this.build(); - }); - - return true; - }; - - glow = false; - break; - } - case REPEAT_REWARD_COMMANDS: - { - name = - this.user.getTranslation("challenges.gui.buttons.admin.repeat-reward-commands"); - description = new ArrayList<>(this.challenge.getRepeatRewardCommands().size() + 1); - description.add(this.user - .getTranslation("challenges.gui.descriptions.admin.repeat-reward-commands")); - - for (String command : this.challenge.getRepeatRewardCommands()) - { - description.add(this.user.getTranslation("challenges.gui.descriptions.command", - "[command]", command)); - } - - icon = new ItemStack(Material.COMMAND_BLOCK); - clickHandler = (panel, user, clickType, slot) -> { - new StringListGUI(this.user, - this.challenge.getRepeatRewardCommands(), - lineLength, - (status, value) -> { - if (status) - { - this.challenge.setRepeatRewardCommands(value); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - default: - return null; - } - - return new PanelItemBuilder(). - icon(icon). - name(name). - description(GuiUtils.stringSplit(description, this.lineLength)). - glow(glow). - clickHandler(clickHandler). - build(); - } - - - // --------------------------------------------------------------------- - // Section: Enums - // --------------------------------------------------------------------- - - - /** - * Represents different types of menus - */ - private enum MenuType - { - PROPERTIES, - REQUIREMENTS, - REWARDS - } - - - /** - * Represents different buttons that could be in menus. - */ - private enum Button - { - NAME, - DEPLOYED, - ICON, - DESCRIPTION, - ORDER, - ENVIRONMENT, - REMOVE_ON_COMPLETE, - } - - - /** - * Represents different rewards buttons that are used in menus. - */ - private enum RewardButton - { - REWARD_TEXT, - REWARD_ITEM, - REWARD_EXPERIENCE, - REWARD_MONEY, - REWARD_COMMANDS, - - REPEATABLE, - REPEAT_COUNT, - - REPEAT_REWARD_TEXT, - REPEAT_REWARD_ITEM, - REPEAT_REWARD_EXPERIENCE, - REPEAT_REWARD_MONEY, - REPEAT_REWARD_COMMANDS, - } - - - /** - * Represents different requirement buttons that are used in menus. - */ - private enum RequirementButton - { - REQUIRED_ENTITIES, - REMOVE_ENTITIES, - REQUIRED_BLOCKS, - REMOVE_BLOCKS, - SEARCH_RADIUS, - REQUIRED_PERMISSIONS, - REQUIRED_ITEMS, - REMOVE_ITEMS, - REQUIRED_EXPERIENCE, - REMOVE_EXPERIENCE, - REQUIRED_LEVEL, - REQUIRED_MONEY, - REMOVE_MONEY, - STATISTIC, - STATISTIC_BLOCKS, - STATISTIC_ITEMS, - STATISTIC_ENTITIES, - STATISTIC_AMOUNT, - REMOVE_STATISTIC, - } - - - // --------------------------------------------------------------------- - // Section: Variables - // --------------------------------------------------------------------- - - - /** - * Variable holds challenge thats needs editing. - */ - private Challenge challenge; - - /** - * Variable holds current active menu. - */ - private MenuType currentMenuType; - - /** - * LineLength variable. - */ - private final int lineLength; -} diff --git a/src/main/java/world/bentobox/challenges/panel/admin/EditChallengePanel.java b/src/main/java/world/bentobox/challenges/panel/admin/EditChallengePanel.java new file mode 100644 index 0000000..5fdfd1b --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/admin/EditChallengePanel.java @@ -0,0 +1,1870 @@ +package world.bentobox.challenges.panel.admin; + + +import java.util.*; +import java.util.function.Consumer; + +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.ItemStack; + +import world.bentobox.bentobox.api.panels.PanelItem; +import world.bentobox.bentobox.api.panels.PanelListener; +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.database.object.Challenge; +import world.bentobox.challenges.database.object.requirements.InventoryRequirements; +import world.bentobox.challenges.database.object.requirements.IslandRequirements; +import world.bentobox.challenges.database.object.requirements.OtherRequirements; +import world.bentobox.challenges.database.object.requirements.StatisticRequirements; +import world.bentobox.challenges.panel.CommonPanel; +import world.bentobox.challenges.panel.ConversationUtils; +import world.bentobox.challenges.panel.util.*; +import world.bentobox.challenges.utils.Constants; +import world.bentobox.challenges.utils.GuiUtils; +import world.bentobox.challenges.utils.Utils; + + +/** + * This class contains all necessary methods that creates GUI and allow to edit challenges + * properties. + */ +public class EditChallengePanel extends CommonPanel +{ + // --------------------------------------------------------------------- + // Section: Constructors + // --------------------------------------------------------------------- + + + /** + * @param addon Addon where panel operates. + * @param world World from which panel was created. + * @param user User who created panel. + * @param topLabel Command top label which creates panel (f.e. island or ai) + * @param permissionPrefix Command permission prefix (f.e. bskyblock.) + * @param challenge - challenge that needs editing + */ + private EditChallengePanel(ChallengesAddon addon, + User user, + World world, + String topLabel, + String permissionPrefix, + Challenge challenge) + { + super(addon, user, world, topLabel, permissionPrefix); + this.challenge = challenge; + this.currentMenuType = MenuType.PROPERTIES; + } + + + /** + * @param panel Parent panel + * @param challenge challenge that needs editing. + */ + private EditChallengePanel(CommonPanel panel, Challenge challenge) + { + super(panel); + this.challenge = challenge; + // Default panel should be Properties. + this.currentMenuType = MenuType.PROPERTIES; + } + + + /** + * Open the Challenges Edit GUI. + * + * @param addon the addon + * @param world the world + * @param user the user + * @param topLabel the top label + * @param permissionPrefix the permission prefix + * @param challenge - challenge that needs editing + */ + public static void open(ChallengesAddon addon, + User user, + World world, + String topLabel, + String permissionPrefix, + Challenge challenge) + { + new EditChallengePanel(addon, user, world, topLabel, permissionPrefix, challenge).build(); + } + + + /** + * Open the Challenges Edit GUI. + * + * @param panel - Parent Panel + * @param challenge - challenge that needs editing + */ + public static void open(CommonPanel panel, Challenge challenge) + { + new EditChallengePanel(panel, challenge).build(); + } + + + // --------------------------------------------------------------------- + // Section: Panel Creation related methods + // --------------------------------------------------------------------- + + + /** + * {@inheritDoc} + */ + @Override + protected void build() + { + PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name( + this.user.getTranslation(Constants.TITLE + "edit-challenge", + "[challenge]", this.challenge.getFriendlyName())); + + GuiUtils.fillBorder(panelBuilder); + + panelBuilder.item(2, this.createMenuButton(MenuType.PROPERTIES)); + panelBuilder.item(4, this.createMenuButton(MenuType.REQUIREMENTS)); + panelBuilder.item(6, this.createMenuButton(MenuType.REWARDS)); + + if (this.currentMenuType.equals(MenuType.PROPERTIES)) + { + this.buildMainPropertiesPanel(panelBuilder); + } + else if (this.currentMenuType.equals(MenuType.REQUIREMENTS)) + { + switch (this.challenge.getChallengeType()) + { + case INVENTORY_TYPE -> this.buildInventoryRequirementsPanel(panelBuilder); + case ISLAND_TYPE -> this.buildIslandRequirementsPanel(panelBuilder); + case OTHER_TYPE -> this.buildOtherRequirementsPanel(panelBuilder); + case STATISTIC_TYPE -> this.buildStatisticRequirementsPanel(panelBuilder); + } + } + else if (this.currentMenuType.equals(MenuType.REWARDS)) + { + this.buildRewardsPanel(panelBuilder); + } + + panelBuilder.item(44, this.returnButton); + + // Every time when this GUI is build, save challenge + // This will ensure that all main things will be always stored + this.addon.getChallengesManager().saveChallenge(this.challenge); + // If for some reason challenge is not loaded, do it. + this.addon.getChallengesManager().loadChallenge(this.challenge, false, null, true); + + panelBuilder.build(); + } + + + /** + * This class populate ChallengesEditGUI with main challenge settings. + * @param panelBuilder PanelBuilder where icons must be added. + */ + private void buildMainPropertiesPanel(PanelBuilder panelBuilder) + { + panelBuilder.listener(new IconChanger()); + + panelBuilder.item(10, this.createButton(Button.NAME)); + panelBuilder.item(16, this.createButton(Button.DEPLOYED)); + + panelBuilder.item(19, this.createButton(Button.ICON)); + panelBuilder.item(22, this.createButton(Button.DESCRIPTION)); + panelBuilder.item(25, this.createButton(Button.ORDER)); + + panelBuilder.item(28, this.createButton(Button.ENVIRONMENT)); + panelBuilder.item(31, this.createButton(Button.REMOVE_ON_COMPLETE)); + } + + + /** + * This class populates ChallengesEditGUI with island challenges requirement elements. + * @param panelBuilder PanelBuilder where icons must be added. + */ + private void buildIslandRequirementsPanel(PanelBuilder panelBuilder) + { + panelBuilder.item(19, this.createRequirementButton(RequirementButton.REQUIRED_ENTITIES)); + panelBuilder.item(28, this.createRequirementButton(RequirementButton.REMOVE_ENTITIES)); + + panelBuilder.item(21, this.createRequirementButton(RequirementButton.REQUIRED_BLOCKS)); + panelBuilder.item(30, this.createRequirementButton(RequirementButton.REMOVE_BLOCKS)); + + panelBuilder.item(23, this.createRequirementButton(RequirementButton.SEARCH_RADIUS)); + panelBuilder.item(25, this.createRequirementButton(RequirementButton.REQUIRED_PERMISSIONS)); + } + + + /** + * This class populates ChallengesEditGUI with inventory challenges requirement elements. + * @param panelBuilder PanelBuilder where icons must be added. + */ + private void buildInventoryRequirementsPanel(PanelBuilder panelBuilder) + { + panelBuilder.item(10, this.createRequirementButton(RequirementButton.REQUIRED_ITEMS)); + panelBuilder.item(19, this.createRequirementButton(RequirementButton.REMOVE_ITEMS)); + + panelBuilder.item(25, this.createRequirementButton(RequirementButton.REQUIRED_PERMISSIONS)); + } + + + /** + * This class populates ChallengesEditGUI with other challenges requirement elements. + * @param panelBuilder PanelBuilder where icons must be added. + */ + private void buildOtherRequirementsPanel(PanelBuilder panelBuilder) + { + panelBuilder.item(10, this.createRequirementButton(RequirementButton.REQUIRED_EXPERIENCE)); + panelBuilder.item(19, this.createRequirementButton(RequirementButton.REMOVE_EXPERIENCE)); + + panelBuilder.item(12, this.createRequirementButton(RequirementButton.REQUIRED_MONEY)); + panelBuilder.item(21, this.createRequirementButton(RequirementButton.REMOVE_MONEY)); + + panelBuilder.item(23, this.createRequirementButton(RequirementButton.REQUIRED_LEVEL)); + + panelBuilder.item(25, this.createRequirementButton(RequirementButton.REQUIRED_PERMISSIONS)); + } + + + /** + * This class populates ChallengesEditGUI with other challenges requirement elements. + * @param panelBuilder PanelBuilder where icons must be added. + */ + private void buildStatisticRequirementsPanel(PanelBuilder panelBuilder) + { + panelBuilder.item(10, this.createRequirementButton(RequirementButton.STATISTIC)); + panelBuilder.item(19, this.createRequirementButton(RequirementButton.REMOVE_STATISTIC)); + + panelBuilder.item(11, this.createRequirementButton(RequirementButton.STATISTIC_AMOUNT)); + + StatisticRequirements requirements = this.challenge.getRequirements(); + + if (requirements.getStatistic() != null) + { + switch (requirements.getStatistic().getType()) + { + case ITEM -> panelBuilder.item(13, this.createRequirementButton(RequirementButton.STATISTIC_ITEMS)); + case BLOCK -> panelBuilder.item(13, this.createRequirementButton(RequirementButton.STATISTIC_BLOCKS)); + case ENTITY -> panelBuilder.item(13, this.createRequirementButton(RequirementButton.STATISTIC_ENTITIES)); + } + } + + panelBuilder.item(25, this.createRequirementButton(RequirementButton.REQUIRED_PERMISSIONS)); + } + + + /** + * This class populates ChallengesEditGUI with challenges reward elements. + * @param panelBuilder PanelBuilder where icons must be added. + */ + private void buildRewardsPanel(PanelBuilder panelBuilder) + { + panelBuilder.item(10, this.createRewardButton(RewardButton.REWARD_TEXT)); + panelBuilder.item(19, this.createRewardButton(RewardButton.REWARD_COMMANDS)); + + panelBuilder.item(11, this.createRewardButton(RewardButton.REWARD_ITEMS)); + panelBuilder.item(20, this.createRewardButton(RewardButton.REWARD_EXPERIENCE)); + panelBuilder.item(29, this.createRewardButton(RewardButton.REWARD_MONEY)); + + panelBuilder.item(22, this.createRewardButton(RewardButton.REPEATABLE)); + + if (this.challenge.isRepeatable()) + { + panelBuilder.item(31, this.createRewardButton(RewardButton.REPEAT_COUNT)); + + panelBuilder.item(15, this.createRewardButton(RewardButton.REPEAT_REWARD_TEXT)); + panelBuilder.item(24, this.createRewardButton(RewardButton.REPEAT_REWARD_COMMANDS)); + + panelBuilder.item(16, this.createRewardButton(RewardButton.REPEAT_REWARD_ITEMS)); + panelBuilder.item(25, this.createRewardButton(RewardButton.REPEAT_REWARD_EXPERIENCE)); + panelBuilder.item(34, this.createRewardButton(RewardButton.REPEAT_REWARD_MONEY)); + } + } + + + // --------------------------------------------------------------------- + // Section: Other methods + // --------------------------------------------------------------------- + + + /** + * This method creates top menu buttons, that allows to switch "tabs". + * @param menuType Menu Type which button must be constructed. + * @return PanelItem that represents given menu type. + */ + private PanelItem createMenuButton(MenuType menuType) + { + final String reference = Constants.BUTTON + menuType.name().toLowerCase() + "."; + + final String name = this.user.getTranslation(reference + "name"); + final List description = new ArrayList<>(3); + description.add(this.user.getTranslation(reference + "description")); + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-select")); + + ItemStack icon; + boolean glow; + PanelItem.ClickHandler clickHandler; + + switch (menuType) + { + case PROPERTIES -> { + icon = new ItemStack(Material.CRAFTING_TABLE); + clickHandler = (panel, user, clickType, slot) -> { + this.currentMenuType = MenuType.PROPERTIES; + this.build(); + + return true; + }; + glow = this.currentMenuType.equals(MenuType.PROPERTIES); + } + case REQUIREMENTS -> { + icon = new ItemStack(Material.HOPPER); + clickHandler = (panel, user, clickType, slot) -> { + this.currentMenuType = MenuType.REQUIREMENTS; + this.build(); + + return true; + }; + glow = this.currentMenuType.equals(MenuType.REQUIREMENTS); + } + case REWARDS -> { + icon = new ItemStack(Material.DROPPER); + clickHandler = (panel, user, clickType, slot) -> { + this.currentMenuType = MenuType.REWARDS; + this.build(); + + return true; + }; + glow = this.currentMenuType.equals(MenuType.REWARDS); + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + glow = false; + } + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + glow(glow). + clickHandler(clickHandler). + build(); + } + + + /** + * This method creates buttons for default main menu. + * @param button Button which panel item must be created. + * @return PanelItem that represents given button. + */ + private PanelItem createButton(Button button) + { + final String reference = Constants.BUTTON + button.name().toLowerCase() + "."; + + final String name = this.user.getTranslation(reference + "name"); + final List description = new ArrayList<>(3); + description.add(this.user.getTranslation(reference + "description")); + + ItemStack icon; + boolean glow; + PanelItem.ClickHandler clickHandler; + + switch (button) + { + case NAME -> { + description.add(this.user.getTranslation(reference + "value", + "[name]", this.challenge.getFriendlyName())); + + icon = new ItemStack(Material.NAME_TAG); + + clickHandler = (panel, user, clickType, i) -> + { + // Create consumer that process description change + Consumer consumer = value -> + { + if (value != null) + { + this.challenge.setFriendlyName(value); + } + + this.build(); + }; + + // start conversation + ConversationUtils.createStringInput(consumer, + user, + user.getTranslation(Constants.CONVERSATIONS + "write-name"), + user.getTranslation(Constants.CONVERSATIONS + "name-changed")); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case DEPLOYED -> { + description.add(this.user.getTranslation(reference + + (this.challenge.isDeployed() ? "enabled" : "disabled"))); + + icon = new ItemStack(Material.LEVER); + clickHandler = (panel, user, clickType, slot) -> { + if (this.challenge.isValid()) + { + this.challenge.setDeployed(!this.challenge.isDeployed()); + } + else + { + Utils.sendMessage(this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "invalid-challenge", + "[challenge]", this.challenge.getFriendlyName())); + this.challenge.setDeployed(false); + } + + this.build(); + return true; + }; + glow = this.challenge.isDeployed(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle")); + } + case ICON -> { + icon = this.challenge.getIcon(); + clickHandler = (panel, user, clickType, i) -> + { + this.selectedButton = button; + this.build(); + return true; + }; + glow = this.selectedButton == button; + + if (this.selectedButton != button) + { + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + else + { + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-on-item")); + } + } + case DESCRIPTION -> { + icon = new ItemStack(Material.WRITTEN_BOOK); + + description.add(this.user.getTranslation(reference + "value")); + description.addAll(this.challenge.getDescription()); + + clickHandler = (panel, user, clickType, i) -> + { + // Create consumer that process description change + Consumer> consumer = value -> + { + if (value != null) + { + this.challenge.setDescription(value); + } + + this.build(); + }; + + if (!this.challenge.getDescription().isEmpty() && clickType.isShiftClick()) + { + // Reset to the empty value + consumer.accept(Collections.emptyList()); + } + else + { + // start conversation + ConversationUtils.createStringListInput(consumer, + user, + user.getTranslation(Constants.CONVERSATIONS + "write-description"), + user.getTranslation(Constants.CONVERSATIONS + "description-changed")); + } + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + + if (!this.challenge.getDescription().isEmpty()) + { + description.add(this.user.getTranslation(Constants.TIPS + "shift-click-to-reset")); + } + } + case ORDER -> { + description.add(this.user.getTranslation(reference + "value", + Constants.NUMBER, String.valueOf(this.challenge.getOrder()))); + + icon = new ItemStack(Material.HOPPER, Math.max(1, this.challenge.getOrder())); + clickHandler = (panel, user, clickType, i) -> { + Consumer numberConsumer = number -> { + if (number != null) + { + this.challenge.setOrder(number.intValue()); + } + + // reopen panel + this.build(); + }; + + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 0, + 2000); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case ENVIRONMENT -> { + description.add(this.user.getTranslation(this.challenge.getEnvironment().contains(World.Environment.NORMAL) ? + reference + "enabled" : reference + "disabled") + + Utils.prettifyObject(World.Environment.NORMAL, this.user)); + description.add(this.user.getTranslation(this.challenge.getEnvironment().contains(World.Environment.NETHER) ? + reference + "enabled" : reference + "disabled") + + Utils.prettifyObject(World.Environment.NETHER, this.user)); + description.add(this.user.getTranslation(this.challenge.getEnvironment().contains(World.Environment.THE_END) ? + reference + "enabled" : reference + "disabled") + + Utils.prettifyObject(World.Environment.THE_END, this.user)); + + icon = new ItemStack(Material.DROPPER); + clickHandler = (panel, user, clickType, slot) -> { + EnvironmentSelector.open(this.user, + this.challenge.getEnvironment(), + (status, value) -> { + if (status) + { + this.challenge.setEnvironment(value); + } + + this.build(); + }); + + return true; + }; + glow = false; + } + case REMOVE_ON_COMPLETE -> { + description.add(this.user.getTranslation(reference + + (this.challenge.isRemoveWhenCompleted() ? "enabled" : "disabled"))); + + if (this.challenge.isRemoveWhenCompleted()) + { + icon = new ItemStack(Material.LAVA_BUCKET); + } + else + { + icon = new ItemStack(Material.BUCKET); + } + + clickHandler = (panel, user, clickType, slot) -> { + this.challenge.setRemoveWhenCompleted(!this.challenge.isRemoveWhenCompleted()); + this.build(); + + return true; + }; + glow = this.challenge.isRemoveWhenCompleted(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle")); + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + glow = false; + } + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + glow(glow). + clickHandler(clickHandler). + build(); + } + + + /** + * This method creates buttons for requirements menu. + * @param button Button which panel item must be created. + * @return PanelItem that represents given button. + */ + private PanelItem createRequirementButton(RequirementButton button) + { + switch (button) + { + case REQUIRED_PERMISSIONS -> { + String reference = Constants.BUTTON + button.name().toLowerCase() + "."; + + String name = this.user.getTranslation(reference + "name"); + final List description = new ArrayList<>(3); + description.add(this.user.getTranslation(reference + "description")); + + if (this.challenge.getRequirements().getRequiredPermissions().isEmpty()) + { + description.add(this.user.getTranslation(reference + "none")); + } + else + { + description.add(this.user.getTranslation(reference + "title")); + + this.challenge.getRequirements().getRequiredPermissions().forEach(permission -> + description.add(this.user.getTranslation(reference + "permission", + "[permission]", permission))); + } + + ItemStack icon = new ItemStack(Material.REDSTONE_LAMP); + + PanelItem.ClickHandler clickHandler = (panel, user, clickType, i) -> + { + // Create consumer that process description change + Consumer> consumer = value -> + { + if (value != null) + { + this.challenge.getRequirements().setRequiredPermissions(new HashSet<>(value)); + } + + this.build(); + }; + + if (!this.challenge.getRequirements().getRequiredPermissions().isEmpty() && + clickType.isShiftClick()) + { + // Reset to the empty value + consumer.accept(Collections.emptyList()); + } + else + { + // start conversation + ConversationUtils.createStringListInput(consumer, + user, + user.getTranslation(Constants.CONVERSATIONS + "write-permissions"), + user.getTranslation(Constants.CONVERSATIONS + "permissions-changed")); + } + + return true; + }; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + + if (!this.challenge.getRequirements().getRequiredPermissions().isEmpty()) + { + description.add(this.user.getTranslation(Constants.TIPS + "shift-click-to-reset")); + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + clickHandler(clickHandler). + build(); + } + // Buttons for Island Requirements + case REQUIRED_ENTITIES, REMOVE_ENTITIES, REQUIRED_BLOCKS, REMOVE_BLOCKS, SEARCH_RADIUS -> { + return this.createIslandRequirementButton(button); + } + // Buttons for Inventory Requirements + case REQUIRED_ITEMS, REMOVE_ITEMS -> { + return this.createInventoryRequirementButton(button); + } + // Buttons for Other Requirements + case REQUIRED_EXPERIENCE, REMOVE_EXPERIENCE, REQUIRED_LEVEL, REQUIRED_MONEY, REMOVE_MONEY -> { + return this.createOtherRequirementButton(button); + } + // Buttons for Statistic Requirements + case STATISTIC, STATISTIC_BLOCKS, STATISTIC_ITEMS, STATISTIC_ENTITIES, STATISTIC_AMOUNT, REMOVE_STATISTIC -> { + return this.createStatisticRequirementButton(button); + } + // Default behaviour. + default -> { + return PanelItem.empty(); + } + } + } + + + /** + * This method creates buttons for island requirements menu. + * @param button Button which panel item must be created. + * @return PanelItem that represents given button. + */ + private PanelItem createIslandRequirementButton(RequirementButton button) + { + final String reference = Constants.BUTTON + button.name().toLowerCase() + "."; + + final String name = this.user.getTranslation(reference + "name"); + final List description = new ArrayList<>(3); + description.add(this.user.getTranslation(reference + "description")); + + ItemStack icon; + boolean glow; + PanelItem.ClickHandler clickHandler; + + final IslandRequirements requirements = this.challenge.getRequirements(); + + switch (button) + { + case REQUIRED_ENTITIES -> { + if (requirements.getRequiredEntities().isEmpty()) + { + description.add(this.user.getTranslation(reference + "none")); + } + else + { + description.add(this.user.getTranslation(reference + "title")); + + requirements.getRequiredEntities().forEach((entity, count) -> + description.add(this.user.getTranslation(reference + "list", + "[entity]", Utils.prettifyObject(entity, this.user), + "[number]", String.valueOf(count)))); + } + + icon = new ItemStack(Material.CREEPER_HEAD); + clickHandler = (panel, user, clickType, slot) -> { + ManageEntitiesPanel.open(this, requirements.getRequiredEntities()); + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case REMOVE_ENTITIES -> { + description.add(this.user.getTranslation(reference + + (requirements.isRemoveEntities() ? "enabled" : "disabled"))); + + icon = new ItemStack(Material.LEVER); + clickHandler = (panel, user, clickType, slot) -> { + requirements.setRemoveEntities(!requirements.isRemoveEntities()); + this.build(); + return true; + }; + glow = requirements.isRemoveEntities(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle")); + } + case REQUIRED_BLOCKS -> { + if (requirements.getRequiredBlocks().isEmpty()) + { + description.add(this.user.getTranslation(reference + "none")); + } + else + { + description.add(this.user.getTranslation(reference + "title")); + + requirements.getRequiredBlocks().forEach((block, count) -> + description.add(this.user.getTranslation(reference + "list", + "[block]", Utils.prettifyObject(block, this.user), + "[number]", String.valueOf(count)))); + } + + icon = new ItemStack(Material.STONE); + clickHandler = (panel, user, clickType, slot) -> { + ManageBlocksPanel.open(this, requirements.getRequiredBlocks()); + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case REMOVE_BLOCKS -> { + description.add(this.user.getTranslation(reference + + (requirements.isRemoveBlocks() ? "enabled" : "disabled"))); + + icon = new ItemStack(Material.LEVER); + clickHandler = (panel, user, clickType, slot) -> { + requirements.setRemoveBlocks(!requirements.isRemoveBlocks()); + this.build(); + return true; + }; + glow = requirements.isRemoveBlocks(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle")); + } + case SEARCH_RADIUS -> { + description.add(this.user.getTranslation(reference + "value", + Constants.NUMBER, String.valueOf(requirements.getSearchRadius()))); + icon = new ItemStack(Material.COBBLESTONE_WALL); + clickHandler = (panel, user, clickType, i) -> { + Consumer numberConsumer = number -> { + if (number != null) + { + requirements.setSearchRadius(number.intValue()); + } + + // reopen panel + this.build(); + }; + + int maxSearchDistance = + this.addon.getPlugin().getIWM().getAddon(this.world).map(gameModeAddon -> + gameModeAddon.getWorldSettings().getIslandDistance()).orElse(100); + + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 1, + maxSearchDistance); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + glow = false; + } + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + glow(glow). + clickHandler(clickHandler). + build(); + } + + + /** + * This method creates buttons for inventory requirements menu. + * @param button Button which panel item must be created. + * @return PanelItem that represents given button. + */ + private PanelItem createInventoryRequirementButton(RequirementButton button) + { + final String reference = Constants.BUTTON + button.name().toLowerCase() + "."; + + final String name = this.user.getTranslation(reference + "name"); + final List description = new ArrayList<>(3); + description.add(this.user.getTranslation(reference + "description")); + + ItemStack icon; + boolean glow; + PanelItem.ClickHandler clickHandler; + + final InventoryRequirements requirements = this.challenge.getRequirements(); + + switch (button) + { + case REQUIRED_ITEMS -> { + if (requirements.getRequiredItems().isEmpty()) + { + description.add(this.user.getTranslation(reference + "none")); + } + else + { + description.add(this.user.getTranslation(reference + "title")); + + Utils.groupEqualItems(requirements.getRequiredItems()).stream(). + sorted(Comparator.comparing(ItemStack::getType)). + forEach(itemStack -> + description.add(this.user.getTranslationOrNothing(reference + "list", + "[item]", Utils.prettifyObject(itemStack, this.user)))); + } + + icon = new ItemStack(Material.CHEST); + clickHandler = (panel, user, clickType, slot) -> { + ItemSelector.open(this.user, + requirements.getRequiredItems(), + (status, value) -> { + if (status) + { + requirements.setRequiredItems(value); + } + + this.build(); + }); + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case REMOVE_ITEMS -> { + description.add(this.user.getTranslation(reference + + (requirements.isTakeItems() ? "enabled" : "disabled"))); + + icon = new ItemStack(Material.LEVER); + clickHandler = (panel, user, clickType, slot) -> { + requirements.setTakeItems(!requirements.isTakeItems()); + this.build(); + return true; + }; + glow = requirements.isTakeItems(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle")); + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + glow = false; + } + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + glow(glow). + clickHandler(clickHandler). + build(); + } + + + /** + * This method creates buttons for other requirements menu. + * @param button Button which panel item must be created. + * @return PanelItem that represents given button. + */ + private PanelItem createOtherRequirementButton(RequirementButton button) + { + final String reference = Constants.BUTTON + button.name().toLowerCase() + "."; + + final String name = this.user.getTranslation(reference + "name"); + final List description = new ArrayList<>(3); + description.add(this.user.getTranslation(reference + "description")); + + ItemStack icon; + boolean glow; + PanelItem.ClickHandler clickHandler; + + final OtherRequirements requirements = this.challenge.getRequirements(); + + switch (button) + { + case REQUIRED_EXPERIENCE -> { + description.add(this.user.getTranslation(reference + "value", + Constants.NUMBER, String.valueOf(requirements.getRequiredExperience()))); + icon = new ItemStack(Material.EXPERIENCE_BOTTLE); + clickHandler = (panel, user, clickType, i) -> { + Consumer numberConsumer = number -> { + if (number != null) + { + requirements.setRequiredExperience(number.intValue()); + } + + // reopen panel + this.build(); + }; + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 0, + Integer.MAX_VALUE); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case REMOVE_EXPERIENCE -> { + description.add(this.user.getTranslation(reference + + (requirements.isTakeExperience() ? "enabled" : "disabled"))); + + icon = new ItemStack(Material.LEVER); + clickHandler = (panel, user, clickType, slot) -> { + requirements.setTakeExperience(!requirements.isTakeExperience()); + this.build(); + return true; + }; + glow = requirements.isTakeExperience(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle")); + } + case REQUIRED_LEVEL -> { + description.add(this.user.getTranslation(reference + "value", + Constants.NUMBER, String.valueOf(requirements.getRequiredIslandLevel()))); + icon = new ItemStack(this.addon.isLevelProvided() ? Material.BEACON : Material.BARRIER); + clickHandler = (panel, user, clickType, i) -> { + Consumer numberConsumer = number -> { + if (number != null) + { + requirements.setRequiredIslandLevel(number.longValue()); + } + + // reopen panel + this.build(); + }; + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 0, + Integer.MAX_VALUE); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case REQUIRED_MONEY -> { + description.add(this.user.getTranslation(reference + "value", + Constants.NUMBER, String.valueOf(requirements.getRequiredMoney()))); + icon = new ItemStack(this.addon.isEconomyProvided() ? Material.GOLD_INGOT : Material.BARRIER); + clickHandler = (panel, user, clickType, i) -> { + Consumer numberConsumer = number -> { + if (number != null) + { + requirements.setRequiredMoney(number.doubleValue()); + } + + // reopen panel + this.build(); + }; + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 0, + Double.MAX_VALUE); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case REMOVE_MONEY -> { + description.add(this.user.getTranslation(reference + + (requirements.isTakeMoney() ? "enabled" : "disabled"))); + + icon = new ItemStack(this.addon.isEconomyProvided() ? Material.LEVER : Material.BARRIER); + clickHandler = (panel, user, clickType, slot) -> { + requirements.setTakeMoney(!requirements.isTakeMoney()); + this.build(); + return true; + }; + glow = requirements.isTakeMoney(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle")); + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + glow = false; + } + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + glow(glow). + clickHandler(clickHandler). + build(); + } + + + /** + * Creates a button for statistic requirements. + * @param button Button that must be created. + * @return PanelItem button. + */ + private PanelItem createStatisticRequirementButton(RequirementButton button) + { + final String reference = Constants.BUTTON + button.name().toLowerCase() + "."; + + final String name = this.user.getTranslation(reference + "name"); + final List description = new ArrayList<>(3); + description.add(this.user.getTranslation(reference + "description")); + + ItemStack icon; + boolean glow; + PanelItem.ClickHandler clickHandler; + + final StatisticRequirements requirements = this.challenge.getRequirements(); + + switch (button) + { + case STATISTIC -> { + description.add(this.user.getTranslation(reference + "value", + "[statistic]", Utils.prettifyObject(requirements.getStatistic(), this.user))); + + icon = new ItemStack(requirements.getStatistic() == null ? Material.BARRIER : Material.PAPER); + clickHandler = (panel, user, clickType, slot) -> { + StatisticSelector.open(this.user, (status, statistic) -> { + if (status) + { + requirements.setStatistic(statistic); + requirements.setMaterial(null); + requirements.setEntity(null); + requirements.setAmount(0); + } + + this.build(); + }); + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case STATISTIC_AMOUNT -> { + description.add(this.user.getTranslation(reference + "value", + Constants.NUMBER, String.valueOf(requirements.getAmount()))); + icon = new ItemStack(Material.CHEST); + clickHandler = (panel, user, clickType, i) -> { + Consumer numberConsumer = number -> { + if (number != null) + { + requirements.setAmount(number.intValue()); + } + + // reopen panel + this.build(); + }; + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 0, + Integer.MAX_VALUE); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case REMOVE_STATISTIC -> { + description.add(this.user.getTranslation(reference + + (requirements.isReduceStatistic() ? "enabled" : "disabled"))); + + icon = new ItemStack(Material.LEVER); + clickHandler = (panel, user, clickType, slot) -> { + requirements.setReduceStatistic(!requirements.isReduceStatistic()); + this.build(); + return true; + }; + glow = requirements.isReduceStatistic(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle")); + } + case STATISTIC_BLOCKS -> { + description.add(this.user.getTranslation(reference + "value", + "[block]", Utils.prettifyObject(requirements.getMaterial(), this.user))); + + icon = requirements.getMaterial() == null ? + new ItemStack(Material.BARRIER) : + new ItemStack(requirements.getMaterial()); + clickHandler = (panel, user, clickType, slot) -> { + SingleBlockSelector.open(this.user, + SingleBlockSelector.Mode.BLOCKS, + (status, block) -> { + if (status) + { + requirements.setMaterial(block); + } + + this.build(); + }); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case STATISTIC_ITEMS -> { + description.add(this.user.getTranslation(reference + "value", + "[item]", Utils.prettifyObject(requirements.getMaterial(), this.user))); + + icon = requirements.getMaterial() == null ? + new ItemStack(Material.BARRIER) : + new ItemStack(requirements.getMaterial()); + clickHandler = (panel, user, clickType, slot) -> { + SingleBlockSelector.open(this.user, + SingleBlockSelector.Mode.ITEMS, + (status, block) -> { + if (status) + { + requirements.setMaterial(block); + } + + this.build(); + }); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case STATISTIC_ENTITIES -> { + description.add(this.user.getTranslation(reference + "value", + "[entity]", Utils.prettifyObject(requirements.getEntity(), this.user))); + + icon = requirements.getEntity() == null ? + new ItemStack(Material.BARRIER) : + new ItemStack(GuiUtils.getEntityEgg(requirements.getEntity())); + clickHandler = (panel, user, clickType, slot) -> { + SingleEntitySelector.open(this.user, + true, + (status, entity) -> { + if (status) + { + requirements.setEntity(entity); + } + + this.build(); + }); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + glow = false; + } + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + glow(glow). + clickHandler(clickHandler). + build(); + } + + + /** + * This method creates buttons for rewards menu. + * @param button Button which panel item must be created. + * @return PanelItem that represents given button. + */ + private PanelItem createRewardButton(RewardButton button) + { + final String reference = Constants.BUTTON + button.name().toLowerCase() + "."; + + final String name = this.user.getTranslation(reference + "name"); + final List description = new ArrayList<>(3); + description.add(this.user.getTranslation(reference + "description")); + + ItemStack icon; + boolean glow; + PanelItem.ClickHandler clickHandler; + + switch (button) + { + case REWARD_TEXT -> { + icon = new ItemStack(Material.WRITTEN_BOOK); + + description.add(this.user.getTranslation(reference + "value")); + description.add(this.challenge.getRewardText()); + + clickHandler = (panel, user, clickType, i) -> + { + // Create consumer that process description change + Consumer> consumer = value -> + { + if (value != null) + { + this.challenge.setRewardText(String.join("\n", value)); + } + + this.build(); + }; + + if (!this.challenge.getRewardText().isEmpty() && clickType.isShiftClick()) + { + // Reset to the empty value + consumer.accept(Collections.emptyList()); + } + else + { + // start conversation + ConversationUtils.createStringListInput(consumer, + user, + user.getTranslation(Constants.CONVERSATIONS + "write-reward-text"), + user.getTranslation(Constants.CONVERSATIONS + "reward-text-changed")); + } + + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + + if (!this.challenge.getRewardText().isEmpty()) + { + description.add(this.user.getTranslation(Constants.TIPS + "shift-click-to-reset")); + } + } + case REWARD_ITEMS -> { + + if (this.challenge.getRewardItems().isEmpty()) + { + description.add(this.user.getTranslation(reference + "none")); + } + else + { + description.add(this.user.getTranslation(reference + "title")); + + Utils.groupEqualItems(this.challenge.getRewardItems()).stream(). + sorted(Comparator.comparing(ItemStack::getType)). + forEach(itemStack -> + description.add(this.user.getTranslationOrNothing(reference + "list", + "[item]", Utils.prettifyObject(itemStack, this.user)))); + } + + icon = new ItemStack(Material.CHEST); + clickHandler = (panel, user, clickType, slot) -> { + ItemSelector.open(this.user, + this.challenge.getRewardItems(), + (status, value) -> { + if (status) + { + this.challenge.setRewardItems(value); + } + + this.build(); + }); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case REWARD_EXPERIENCE -> { + description.add(this.user.getTranslation(reference + "value", + Constants.NUMBER, String.valueOf(this.challenge.getRewardExperience()))); + icon = new ItemStack(Material.EXPERIENCE_BOTTLE); + clickHandler = (panel, user, clickType, i) -> { + Consumer numberConsumer = number -> { + if (number != null) + { + this.challenge.setRewardExperience(number.intValue()); + } + + // reopen panel + this.build(); + }; + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 0, + Integer.MAX_VALUE); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case REWARD_MONEY -> { + description.add(this.user.getTranslation(reference + "value", + Constants.NUMBER, String.valueOf(this.challenge.getRewardMoney()))); + icon = new ItemStack(this.addon.isEconomyProvided() ? Material.GOLD_INGOT : Material.BARRIER); + clickHandler = (panel, user, clickType, i) -> { + Consumer numberConsumer = number -> { + if (number != null) + { + this.challenge.setRewardMoney(number.doubleValue()); + } + + // reopen panel + this.build(); + }; + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 0, + Double.MAX_VALUE); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case REWARD_COMMANDS -> { + icon = new ItemStack(Material.COMMAND_BLOCK); + + description.add(this.user.getTranslation(reference + "value")); + description.addAll(this.challenge.getRewardCommands()); + + clickHandler = (panel, user, clickType, i) -> + { + // Create consumer that process description change + Consumer> consumer = value -> + { + if (value != null) + { + this.challenge.setRewardCommands(value); + } + + this.build(); + }; + + if (!this.challenge.getRewardCommands().isEmpty() && clickType.isShiftClick()) + { + // Reset to the empty value + consumer.accept(Collections.emptyList()); + } + else + { + // start conversation + ConversationUtils.createStringListInput(consumer, + user, + user.getTranslation(Constants.CONVERSATIONS + "write-reward-commands"), + user.getTranslation(Constants.CONVERSATIONS + "reward-commands-changed")); + } + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + + if (!this.challenge.getRewardCommands().isEmpty()) + { + description.add(this.user.getTranslation(Constants.TIPS + "shift-click-to-reset")); + } + } + case REPEATABLE -> { + description.add(this.user.getTranslation(reference + + (this.challenge.isRepeatable() ? "enabled" : "disabled"))); + + icon = new ItemStack(Material.LEVER); + clickHandler = (panel, user, clickType, slot) -> { + this.challenge.setRepeatable(!this.challenge.isRepeatable()); + this.build(); + return true; + }; + glow = this.challenge.isRepeatable(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle")); + } + case REPEAT_COUNT -> { + description.add(this.user.getTranslation(reference + "value", + Constants.NUMBER, String.valueOf(this.challenge.getMaxTimes()))); + icon = new ItemStack(Material.COBBLESTONE_WALL); + clickHandler = (panel, user, clickType, i) -> { + Consumer numberConsumer = number -> { + if (number != null) + { + this.challenge.setMaxTimes(number.intValue()); + } + + // reopen panel + this.build(); + }; + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 0, + Integer.MAX_VALUE); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case REPEAT_REWARD_TEXT -> { + icon = new ItemStack(Material.WRITTEN_BOOK); + + description.add(this.user.getTranslation(reference + "value")); + description.add(this.challenge.getRepeatRewardText()); + + clickHandler = (panel, user, clickType, i) -> + { + // Create consumer that process description change + Consumer> consumer = value -> + { + if (value != null) + { + this.challenge.setRepeatRewardText(String.join("\n", value)); + } + + this.build(); + }; + + if (!this.challenge.getRepeatRewardText().isEmpty() && clickType.isShiftClick()) + { + // Reset to the empty value + consumer.accept(Collections.emptyList()); + } + else + { + // start conversation + ConversationUtils.createStringListInput(consumer, + user, + user.getTranslation(Constants.CONVERSATIONS + "write-repeat-reward-text"), + user.getTranslation(Constants.CONVERSATIONS + "repeat-reward-text-changed")); + } + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + + if (!this.challenge.getRepeatRewardText().isEmpty()) + { + description.add(this.user.getTranslation(Constants.TIPS + "shift-click-to-reset")); + } + } + case REPEAT_REWARD_ITEMS -> { + + if (this.challenge.getRepeatItemReward().isEmpty()) + { + description.add(this.user.getTranslation(reference + "none")); + } + else + { + description.add(this.user.getTranslation(reference + "title")); + + Utils.groupEqualItems(this.challenge.getRepeatItemReward()).stream(). + sorted(Comparator.comparing(ItemStack::getType)). + forEach(itemStack -> + description.add(this.user.getTranslationOrNothing(reference + "list", + "[item]", Utils.prettifyObject(itemStack, this.user)))); + } + + icon = new ItemStack(Material.CHEST); + clickHandler = (panel, user, clickType, slot) -> { + ItemSelector.open(this.user, + this.challenge.getRewardItems(), + (status, value) -> { + if (status) + { + this.challenge.setRepeatItemReward(value); + } + + this.build(); + }); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case REPEAT_REWARD_EXPERIENCE -> { + description.add(this.user.getTranslation(reference + "value", + Constants.NUMBER, String.valueOf(this.challenge.getRepeatExperienceReward()))); + icon = new ItemStack(Material.EXPERIENCE_BOTTLE); + clickHandler = (panel, user, clickType, i) -> { + Consumer numberConsumer = number -> { + if (number != null) + { + this.challenge.setRepeatExperienceReward(number.intValue()); + } + + // reopen panel + this.build(); + }; + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 0, + Integer.MAX_VALUE); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case REPEAT_REWARD_MONEY -> { + description.add(this.user.getTranslation(reference + "value", + Constants.NUMBER, String.valueOf(this.challenge.getRepeatMoneyReward()))); + icon = new ItemStack(this.addon.isEconomyProvided() ? Material.GOLD_NUGGET : Material.BARRIER); + clickHandler = (panel, user, clickType, i) -> { + Consumer numberConsumer = number -> { + if (number != null) + { + this.challenge.setRepeatMoneyReward(number.doubleValue()); + } + + // reopen panel + this.build(); + }; + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 0, + Double.MAX_VALUE); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case REPEAT_REWARD_COMMANDS -> { + icon = new ItemStack(Material.COMMAND_BLOCK); + + description.add(this.user.getTranslation(reference + "value")); + description.addAll(this.challenge.getRepeatRewardCommands()); + + clickHandler = (panel, user, clickType, i) -> + { + // Create consumer that process description change + Consumer> consumer = value -> + { + if (value != null) + { + this.challenge.setRepeatRewardCommands(value); + } + + this.build(); + }; + + if (!this.challenge.getRepeatRewardCommands().isEmpty() && clickType.isShiftClick()) + { + // Reset to the empty value + consumer.accept(Collections.emptyList()); + } + else + { + // start conversation + ConversationUtils.createStringListInput(consumer, + user, + user.getTranslation(Constants.CONVERSATIONS + "write-repeat-reward-commands"), + user.getTranslation(Constants.CONVERSATIONS + "repeat-reward-commands-changed")); + } + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + + if (!this.challenge.getRepeatRewardCommands().isEmpty()) + { + description.add(this.user.getTranslation(Constants.TIPS + "shift-click-to-reset")); + } + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + glow = false; + } + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + glow(glow). + clickHandler(clickHandler). + build(); + } + + // --------------------------------------------------------------------- + // Section: Classes + // --------------------------------------------------------------------- + + + /** + * This class allows changing icon for Generator Tier + */ + private class IconChanger implements PanelListener + { + /** + * Process inventory click. If generator icon is selected and user clicks on item in his inventory, then change + * icon to the item from inventory. + * + * @param user the user + * @param event the event + */ + @Override + public void onInventoryClick(User user, InventoryClickEvent event) + { + // Handle icon changing + if (EditChallengePanel.this.selectedButton != null && + event.getCurrentItem() != null && + !event.getCurrentItem().getType().equals(Material.AIR) && + event.getRawSlot() > 44) + { + // set material and amount only. Other data should be removed. + + if (EditChallengePanel.this.selectedButton == Button.ICON) + { + EditChallengePanel.this.challenge.setIcon(event.getCurrentItem().clone()); + // Deselect icon + EditChallengePanel.this.selectedButton = null; + // Rebuild icon + EditChallengePanel.this.build(); + } + } + } + + + /** + * On inventory close. + * + * @param event the event + */ + @Override + public void onInventoryClose(InventoryCloseEvent event) + { + // Do nothing + } + + + /** + * Setup current listener. + */ + @Override + public void setup() + { + // Do nothing + } + } + + + // --------------------------------------------------------------------- + // Section: Enums + // --------------------------------------------------------------------- + + + /** + * Represents different types of menus + */ + private enum MenuType + { + PROPERTIES, + REQUIREMENTS, + REWARDS + } + + + /** + * Represents different buttons that could be in menus. + */ + private enum Button + { + NAME, + DEPLOYED, + ICON, + DESCRIPTION, + ORDER, + ENVIRONMENT, + REMOVE_ON_COMPLETE, + } + + + /** + * Represents different rewards buttons that are used in menus. + */ + private enum RewardButton + { + REWARD_TEXT, + REWARD_ITEMS, + REWARD_EXPERIENCE, + REWARD_MONEY, + REWARD_COMMANDS, + + REPEATABLE, + REPEAT_COUNT, + + REPEAT_REWARD_TEXT, + REPEAT_REWARD_ITEMS, + REPEAT_REWARD_EXPERIENCE, + REPEAT_REWARD_MONEY, + REPEAT_REWARD_COMMANDS, + } + + + /** + * Represents different requirement buttons that are used in menus. + */ + private enum RequirementButton + { + REQUIRED_ENTITIES, + REMOVE_ENTITIES, + REQUIRED_BLOCKS, + REMOVE_BLOCKS, + SEARCH_RADIUS, + REQUIRED_PERMISSIONS, + REQUIRED_ITEMS, + REMOVE_ITEMS, + REQUIRED_EXPERIENCE, + REMOVE_EXPERIENCE, + REQUIRED_LEVEL, + REQUIRED_MONEY, + REMOVE_MONEY, + STATISTIC, + STATISTIC_BLOCKS, + STATISTIC_ITEMS, + STATISTIC_ENTITIES, + STATISTIC_AMOUNT, + REMOVE_STATISTIC, + } + + + // --------------------------------------------------------------------- + // Section: Variables + // --------------------------------------------------------------------- + + + /** + * Variable holds challenge thats needs editing. + */ + private final Challenge challenge; + + + private Button selectedButton; + + /** + * Variable holds current active menu. + */ + private MenuType currentMenuType; +} diff --git a/src/main/java/world/bentobox/challenges/panel/admin/EditLevelGUI.java b/src/main/java/world/bentobox/challenges/panel/admin/EditLevelGUI.java deleted file mode 100644 index 094d8c7..0000000 --- a/src/main/java/world/bentobox/challenges/panel/admin/EditLevelGUI.java +++ /dev/null @@ -1,764 +0,0 @@ -package world.bentobox.challenges.panel.admin; - - -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.inventory.ItemStack; - -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.managers.ChallengesManager; -import world.bentobox.challenges.database.object.Challenge; -import world.bentobox.challenges.database.object.ChallengeLevel; -import world.bentobox.challenges.panel.CommonGUI; -import world.bentobox.challenges.panel.util.ItemSwitchGUI; -import world.bentobox.challenges.panel.util.NumberGUI; -import world.bentobox.challenges.panel.util.SelectBlocksGUI; -import world.bentobox.challenges.panel.util.SelectChallengeGUI; -import world.bentobox.challenges.panel.util.StringListGUI; -import world.bentobox.challenges.utils.GuiUtils; -import world.bentobox.challenges.utils.Utils; - - -/** - * This class contains all necessary elements to create Levels Edit GUI. - */ -public class EditLevelGUI extends CommonGUI -{ - // --------------------------------------------------------------------- - // Section: Constructors - // --------------------------------------------------------------------- - - - /** - * @param addon Addon where panel operates. - * @param world World from which panel was created. - * @param user User who created panel. - * @param topLabel Command top label which creates panel (f.e. island or ai) - * @param permissionPrefix Command permission prefix (f.e. bskyblock.) - * @param challengeLevel ChallengeLevel that must be edited. - */ - public EditLevelGUI(ChallengesAddon addon, - World world, - User user, - ChallengeLevel challengeLevel, - String topLabel, - String permissionPrefix) - { - this(addon, world, user, challengeLevel, topLabel, permissionPrefix, null); - } - - - /** - * @param addon Addon where panel operates. - * @param world World from which panel was created. - * @param user User who created panel. - * @param topLabel Command top label which creates panel (f.e. island or ai) - * @param permissionPrefix Command permission prefix (f.e. bskyblock.) - * @param challengeLevel ChallengeLevel that must be edited. - */ - public EditLevelGUI(ChallengesAddon addon, - World world, - User user, - ChallengeLevel challengeLevel, - String topLabel, - String permissionPrefix, - CommonGUI parentGUI) - { - super(addon, world, user, topLabel, permissionPrefix, parentGUI); - this.challengeLevel = challengeLevel; - this.currentMenuType = MenuType.PROPERTIES; - } - - - // --------------------------------------------------------------------- - // Section: Methods - // --------------------------------------------------------------------- - - - /** - * This method builds all necessary elements in GUI panel. - */ - @Override - public void build() - { - PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name( - this.user.getTranslation("challenges.gui.title.admin.edit-level-title")); - - GuiUtils.fillBorder(panelBuilder); - - panelBuilder.item(2, this.createMenuButton(MenuType.PROPERTIES)); - panelBuilder.item(4, this.createMenuButton(MenuType.REWARDS)); - panelBuilder.item(6, this.createMenuButton(MenuType.CHALLENGES)); - - if (this.currentMenuType.equals(MenuType.PROPERTIES)) - { - this.buildMainPropertiesPanel(panelBuilder); - } - else if (this.currentMenuType.equals(MenuType.CHALLENGES)) - { - this.buildChallengesPanel(panelBuilder); - } - else if (this.currentMenuType.equals(MenuType.REWARDS)) - { - this.buildRewardsPanel(panelBuilder); - } - - panelBuilder.item(44, this.returnButton); - - // Save challenge level every time this gui is build. - // It will ensure that changes are stored in database. - this.addon.getChallengesManager().saveLevel(this.challengeLevel); - - panelBuilder.build(); - } - - - /** - * This class populate LevelsEditGUI with main level settings. - * @param panelBuilder PanelBuilder where icons must be added. - */ - private void buildMainPropertiesPanel(PanelBuilder panelBuilder) - { - panelBuilder.item(10, this.createButton(Button.NAME)); - - panelBuilder.item(19, this.createButton(Button.ICON)); - panelBuilder.item(28, this.createButton(Button.CLOSED_ICON)); - panelBuilder.item(22, this.createButton(Button.UNLOCK_MESSAGE)); - panelBuilder.item(25, this.createButton(Button.ORDER)); - - panelBuilder.item(31, this.createButton(Button.WAIVER_AMOUNT)); - } - - - /** - * This class populate LevelsEditGUI with level rewards. - * @param panelBuilder PanelBuilder where icons must be added. - */ - private void buildRewardsPanel(PanelBuilder panelBuilder) - { - panelBuilder.item(12, this.createButton(Button.REWARD_DESCRIPTION)); - panelBuilder.item(21, this.createButton(Button.REWARD_COMMANDS)); - - panelBuilder.item(13, this.createButton(Button.REWARD_ITEM)); - panelBuilder.item(22, this.createButton(Button.REWARD_EXPERIENCE)); - panelBuilder.item(31, this.createButton(Button.REWARD_MONEY)); - } - - - /** - * This class populate LevelsEditGUI with level challenges. - * @param panelBuilder PanelBuilder where icons must be added. - */ - private void buildChallengesPanel(PanelBuilder panelBuilder) - { - List challengeList = this.addon.getChallengesManager().getLevelChallenges(this.challengeLevel); - - final int MAX_ELEMENTS = 21; - - if (this.pageIndex < 0) - { - this.pageIndex = challengeList.size() / MAX_ELEMENTS; - } - else if (this.pageIndex > (challengeList.size() / MAX_ELEMENTS)) - { - this.pageIndex = 0; - } - - int challengeIndex = MAX_ELEMENTS * this.pageIndex; - - // I want first row to be only for navigation and return button. - int index = 10; - - while (challengeIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) && - challengeIndex < challengeList.size() && - index < 36) - { - if (!panelBuilder.slotOccupied(index)) - { - panelBuilder.item(index, this.createChallengeIcon(challengeList.get(challengeIndex++))); - } - - index++; - } - - // Navigation buttons only if necessary - if (challengeList.size() > MAX_ELEMENTS) - { - panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS)); - panelBuilder.item(26, this.getButton(CommonButtons.NEXT)); - } - - panelBuilder.item(39, this.createButton(Button.ADD_CHALLENGE)); - panelBuilder.item(41, this.createButton(Button.REMOVE_CHALLENGE)); - } - - - // --------------------------------------------------------------------- - // Section: Other methods - // --------------------------------------------------------------------- - - - /** - * This method creates top menu buttons, that allows to switch "tabs". - * @param menuType Menu Type which button must be constructed. - * @return PanelItem that represents given menu type. - */ - private PanelItem createMenuButton(MenuType menuType) - { - ItemStack icon; - String name; - String description; - boolean glow; - PanelItem.ClickHandler clickHandler; - - switch (menuType) - { - case PROPERTIES: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.properties"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.properties"); - icon = new ItemStack(Material.CRAFTING_TABLE); - clickHandler = (panel, user, clickType, slot) -> { - this.currentMenuType = MenuType.PROPERTIES; - this.build(); - - return true; - }; - glow = this.currentMenuType.equals(MenuType.PROPERTIES); - break; - } - case CHALLENGES: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.challenges"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.challenges"); - icon = new ItemStack(Material.RAIL); - clickHandler = (panel, user, clickType, slot) -> { - this.currentMenuType = MenuType.CHALLENGES; - this.build(); - - return true; - }; - glow = this.currentMenuType.equals(MenuType.CHALLENGES); - break; - } - case REWARDS: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.rewards"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.rewards"); - icon = new ItemStack(Material.DROPPER); - clickHandler = (panel, user, clickType, slot) -> { - this.currentMenuType = MenuType.REWARDS; - this.build(); - - return true; - }; - glow = this.currentMenuType.equals(MenuType.REWARDS); - break; - } - default: - return null; - } - - return new PanelItemBuilder(). - icon(icon). - name(name). - description(GuiUtils.stringSplit(description, this.addon.getChallengesSettings().getLoreLineLength())). - glow(glow). - clickHandler(clickHandler). - build(); - } - - - /** - * This method creates given challenge icon. On click it should open Edit Challenge GUI. - * @param challenge Challenge which icon must be created. - * @return PanelItem that represents given challenge. - */ - private PanelItem createChallengeIcon(Challenge challenge) - { - return new PanelItemBuilder(). - name(ChatColor.translateAlternateColorCodes('&', challenge.getFriendlyName())). - description(GuiUtils.stringSplit( - challenge.getDescription(), - this.addon.getChallengesSettings().getLoreLineLength())). - icon(challenge.getIcon()). - clickHandler((panel, user1, clickType, slot) -> { - // Open challenges edit screen. - new EditChallengeGUI(this.addon, - this.world, - this.user, - challenge, - this.topLabel, - this.permissionPrefix, - this).build(); - return true; - }). - glow(!challenge.isDeployed()). - build(); - - } - - - /** - * This method creates buttons for default main menu. - * @param button Button which panel item must be created. - * @return PanelItem that represents given button. - */ - private PanelItem createButton(Button button) - { - ItemStack icon; - String name; - List description; - boolean glow; - PanelItem.ClickHandler clickHandler; - - final int lineLength = this.addon.getChallengesSettings().getLoreLineLength(); - - switch (button) - { - case NAME: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.name"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.name-level")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", this.challengeLevel.getFriendlyName())); - icon = new ItemStack(Material.DROPPER); - clickHandler = (panel, user, clickType, slot) -> { - - this.getFriendlyName(reply -> - { - if (reply != null) - { - this.challengeLevel.setFriendlyName(reply); - } - this.build(); - }, - this.user.getTranslation("challenges.gui.questions.admin.level-name"), - this.challengeLevel.getFriendlyName() - ); - - return true; - }; - glow = false; - break; - } - case ICON: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.icon"); - description = Collections.singletonList(this.user.getTranslation( - "challenges.gui.descriptions.admin.icon-level")); - icon = this.challengeLevel.getIcon(); - clickHandler = (panel, user, clickType, slot) -> { - - new SelectBlocksGUI(this.user, true, (status, materials) -> { - if (status) - { - materials.forEach(material -> - this.challengeLevel.setIcon(new ItemStack(material))); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case CLOSED_ICON: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.locked-icon"); - description = Collections.singletonList(this.user.getTranslation( - "challenges.gui.descriptions.admin.locked-icon")); - - boolean isNull = this.challengeLevel.getLockedIcon() == null; - - if (isNull) - { - icon = new ItemStack(Material.BARRIER); - } - else - { - icon = this.challengeLevel.getLockedIcon().clone(); - } - - clickHandler = (panel, user, clickType, slot) -> { - new SelectBlocksGUI(this.user, true, (status, materials) -> { - if (status) - { - materials.forEach(material -> - this.challengeLevel.setLockedIcon(new ItemStack(material))); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case UNLOCK_MESSAGE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.description"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.description")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", "|" + this.challengeLevel.getUnlockMessage())); - icon = new ItemStack(Material.WRITABLE_BOOK); - clickHandler = (panel, user, clickType, slot) -> { - new StringListGUI(this.user, this.challengeLevel.getUnlockMessage(), lineLength, (status, value) -> { - if (status) - { - String singleLineMessage = value.stream(). - map(s -> s + "|"). - collect(Collectors.joining()); - - if (singleLineMessage.endsWith("|")) - { - singleLineMessage = singleLineMessage.substring(0, singleLineMessage.length() - 1); - } - - this.challengeLevel.setUnlockMessage(singleLineMessage); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case ORDER: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.order"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.order")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", Integer.toString(this.challengeLevel.getOrder()))); - icon = new ItemStack(Material.DROPPER); - clickHandler = (panel, user, clickType, slot) -> { - new NumberGUI(this.user, this.challengeLevel.getOrder(), -1, 54, lineLength, (status, value) -> { - if (status) - { - this.challengeLevel.setOrder(value); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case WAIVER_AMOUNT: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.waiver-amount"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.waiver-amount")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", Integer.toString(this.challengeLevel.getWaiverAmount()))); - - icon = new ItemStack(Material.REDSTONE_TORCH); - clickHandler = (panel, user, clickType, slot) -> { - new NumberGUI(this.user, this.challengeLevel.getWaiverAmount(), 0, lineLength, (status, value) -> { - if (status) - { - this.challengeLevel.setWaiverAmount(value); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - - case REWARD_DESCRIPTION: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.reward-text"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reward-text-level")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", "|" + this.challengeLevel.getRewardText())); - icon = new ItemStack(Material.WRITTEN_BOOK); - clickHandler = (panel, user, clickType, slot) -> { - new StringListGUI(this.user, this.challengeLevel.getRewardText(), lineLength, (status, value) -> { - if (status) - { - String singleLineMessage = value.stream(). - map(s -> s + "|"). - collect(Collectors.joining()); - - if (singleLineMessage.endsWith("|")) - { - singleLineMessage = singleLineMessage.substring(0, singleLineMessage.length() - 1); - } - - this.challengeLevel.setRewardText(singleLineMessage); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case REWARD_ITEM: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.reward-items"); - - description = new ArrayList<>(this.challengeLevel.getRewardItems().size() + 1); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reward-items")); - - Utils.groupEqualItems(this.challengeLevel.getRewardItems()).forEach(itemStack -> - description.addAll(this.generateItemStackDescription(itemStack))); - - icon = new ItemStack(Material.CHEST); - clickHandler = (panel, user, clickType, slot) -> { - new ItemSwitchGUI(this.user, this.challengeLevel.getRewardItems(), lineLength, (status, value) -> { - if (status) - { - this.challengeLevel.setRewardItems(value); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case REWARD_EXPERIENCE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.reward-experience"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reward-experience")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", Integer.toString(this.challengeLevel.getRewardExperience()))); - icon = new ItemStack(Material.EXPERIENCE_BOTTLE); - clickHandler = (panel, user, clickType, slot) -> { - new NumberGUI(this.user, this.challengeLevel.getRewardExperience(), 0, lineLength, (status, value) -> { - if (status) - { - this.challengeLevel.setRewardExperience(value); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case REWARD_MONEY: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.reward-money"); - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reward-money")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", Integer.toString(this.challengeLevel.getRewardMoney()))); - - icon = new ItemStack(this.addon.isEconomyProvided() ? Material.GOLD_INGOT : Material.BARRIER); - clickHandler = (panel, user, clickType, slot) -> { - new NumberGUI(this.user, this.challengeLevel.getRewardMoney(), 0, lineLength, (status, value) -> { - if (status) - { - this.challengeLevel.setRewardMoney(value); - } - - this.build(); - }); - - return true; - }; - - glow = false; - break; - } - case REWARD_COMMANDS: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.reward-commands"); - description = new ArrayList<>(this.challengeLevel.getRewardCommands().size() + 1); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reward-commands")); - - for (String command : this.challengeLevel.getRewardCommands()) - { - description.add(this.user.getTranslation("challenges.gui.descriptions.command", - "[command]", command)); - } - - icon = new ItemStack(Material.COMMAND_BLOCK); - clickHandler = (panel, user, clickType, slot) -> { - new StringListGUI(this.user, this.challengeLevel.getRewardCommands(), lineLength, (status, value) -> { - if (status) - { - this.challengeLevel.setRewardCommands(value); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - - case ADD_CHALLENGE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.add-challenge"); - description = Collections.singletonList(this.user.getTranslation("challenges.gui.descriptions.admin.add-challenge")); - icon = new ItemStack(Material.WATER_BUCKET); - clickHandler = (panel, user, clickType, slot) -> { - ChallengesManager manager = this.addon.getChallengesManager(); - - // Get all challenge that is not in current level. - List challengeList = manager.getAllChallenges(this.world); - challengeList.removeAll(manager.getLevelChallenges(this.challengeLevel)); - - // Generate descriptions for these challenges - Map> challengeDescriptionMap = challengeList.stream(). - collect(Collectors.toMap(challenge -> challenge, - challenge -> this.generateChallengeDescription(challenge, this.user.getPlayer()), - (a, b) -> b, - () -> new LinkedHashMap<>(challengeList.size()))); - - // Open select gui - new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, valueSet) -> { - if (status) - { - valueSet.forEach(challenge -> manager.addChallengeToLevel(challenge, this.challengeLevel)); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case REMOVE_CHALLENGE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.remove-challenge"); - description = Collections.singletonList(this.user.getTranslation("challenges.gui.descriptions.admin.remove-challenge")); - icon = new ItemStack(Material.LAVA_BUCKET); - clickHandler = (panel, user, clickType, slot) -> { - ChallengesManager manager = this.addon.getChallengesManager(); - - // Get all challenge that is in current level. - List challengeList = manager.getLevelChallenges(this.challengeLevel); - - // Generate descriptions for these challenges - Map> challengeDescriptionMap = challengeList.stream(). - collect(Collectors.toMap(challenge -> challenge, - challenge -> this.generateChallengeDescription(challenge, this.user.getPlayer()), - (a, b) -> b, - () -> new LinkedHashMap<>(challengeList.size()))); - - // Open select gui - new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, valueSet) -> { - if (status) - { - valueSet.forEach(challenge -> manager.removeChallengeFromLevel(challenge, this.challengeLevel)); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - default: - return null; - } - - - - return new PanelItemBuilder(). - icon(icon). - name(name). - description(GuiUtils.stringSplit(description, lineLength)). - glow(glow). - clickHandler(clickHandler). - build(); - } - - - // --------------------------------------------------------------------- - // Section: Enums - // --------------------------------------------------------------------- - - - /** - * Represents different buttons that could be in menus. - */ - private enum Button - { - NAME, - ICON, - CLOSED_ICON, - UNLOCK_MESSAGE, - ORDER, - WAIVER_AMOUNT, - - REWARD_DESCRIPTION, - REWARD_ITEM, - REWARD_EXPERIENCE, - REWARD_MONEY, - REWARD_COMMANDS, - - ADD_CHALLENGE, - REMOVE_CHALLENGE - } - - - /** - * Represents different types of menus - */ - private enum MenuType - { - PROPERTIES, - CHALLENGES, - REWARDS - } - - - // --------------------------------------------------------------------- - // Section: Variables - // --------------------------------------------------------------------- - - /** - * This variable holds current challenge level that is in editing GUI. - */ - private ChallengeLevel challengeLevel; - - /** - * Variable holds current active menu. - */ - private MenuType currentMenuType; -} \ No newline at end of file diff --git a/src/main/java/world/bentobox/challenges/panel/admin/EditLevelPanel.java b/src/main/java/world/bentobox/challenges/panel/admin/EditLevelPanel.java new file mode 100644 index 0000000..93995b6 --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/admin/EditLevelPanel.java @@ -0,0 +1,876 @@ +package world.bentobox.challenges.panel.admin; + + +import java.util.*; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.ItemStack; + +import world.bentobox.bentobox.api.panels.PanelItem; +import world.bentobox.bentobox.api.panels.PanelListener; +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.bentobox.util.Util; +import world.bentobox.challenges.ChallengesAddon; +import world.bentobox.challenges.managers.ChallengesManager; +import world.bentobox.challenges.database.object.Challenge; +import world.bentobox.challenges.database.object.ChallengeLevel; +import world.bentobox.challenges.panel.CommonPagedPanel; +import world.bentobox.challenges.panel.CommonPanel; +import world.bentobox.challenges.panel.ConversationUtils; +import world.bentobox.challenges.panel.util.ItemSelector; +import world.bentobox.challenges.panel.util.ChallengeSelector; +import world.bentobox.challenges.utils.Constants; +import world.bentobox.challenges.utils.GuiUtils; +import world.bentobox.challenges.utils.Utils; + + +/** + * This class contains all necessary elements to create Levels Edit GUI. + */ +public class EditLevelPanel extends CommonPagedPanel +{ + // --------------------------------------------------------------------- + // Section: Constructors + // --------------------------------------------------------------------- + + + /** + * @param addon Addon where panel operates. + * @param world World from which panel was created. + * @param user User who created panel. + * @param topLabel Command top label which creates panel (f.e. island or ai) + * @param permissionPrefix Command permission prefix (f.e. bskyblock.) + * @param challengeLevel ChallengeLevel that must be edited. + */ + private EditLevelPanel(ChallengesAddon addon, + User user, + World world, + String topLabel, + String permissionPrefix, + ChallengeLevel challengeLevel) + { + super(addon, user, world, topLabel, permissionPrefix); + this.challengeLevel = challengeLevel; + this.currentMenuType = MenuType.PROPERTIES; + } + + + /** + * @param challengeLevel ChallengeLevel that must be edited. + */ + private EditLevelPanel(CommonPanel parentGUI, ChallengeLevel challengeLevel) + { + super(parentGUI); + this.challengeLevel = challengeLevel; + this.currentMenuType = MenuType.PROPERTIES; + } + + + /** + * Open the Challenges Level Edit GUI. + * + * @param addon the addon + * @param world the world + * @param user the user + * @param topLabel the top label + * @param permissionPrefix the permission prefix + * @param level - level that needs editing + */ + public static void open(ChallengesAddon addon, + User user, + World world, + String topLabel, + String permissionPrefix, + ChallengeLevel level) + { + new EditLevelPanel(addon, user, world, topLabel, permissionPrefix, level).build(); + } + + + /** + * Open the Challenges Level Edit GUI. + * + * @param panel - Parent Panel + * @param level - level that needs editing + */ + public static void open(CommonPanel panel, ChallengeLevel level) + { + new EditLevelPanel(panel, level).build(); + } + + + // --------------------------------------------------------------------- + // Section: Methods + // --------------------------------------------------------------------- + + + /** + * This method builds all necessary elements in GUI panel. + */ + @Override + protected void build() + { + PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name( + this.user.getTranslation(Constants.TITLE + "edit-level", + "[level]", this.challengeLevel.getFriendlyName())); + + GuiUtils.fillBorder(panelBuilder); + + panelBuilder.item(2, this.createMenuButton(MenuType.PROPERTIES)); + panelBuilder.item(4, this.createMenuButton(MenuType.REWARDS)); + panelBuilder.item(6, this.createMenuButton(MenuType.CHALLENGES)); + + if (this.currentMenuType.equals(MenuType.PROPERTIES)) + { + this.buildMainPropertiesPanel(panelBuilder); + } + else if (this.currentMenuType.equals(MenuType.CHALLENGES)) + { + this.buildChallengesPanel(panelBuilder); + } + else if (this.currentMenuType.equals(MenuType.REWARDS)) + { + this.buildRewardsPanel(panelBuilder); + } + + panelBuilder.item(44, this.returnButton); + + // Save challenge level every time this gui is build. + // It will ensure that changes are stored in database. + this.addon.getChallengesManager().saveLevel(this.challengeLevel); + + panelBuilder.build(); + } + + + /** + * This class populate LevelsEditGUI with main level settings. + * @param panelBuilder PanelBuilder where icons must be added. + */ + private void buildMainPropertiesPanel(PanelBuilder panelBuilder) + { + panelBuilder.listener(new IconChanger()); + + panelBuilder.item(10, this.createButton(Button.NAME)); + + panelBuilder.item(19, this.createButton(Button.ICON)); + panelBuilder.item(28, this.createButton(Button.LOCKED_ICON)); + panelBuilder.item(22, this.createButton(Button.DESCRIPTION)); + panelBuilder.item(25, this.createButton(Button.ORDER)); + + panelBuilder.item(31, this.createButton(Button.WAIVER_AMOUNT)); + } + + + /** + * This class populate LevelsEditGUI with level rewards. + * @param panelBuilder PanelBuilder where icons must be added. + */ + private void buildRewardsPanel(PanelBuilder panelBuilder) + { + panelBuilder.item(12, this.createButton(Button.REWARD_TEXT)); + panelBuilder.item(21, this.createButton(Button.REWARD_COMMANDS)); + + panelBuilder.item(13, this.createButton(Button.REWARD_ITEMS)); + panelBuilder.item(22, this.createButton(Button.REWARD_EXPERIENCE)); + panelBuilder.item(31, this.createButton(Button.REWARD_MONEY)); + } + + + /** + * This class populate LevelsEditGUI with level challenges. + * @param panelBuilder PanelBuilder where icons must be added. + */ + private void buildChallengesPanel(PanelBuilder panelBuilder) + { + List challengeList = this.addon.getChallengesManager().getLevelChallenges(this.challengeLevel); + + this.populateElements(panelBuilder, + challengeList, + o -> this.createChallengeIcon((Challenge) o)); + + panelBuilder.item(39, this.createButton(Button.ADD_CHALLENGES)); + panelBuilder.item(41, this.createButton(Button.REMOVE_CHALLENGES)); + } + + + // --------------------------------------------------------------------- + // Section: Other methods + // --------------------------------------------------------------------- + + + /** + * This method creates top menu buttons, that allows to switch "tabs". + * @param menuType Menu Type which button must be constructed. + * @return PanelItem that represents given menu type. + */ + private PanelItem createMenuButton(MenuType menuType) + { + final String reference = Constants.BUTTON + menuType.name().toLowerCase() + "."; + + final String name = this.user.getTranslation(reference + "name"); + final List description = new ArrayList<>(3); + description.add(this.user.getTranslation(reference + "description")); + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-select")); + + ItemStack icon; + boolean glow; + PanelItem.ClickHandler clickHandler; + + switch (menuType) + { + case PROPERTIES -> { + icon = new ItemStack(Material.CRAFTING_TABLE); + clickHandler = (panel, user, clickType, slot) -> { + this.currentMenuType = MenuType.PROPERTIES; + this.build(); + + return true; + }; + glow = this.currentMenuType.equals(MenuType.PROPERTIES); + } + case CHALLENGES -> { + icon = new ItemStack(Material.RAIL); + clickHandler = (panel, user, clickType, slot) -> { + this.currentMenuType = MenuType.CHALLENGES; + this.build(); + + return true; + }; + glow = this.currentMenuType.equals(MenuType.CHALLENGES); + } + case REWARDS -> { + icon = new ItemStack(Material.DROPPER); + clickHandler = (panel, user, clickType, slot) -> { + this.currentMenuType = MenuType.REWARDS; + this.build(); + + return true; + }; + glow = this.currentMenuType.equals(MenuType.REWARDS); + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + glow = false; + } + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + glow(glow). + clickHandler(clickHandler). + build(); + } + + + /** + * This method creates given challenge icon. On click it should open Edit Challenge GUI. + * @param challenge Challenge which icon must be created. + * @return PanelItem that represents given challenge. + */ + private PanelItem createChallengeIcon(Challenge challenge) + { + return new PanelItemBuilder(). + name(Util.translateColorCodes(challenge.getFriendlyName())). + description(this.generateChallengeDescription(challenge, null)). + description(""). + description(this.user.getTranslation(Constants.TIPS + "click-to-edit")). + icon(challenge.getIcon()). + clickHandler((panel, user, clickType, slot) -> { + // Open challenges edit screen. + EditChallengePanel.open(this, challenge); + return true; + }). + glow(!challenge.isDeployed()). + build(); + } + + + /** + * This method creates buttons for default main menu. + * @param button Button which panel item must be created. + * @return PanelItem that represents given button. + */ + private PanelItem createButton(Button button) + { + final String reference = Constants.BUTTON + button.name().toLowerCase() + "."; + + final String name = this.user.getTranslation(reference + "name"); + final List description = new ArrayList<>(3); + description.add(this.user.getTranslation(reference + "description")); + + ItemStack icon; + boolean glow; + PanelItem.ClickHandler clickHandler; + + switch (button) + { + case REWARD_TEXT -> { + icon = new ItemStack(Material.WRITTEN_BOOK); + + description.add(this.user.getTranslation(reference + "value")); + description.add(this.challengeLevel.getRewardText()); + + clickHandler = (panel, user, clickType, i) -> + { + // Create consumer that process description change + Consumer> consumer = value -> + { + if (value != null) + { + this.challengeLevel.setRewardText(String.join("\n", value)); + } + + this.build(); + }; + + if (!this.challengeLevel.getRewardText().isEmpty() && clickType.isShiftClick()) + { + // Reset to the empty value + consumer.accept(Collections.emptyList()); + } + else + { + // start conversation + ConversationUtils.createStringListInput(consumer, + user, + user.getTranslation(Constants.CONVERSATIONS + "write-reward-text"), + user.getTranslation(Constants.CONVERSATIONS + "reward-text-changed")); + } + + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + + if (!this.challengeLevel.getRewardText().isEmpty()) + { + description.add(this.user.getTranslation(Constants.TIPS + "shift-click-to-reset")); + } + } + case REWARD_ITEMS -> { + + if (this.challengeLevel.getRewardItems().isEmpty()) + { + description.add(this.user.getTranslation(reference + "none")); + } + else + { + description.add(this.user.getTranslation(reference + "title")); + + Utils.groupEqualItems(this.challengeLevel.getRewardItems()).stream(). + sorted(Comparator.comparing(ItemStack::getType)). + forEach(itemStack -> + description.add(this.user.getTranslationOrNothing(reference + "list", + "[item]", Utils.prettifyObject(itemStack, this.user)))); + } + + icon = new ItemStack(Material.CHEST); + clickHandler = (panel, user, clickType, slot) -> { + ItemSelector.open(this.user, + this.challengeLevel.getRewardItems(), + (status, value) -> { + if (status) + { + this.challengeLevel.setRewardItems(value); + } + + this.build(); + }); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case REWARD_EXPERIENCE -> { + description.add(this.user.getTranslation(reference + "value", + Constants.NUMBER, String.valueOf(this.challengeLevel.getRewardExperience()))); + icon = new ItemStack(Material.EXPERIENCE_BOTTLE); + clickHandler = (panel, user, clickType, i) -> { + Consumer numberConsumer = number -> { + if (number != null) + { + this.challengeLevel.setRewardExperience(number.intValue()); + } + + // reopen panel + this.build(); + }; + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 0, + Integer.MAX_VALUE); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case REWARD_MONEY -> { + description.add(this.user.getTranslation(reference + "value", + Constants.NUMBER, String.valueOf(this.challengeLevel.getRewardMoney()))); + icon = new ItemStack(this.addon.isEconomyProvided() ? Material.GOLD_INGOT : Material.BARRIER); + clickHandler = (panel, user, clickType, i) -> { + Consumer numberConsumer = number -> { + if (number != null) + { + this.challengeLevel.setRewardMoney(number.doubleValue()); + } + + // reopen panel + this.build(); + }; + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 0, + Double.MAX_VALUE); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case REWARD_COMMANDS -> { + icon = new ItemStack(Material.COMMAND_BLOCK); + + description.add(this.user.getTranslation(reference + "value")); + description.addAll(this.challengeLevel.getRewardCommands()); + + clickHandler = (panel, user, clickType, i) -> + { + // Create consumer that process description change + Consumer> consumer = value -> + { + if (value != null) + { + this.challengeLevel.setRewardCommands(value); + } + + this.build(); + }; + + if (!this.challengeLevel.getRewardCommands().isEmpty() && clickType.isShiftClick()) + { + // Reset to the empty value + consumer.accept(Collections.emptyList()); + } + else + { + // start conversation + ConversationUtils.createStringListInput(consumer, + user, + user.getTranslation(Constants.CONVERSATIONS + "write-reward-commands"), + user.getTranslation(Constants.CONVERSATIONS + "reward-commands-changed")); + } + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + + if (!this.challengeLevel.getRewardCommands().isEmpty()) + { + description.add(this.user.getTranslation(Constants.TIPS + "shift-click-to-reset")); + } + } + case NAME -> { + description.add(this.user.getTranslation(reference + "value", + "[name]", this.challengeLevel.getFriendlyName())); + + icon = new ItemStack(Material.NAME_TAG); + + clickHandler = (panel, user, clickType, i) -> + { + // Create consumer that process description change + Consumer consumer = value -> + { + if (value != null) + { + this.challengeLevel.setFriendlyName(value); + } + + this.build(); + }; + + // start conversation + ConversationUtils.createStringInput(consumer, + user, + user.getTranslation(Constants.CONVERSATIONS + "write-name"), + user.getTranslation(Constants.CONVERSATIONS + "name-changed")); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case DESCRIPTION -> { + icon = new ItemStack(Material.WRITTEN_BOOK); + + description.add(this.user.getTranslation(reference + "value")); + description.add(this.challengeLevel.getUnlockMessage()); + + clickHandler = (panel, user, clickType, i) -> + { + // Create consumer that process description change + Consumer> consumer = value -> + { + if (value != null) + { + this.challengeLevel.setUnlockMessage(String.join("\n", value)); + } + + this.build(); + }; + + if (!this.challengeLevel.getUnlockMessage().isEmpty() && clickType.isShiftClick()) + { + // Reset to the empty value + consumer.accept(Collections.emptyList()); + } + else + { + // start conversation + ConversationUtils.createStringListInput(consumer, + user, + user.getTranslation(Constants.CONVERSATIONS + "write-description"), + user.getTranslation(Constants.CONVERSATIONS + "description-changed")); + } + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + + if (!this.challengeLevel.getUnlockMessage().isEmpty()) + { + description.add(this.user.getTranslation(Constants.TIPS + "shift-click-to-reset")); + } + } + case ICON, LOCKED_ICON -> { + icon = button == Button.LOCKED_ICON ? + this.challengeLevel.getLockedIcon() : + this.challengeLevel.getIcon(); + + clickHandler = (panel, user, clickType, i) -> + { + this.selectedButton = button; + this.build(); + return true; + }; + + if (this.selectedButton != button) + { + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + else + { + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-on-item")); + } + + glow = this.selectedButton == button; + } + case ORDER -> { + description.add(this.user.getTranslation(reference + "value", + Constants.NUMBER, String.valueOf(this.challengeLevel.getOrder()))); + + icon = new ItemStack(Material.HOPPER, Math.max(1, this.challengeLevel.getOrder())); + clickHandler = (panel, user, clickType, i) -> { + Consumer numberConsumer = number -> { + if (number != null) + { + this.challengeLevel.setOrder(number.intValue()); + } + + // reopen panel + this.build(); + }; + + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 0, + 2000); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case WAIVER_AMOUNT -> { + description.add(this.user.getTranslation(reference + "value", + Constants.NUMBER, String.valueOf(this.challengeLevel.getWaiverAmount()))); + + icon = new ItemStack(Material.HOPPER, Math.max(1, this.challengeLevel.getWaiverAmount())); + clickHandler = (panel, user, clickType, i) -> { + Consumer numberConsumer = number -> { + if (number != null) + { + this.challengeLevel.setWaiverAmount(number.intValue()); + } + + // reopen panel + this.build(); + }; + + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 0, + 2000); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case ADD_CHALLENGES -> { + icon = new ItemStack(Material.WATER_BUCKET); + clickHandler = (panel, user, clickType, slot) -> { + ChallengesManager manager = this.addon.getChallengesManager(); + + // Get all challenge that is not in current level. + List challengeList = manager.getAllChallenges(this.world); + challengeList.removeAll(manager.getLevelChallenges(this.challengeLevel)); + + // Generate descriptions for these challenges + Map> challengeDescriptionMap = challengeList.stream(). + collect(Collectors.toMap(challenge -> challenge, + challenge -> this.generateChallengeDescription(challenge, null), + (a, b) -> b, + () -> new LinkedHashMap<>(challengeList.size()))); + + // Open select gui + ChallengeSelector.open(this.user, + Material.BLUE_STAINED_GLASS_PANE, + challengeDescriptionMap, + (status, valueSet) -> { + if (status) + { + valueSet.forEach(challenge -> + manager.addChallengeToLevel(challenge, this.challengeLevel)); + } + + this.build(); + }); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-add")); + } + case REMOVE_CHALLENGES -> { + icon = new ItemStack(Material.LAVA_BUCKET); + clickHandler = (panel, user, clickType, slot) -> { + ChallengesManager manager = this.addon.getChallengesManager(); + + // Get all challenge that is in current level. + List challengeList = manager.getLevelChallenges(this.challengeLevel); + + // Generate descriptions for these challenges + Map> challengeDescriptionMap = challengeList.stream(). + collect(Collectors.toMap(challenge -> challenge, + challenge -> this.generateChallengeDescription(challenge, null), + (a, b) -> b, + () -> new LinkedHashMap<>(challengeList.size()))); + + // Open select gui + ChallengeSelector.open(this.user, + Material.RED_STAINED_GLASS_PANE, + challengeDescriptionMap, + (status, valueSet) -> { + if (status) + { + valueSet.forEach(challenge -> + manager.removeChallengeFromLevel(challenge, this.challengeLevel)); + } + + this.build(); + }); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-remove")); + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + glow = false; + } + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + glow(glow). + clickHandler(clickHandler). + build(); + } + + + // --------------------------------------------------------------------- + // Section: Classes + // --------------------------------------------------------------------- + + + /** + * This class allows changing icon for Generator Tier + */ + private class IconChanger implements PanelListener + { + /** + * Process inventory click. If generator icon is selected and user clicks on item in his inventory, then change + * icon to the item from inventory. + * + * @param user the user + * @param event the event + */ + @Override + public void onInventoryClick(User user, InventoryClickEvent event) + { + // Handle icon changing + if (EditLevelPanel.this.selectedButton != null && + event.getCurrentItem() != null && + !event.getCurrentItem().getType().equals(Material.AIR) && + event.getRawSlot() > 44) + { + // set material and amount only. Other data should be removed. + + if (EditLevelPanel.this.selectedButton == Button.ICON) + { + EditLevelPanel.this.challengeLevel.setIcon(event.getCurrentItem().clone()); + // Deselect icon + EditLevelPanel.this.selectedButton = null; + // Rebuild icon + EditLevelPanel.this.build(); + } + else if (EditLevelPanel.this.selectedButton == Button.LOCKED_ICON) + { + EditLevelPanel.this.challengeLevel.setLockedIcon(event.getCurrentItem().clone()); + // Deselect icon + EditLevelPanel.this.selectedButton = null; + // Rebuild icon + EditLevelPanel.this.build(); + } + } + } + + + /** + * On inventory close. + * + * @param event the event + */ + @Override + public void onInventoryClose(InventoryCloseEvent event) + { + // Do nothing + } + + + /** + * Setup current listener. + */ + @Override + public void setup() + { + // Do nothing + } + } + + + // --------------------------------------------------------------------- + // Section: Enums + // --------------------------------------------------------------------- + + + /** + * Represents different buttons that could be in menus. + */ + private enum Button + { + NAME, + ICON, + LOCKED_ICON, + DESCRIPTION, + ORDER, + WAIVER_AMOUNT, + + REWARD_TEXT, + REWARD_ITEMS, + REWARD_EXPERIENCE, + REWARD_MONEY, + REWARD_COMMANDS, + + ADD_CHALLENGES, + REMOVE_CHALLENGES + } + + + /** + * Represents different types of menus + */ + private enum MenuType + { + PROPERTIES, + CHALLENGES, + REWARDS + } + + + // --------------------------------------------------------------------- + // Section: Variables + // --------------------------------------------------------------------- + + /** + * This variable holds current challenge level that is in editing GUI. + */ + private final ChallengeLevel challengeLevel; + + /** + * Variable holds current active menu. + */ + private MenuType currentMenuType; + + private Button selectedButton; +} \ No newline at end of file diff --git a/src/main/java/world/bentobox/challenges/panel/admin/EditLoreGUI.java b/src/main/java/world/bentobox/challenges/panel/admin/EditLoreGUI.java deleted file mode 100644 index 860de1a..0000000 --- a/src/main/java/world/bentobox/challenges/panel/admin/EditLoreGUI.java +++ /dev/null @@ -1,638 +0,0 @@ -package world.bentobox.challenges.panel.admin; - - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -import org.bukkit.Material; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryCloseEvent; -import org.bukkit.inventory.ItemStack; -import org.eclipse.jdt.annotation.Nullable; - -import world.bentobox.bentobox.api.panels.PanelItem; -import world.bentobox.bentobox.api.panels.PanelListener; -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.config.SettingsUtils.ChallengeLore; -import world.bentobox.challenges.config.SettingsUtils.LevelLore; -import world.bentobox.challenges.panel.CommonGUI; -import world.bentobox.challenges.utils.GuiUtils; - - -/** - * This class allows to change Input ItemStacks to different ItemStacks. - */ -public class EditLoreGUI extends CommonGUI -{ - public EditLoreGUI(CommonGUI parent, LoreType loreType) - { - super(parent); - - this.lore = loreType; - this.activeValues = new ArrayList<>(); - - switch (this.lore) - { - case CHALLENGES: - - for (ChallengeLore lore : this.addon.getChallengesSettings().getChallengeLoreMessage()) - { - this.activeValues.add(lore.name()); - } - - break; - case LEVELS: - - for (LevelLore lore : this.addon.getChallengesSettings().getLevelLoreMessage()) - { - this.activeValues.add(lore.name()); - } - - break; - } - } - - - /** - * This is static call method for easier GUI opening. - * @param parent Parent GUI. - * @param loreType loreType that will be edited. - */ - public static void open(CommonGUI parent, LoreType loreType) - { - new EditLoreGUI(parent, loreType).build(); - } - - - // --------------------------------------------------------------------- - // Section: Methods - // --------------------------------------------------------------------- - - - /** - * This method builds panel that allows to change given number value. - */ - @Override - public void build() - { - PanelBuilder panelBuilder = new PanelBuilder(). - name(this.user.getTranslation("challenges.gui.title.admin.lore-edit")). - user(this.user). - listener(new CustomPanelListener()); - - GuiUtils.fillBorder(panelBuilder, 5, Material.MAGENTA_STAINED_GLASS_PANE); - - // Define all active buttons - panelBuilder.item(1, this.getButton(Button.SAVE)); - - panelBuilder.item(3, this.getButton(Button.ADD)); - panelBuilder.item(4, this.getButton(Button.REMOVE)); - - // TODO: Need 2 View Buttons - // One for closes / One for opened. - // panelBuilder.item(6, this.getButton(Button.VIEW)); - - panelBuilder.item(44, this.returnButton); - - // necessary as I have a border around this GUI - int currentIndex = 10; - - // Only 21 elements will be displayed. On porpoise! - for (int i = 0; i < this.activeValues.size() || i > 21; i++) - { - panelBuilder.item(currentIndex++, this.getLoreButton(this.activeValues.get(i))); - - // Border element - if (currentIndex % 9 == 8) - { - currentIndex += 2; - } - - // Just in case. Should never occur. - if (currentIndex % 9 == 0) - { - currentIndex++; - } - } - - panelBuilder.build(); - } - - - /** - * This method create button that does some functionality in current gui. - * @param button Button functionality. - * @return PanelItem. - */ - private PanelItem getButton(Button button) - { - ItemStack icon; - String name; - List description; - PanelItem.ClickHandler clickHandler; - - switch (button) - { - case SAVE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.save"); - description = Collections.emptyList(); - icon = new ItemStack(Material.COMMAND_BLOCK); - clickHandler = (panel, user, clickType, slot) -> { - - switch (this.lore) - { - case CHALLENGES: - { - List lore = this.activeValues.stream(). - map(ChallengeLore::valueOf). - collect(Collectors.toCollection(() -> new ArrayList<>(this.activeValues.size()))); - - this.addon.getChallengesSettings().setChallengeLoreMessage(lore); - - break; - } - case LEVELS: - { - List lore = this.activeValues.stream(). - map(LevelLore::valueOf). - collect(Collectors.toCollection(() -> new ArrayList<>(this.activeValues.size()))); - - this.addon.getChallengesSettings().setLevelLoreMessage(lore); - - break; - } - } - - // Save and return to parent gui. - this.parentGUI.build(); - - return true; - }; - break; - } - case ADD: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.add"); - description = Collections.emptyList(); - icon = new ItemStack(Material.GREEN_STAINED_GLASS_PANE); - clickHandler = (panel, user, clickType, slot) -> { - new AddLoreElementGUI(element -> { - this.activeValues.add(element); - this.build(); - }); - - return true; - }; - - break; - } - case REMOVE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.remove-selected"); - description = Collections.emptyList(); - icon = new ItemStack(Material.RED_STAINED_GLASS_PANE); - clickHandler = (panel, user, clickType, slot) -> { - new RemoveLoreElementGUI((element, index) -> { - if (this.activeValues.get(index).equals(element)) - { - this.activeValues.remove(element); - } - - this.build(); - }); - - return true; - }; - - break; - } - case VIEW: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.view"); - description = Collections.emptyList(); - icon = new ItemStack(Material.YELLOW_STAINED_GLASS_PANE); - clickHandler = (panel, user, clickType, slot) -> { - return true; - }; - - break; - } - default: - return null; - } - - return new PanelItemBuilder(). - icon(icon). - name(name). - description(GuiUtils.stringSplit(description, this.addon.getChallengesSettings().getLoreLineLength())). - glow(false). - clickHandler(clickHandler). - build(); - } - - - /** - * This method creates button for lore element. - * @param loreElement String that represents current lore element. - * @return PanelItem. - */ - @Nullable - private PanelItem getLoreButton(String loreElement) - { - switch (this.lore) - { - case CHALLENGES: - return this.getChallengeLoreButton(loreElement); - case LEVELS: - return this.getLevelLoreButton(loreElement); - default: - // this should never happen! - return null; - } - } - - - /** - * This method creates button for challenge lore element. - * @param loreElement String that represents current challenge lore element. - * @return PanelItem. - */ - private PanelItem getChallengeLoreButton(String loreElement) - { - Material icon; - String name = loreElement; - List description = new ArrayList<>(); - description.add(this.user.getTranslation(REFERENCE_DESCRIPTION + "lore." + loreElement.toLowerCase())); - - PanelItem.ClickHandler clickHandler = (panel, user1, clickType, slot) -> true; - - switch (ChallengeLore.valueOf(loreElement)) - { - case LEVEL: - { - icon = Material.DIRT; - break; - } - case STATUS: - { - icon = Material.LEVER; - break; - } - case COUNT: - { - icon = Material.REPEATER; - break; - } - case DESCRIPTION: - { - icon = Material.WRITTEN_BOOK; - break; - } - case WARNINGS: - { - icon = Material.LAVA_BUCKET; - break; - } - case ENVIRONMENT: - { - icon = Material.GLASS; - break; - } - case REQUIREMENTS: - { - icon = Material.HOPPER; - break; - } - case REWARD_TEXT: - { - icon = Material.PAPER; - break; - } - case REWARD_OTHER: - { - icon = Material.CHEST; - break; - } - case REWARD_ITEMS: - { - icon = Material.TRAPPED_CHEST; - break; - } - case REWARD_COMMANDS: - { - icon = Material.COMMAND_BLOCK; - break; - } - default: - { - icon = Material.BARRIER; - break; - } - } - - return new PanelItemBuilder(). - name(name). - icon(icon). - description(GuiUtils.stringSplit(description, this.addon.getChallengesSettings().getLoreLineLength())). - clickHandler(clickHandler). - glow(false). - build(); - } - - - /** - * This method creates button for challenge level lore element. - * @param loreElement String that represents current challenge level lore element. - * @return PanelItem. - */ - private PanelItem getLevelLoreButton(String loreElement) - { - Material icon; - String name = loreElement; - List description = new ArrayList<>(); - description.add(this.user.getTranslation(REFERENCE_DESCRIPTION + "lore." + loreElement.toLowerCase())); - - PanelItem.ClickHandler clickHandler = (panel, user1, clickType, slot) -> true; - - switch (LevelLore.valueOf(loreElement)) - { - case LEVEL_STATUS: - { - icon = Material.DIRT; - break; - } - case CHALLENGE_COUNT: - { - icon = Material.REPEATER; - break; - } - case UNLOCK_MESSAGE: - { - icon = Material.WRITTEN_BOOK; - break; - } - case WAIVER_AMOUNT: - { - icon = Material.COMPARATOR; - break; - } - case LEVEL_REWARD_TEXT: - { - icon = Material.PAPER; - break; - } - case LEVEL_REWARD_OTHER: - { - icon = Material.CHEST; - break; - } - case LEVEL_REWARD_ITEMS: - { - icon = Material.TRAPPED_CHEST; - break; - } - case LEVEL_REWARD_COMMANDS: - { - icon = Material.COMMAND_BLOCK; - break; - } - default: - { - icon = Material.BARRIER; - break; - } - } - - return new PanelItemBuilder(). - name(name). - icon(icon). - description(GuiUtils.stringSplit(description, this.addon.getChallengesSettings().getLoreLineLength())). - clickHandler(clickHandler). - glow(false). - build(); - } - - - // --------------------------------------------------------------------- - // Section: Select GUI - // --------------------------------------------------------------------- - - - /** - * This class opens new GUI that add an element from all available lore values. - */ - private class AddLoreElementGUI - { - private AddLoreElementGUI(Consumer selectedElement) - { - PanelBuilder panelBuilder = new PanelBuilder(). - name(EditLoreGUI.this.user.getTranslation("challenges.gui.title.admin.lore-add")). - user(EditLoreGUI.this.user); - - GuiUtils.fillBorder(panelBuilder, 5, Material.MAGENTA_STAINED_GLASS_PANE); - - int currentIndex = 10; - - List values = new ArrayList<>(); - - // Populate list with all elements. - switch (EditLoreGUI.this.lore) - { - case CHALLENGES: - for (ChallengeLore value : ChallengeLore.values()) - { - values.add(value.name()); - } - break; - case LEVELS: - for (LevelLore value : LevelLore.values()) - { - values.add(value.name()); - } - break; - } - - for (String value : values) - { - PanelItem item = EditLoreGUI.this.getLoreButton(value); - if (item != null) { - item.setClickHandler((panel, user1, clickType, slot) -> { - selectedElement.accept(value); - return true; - }); - - panelBuilder.item(currentIndex++, item); - - - // Border element - if (currentIndex % 9 == 8) - { - currentIndex += 2; - } - - // Just in case. Should never occur. - if (currentIndex % 9 == 0) - { - currentIndex++; - } - - // Just in case. Should never occur. - if (currentIndex > 35) - { - break; - } - } - } - - panelBuilder.build(); - } - } - - - /** - * This class opens new GUI that remove an element from all available lore values. - */ - private class RemoveLoreElementGUI - { - private RemoveLoreElementGUI(BiConsumer selectedElement) - { - PanelBuilder panelBuilder = new PanelBuilder(). - name(EditLoreGUI.this.user.getTranslation("challenges.gui.title.admin.lore-remove")). - user(EditLoreGUI.this.user); - - GuiUtils.fillBorder(panelBuilder, 5, Material.MAGENTA_STAINED_GLASS_PANE); - - int currentIndex = 10; - - List values = EditLoreGUI.this.activeValues; - - for (int i = 0; i < values.size(); i++) - { - final int counter = i; - - String value = values.get(counter); - PanelItem item = EditLoreGUI.this.getLoreButton(value); - if (item != null) { - item.setClickHandler((panel, user1, clickType, slot) -> { - selectedElement.accept(value, counter); - return true; - }); - - panelBuilder.item(currentIndex++, item); - - // Border element - if (currentIndex % 9 == 8) - { - currentIndex += 2; - } - - // Just in case. Should never occur. - if (currentIndex % 9 == 0) - { - currentIndex++; - } - - // Just in case. Should never occur. - if (currentIndex > 35) - { - break; - } - } - } - - panelBuilder.build(); - } - } - - - // --------------------------------------------------------------------- - // Section: Private classes - // --------------------------------------------------------------------- - - - /** - * This CustomPanelListener allows to move items in current panel. - */ - private class CustomPanelListener implements PanelListener - { - @Override - public void setup() - { - } - - - @Override - public void onInventoryClose(InventoryCloseEvent inventoryCloseEvent) - { - } - - - @Override - public void onInventoryClick(User user, InventoryClickEvent event) - { - // First row of elements should be ignored, as it contains buttons and blocked slots. - event.setCancelled(event.getRawSlot() < 9 || - event.getRawSlot() < 35 || - event.getRawSlot() % 9 == 0 || - event.getRawSlot() % 9 == 8); - } - } - - - // --------------------------------------------------------------------- - // Section: Enums - // --------------------------------------------------------------------- - - - /** - * This enum holds all button values in current gui. - */ - private enum Button - { - SAVE, - ADD, - REMOVE, - VIEW, - RETURN - } - - - /** - * This enum holds which Lore is edited with current GUI. - */ - public enum LoreType - { - CHALLENGES, - LEVELS, - } - - - // --------------------------------------------------------------------- - // Section: Variables - // --------------------------------------------------------------------- - - /** - * Lore that will be edited with current GUI. - */ - private final LoreType lore; - - /** - * List of lore elements that are currently enabled. - */ - private List activeValues; - - - // --------------------------------------------------------------------- - // Section: Constants - // --------------------------------------------------------------------- - - - private final static String REFERENCE_DESCRIPTION = "challenges.gui.descriptions.admin."; -} diff --git a/src/main/java/world/bentobox/challenges/panel/admin/EditSettingsGUI.java b/src/main/java/world/bentobox/challenges/panel/admin/EditSettingsGUI.java deleted file mode 100644 index c808dac..0000000 --- a/src/main/java/world/bentobox/challenges/panel/admin/EditSettingsGUI.java +++ /dev/null @@ -1,606 +0,0 @@ -package world.bentobox.challenges.panel.admin; - - -import java.util.ArrayList; -import java.util.List; - -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.inventory.ItemStack; - -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.config.Settings; -import world.bentobox.challenges.config.SettingsUtils.GuiMode; -import world.bentobox.challenges.config.SettingsUtils.VisibilityMode; -import world.bentobox.challenges.panel.CommonGUI; -import world.bentobox.challenges.panel.util.NumberGUI; -import world.bentobox.challenges.panel.util.SelectBlocksGUI; -import world.bentobox.challenges.utils.GuiUtils; -import world.bentobox.challenges.utils.Utils; - - -/** - * This Class creates GUI that allows to change Challenges Addon Settings via in-game - * menu. - */ -public class EditSettingsGUI extends CommonGUI -{ - // --------------------------------------------------------------------- - // Section: Constructors - // --------------------------------------------------------------------- - - - /** - * @param addon Addon where panel operates. - * @param world World from which panel was created. - * @param user User who created panel. - * @param topLabel Command top label which creates panel (f.e. island or ai) - * @param permissionPrefix Command permission prefix (f.e. bskyblock.) - */ - public EditSettingsGUI(ChallengesAddon addon, - World world, - User user, - String topLabel, - String permissionPrefix) - { - this(addon, world, user, topLabel, permissionPrefix, null); - } - - - /** - * @param addon Addon where panel operates. - * @param world World from which panel was created. - * @param user User who created panel. - * @param topLabel Command top label which creates panel (f.e. island or ai) - * @param permissionPrefix Command permission prefix (f.e. bskyblock.) - */ - public EditSettingsGUI(ChallengesAddon addon, - World world, - User user, - String topLabel, - String permissionPrefix, - CommonGUI parentGUI) - { - super(addon, world, user, topLabel, permissionPrefix, parentGUI); - this.settings = this.addon.getChallengesSettings(); - } - - - // --------------------------------------------------------------------- - // Section: Methods - // --------------------------------------------------------------------- - - - @Override - public void build() - { - PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name( - this.user.getTranslation("challenges.gui.title.admin.settings-title")); - - GuiUtils.fillBorder(panelBuilder); - - panelBuilder.item(10, this.getSettingsButton(Button.ENABLE_TITLE)); - - if (this.settings.isShowCompletionTitle()) - { - panelBuilder.item(19, this.getSettingsButton(Button.TITLE_SHOWTIME)); - } - - panelBuilder.item(28, this.getSettingsButton(Button.BROADCAST)); - - panelBuilder.item(11, this.getSettingsButton(Button.GLOW_COMPLETED)); - panelBuilder.item(20, this.getSettingsButton(Button.REMOVE_COMPLETED)); - panelBuilder.item(29, this.getSettingsButton(Button.VISIBILITY_MODE)); - - panelBuilder.item(21, this.getSettingsButton(Button.LOCKED_LEVEL_ICON)); - panelBuilder.item(30, this.getSettingsButton(Button.FREE_AT_TOP)); - - panelBuilder.item(22, this.getSettingsButton(Button.GAMEMODE_GUI)); - - if (this.settings.isUseCommonGUI()) - { - // This should be active only when single gui is enabled. - panelBuilder.item(31, this.getSettingsButton(Button.GAMEMODE_GUI_VIEW_MODE)); - } - - panelBuilder.item(14, this.getSettingsButton(Button.LORE_LENGTH)); - panelBuilder.item(23, this.getSettingsButton(Button.CHALLENGE_LORE)); - panelBuilder.item(32, this.getSettingsButton(Button.LEVEL_LORE)); - - panelBuilder.item(24, this.getSettingsButton(Button.HISTORY)); - - if (this.settings.isStoreHistory()) - { - panelBuilder.item(33, this.getSettingsButton(Button.PURGE_HISTORY)); - } - - panelBuilder.item(25, this.getSettingsButton(Button.RESET_CHALLENGES)); - panelBuilder.item(34, this.getSettingsButton(Button.STORE_MODE)); - - // Return Button - panelBuilder.item(44, this.returnButton); - - // Save Settings every time this GUI is created. It will avoid issues with - // Overwritten setting after server stop. - this.addon.saveSettings(); - - panelBuilder.build(); - } - - - private PanelItem getSettingsButton(Button button) - { - ItemStack icon; - String name; - List description; - boolean glow; - PanelItem.ClickHandler clickHandler; - - switch (button) - { - case RESET_CHALLENGES: - { - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reset-on-new")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - this.settings.isResetChallenges() ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - name = this.user.getTranslation("challenges.gui.buttons.admin.reset-on-new"); - icon = new ItemStack(Material.LAVA_BUCKET); - - clickHandler = (panel, user1, clickType, i) -> { - this.settings.setResetChallenges( - !this.settings.isResetChallenges()); - - panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); - return true; - }; - - glow = this.settings.isResetChallenges(); - break; - } - case BROADCAST: - { - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.broadcast")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - this.settings.isBroadcastMessages() ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - - description = new ArrayList<>(2); - - name = this.user.getTranslation("challenges.gui.buttons.admin.broadcast"); - icon = new ItemStack(Material.JUKEBOX); - clickHandler = (panel, user1, clickType, i) -> { - this.settings.setBroadcastMessages( - !this.settings.isBroadcastMessages()); - panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); - return true; - }; - glow = this.settings.isBroadcastMessages(); - - break; - } - case REMOVE_COMPLETED: - { - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.remove-completed")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - this.settings.isRemoveCompleteOneTimeChallenges() ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - - name = this.user.getTranslation("challenges.gui.buttons.admin.remove-completed"); - icon = new ItemStack(Material.MAGMA_BLOCK); - clickHandler = (panel, user1, clickType, i) -> { - this.settings.setRemoveCompleteOneTimeChallenges( - !this.settings.isRemoveCompleteOneTimeChallenges()); - panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); - return true; - }; - glow = this.settings.isRemoveCompleteOneTimeChallenges(); - - break; - } - case LORE_LENGTH: - { - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.line-length")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", Integer.toString(this.settings.getLoreLineLength()))); - name = this.user.getTranslation("challenges.gui.buttons.admin.line-length"); - icon = new ItemStack(Material.ANVIL); - clickHandler = (panel, user1, clickType, i) -> { - new NumberGUI(this.user, - this.settings.getLoreLineLength(), - 0, - this.settings.getLoreLineLength(), - (status, value) -> { - if (status) - { - this.settings.setLoreLineLength(value); - } - - panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); - }); - - return true; - }; - glow = false; - break; - } - case LEVEL_LORE: - { - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.level-lore")); - name = this.user.getTranslation("challenges.gui.buttons.admin.level-lore"); - icon = new ItemStack(Material.MAP); - clickHandler = (panel, user1, clickType, i) -> { - - EditLoreGUI.open(this, EditLoreGUI.LoreType.LEVELS); - - return true; - }; - glow = false; - break; - } - case CHALLENGE_LORE: - { - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.challenge-lore")); - name = this.user.getTranslation("challenges.gui.buttons.admin.challenge-lore"); - icon = new ItemStack(Material.PAPER); - clickHandler = (panel, user1, clickType, i) -> { - - EditLoreGUI.open(this, EditLoreGUI.LoreType.CHALLENGES); - - return true; - }; - glow = false; - break; - } - case FREE_AT_TOP: - { - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.free-at-top")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - this.settings.isAddCompletedGlow() ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - name = this.user.getTranslation("challenges.gui.buttons.admin.free-at-top"); - icon = new ItemStack(Material.FILLED_MAP); - clickHandler = (panel, user1, clickType, i) -> { - this.settings.setFreeChallengesFirst(!this.settings.isFreeChallengesFirst()); - panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); - return true; - }; - glow = this.settings.isFreeChallengesFirst(); - break; - } - case GLOW_COMPLETED: - { - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.glow")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - this.settings.isAddCompletedGlow() ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - - - name = this.user.getTranslation("challenges.gui.buttons.admin.glow"); - icon = new ItemStack(Material.GLOWSTONE); - clickHandler = (panel, user1, clickType, i) -> { - this.settings.setAddCompletedGlow(!this.settings.isAddCompletedGlow()); - panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); - return true; - }; - glow = this.settings.isAddCompletedGlow(); - break; - } - case GAMEMODE_GUI_VIEW_MODE: - { - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.gui-view-mode")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - this.settings.getUserGuiMode().equals(GuiMode.GAMEMODE_LIST) ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - name = this.user.getTranslation("challenges.gui.buttons.admin.gui-view-mode"); - icon = new ItemStack(Material.STONE_BUTTON); - clickHandler = (panel, user1, clickType, i) -> { - - if (this.settings.getUserGuiMode().equals(GuiMode.GAMEMODE_LIST)) - { - this.settings.setUserGuiMode(GuiMode.CURRENT_WORLD); - } - else - { - this.settings.setUserGuiMode(GuiMode.GAMEMODE_LIST); - } - - panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); - return true; - }; - glow = this.settings.getUserGuiMode().equals(GuiMode.GAMEMODE_LIST); - break; - } - case GAMEMODE_GUI: - { - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.gui-mode")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - this.settings.isUseCommonGUI() ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - name = this.user.getTranslation("challenges.gui.buttons.admin.gui-mode"); - icon = new ItemStack(Material.BLACK_STAINED_GLASS_PANE); - clickHandler = (panel, user1, clickType, i) -> { - this.settings.setUseCommonGUI(!this.settings.isUseCommonGUI()); - // We cannot use single item changing as this option enabling/disabling will change other - // option visibility. - this.build(); - return true; - }; - glow = this.settings.isUseCommonGUI(); - break; - } - case HISTORY: - { - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.history-store")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - this.settings.isStoreHistory() ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - name = this.user.getTranslation("challenges.gui.buttons.admin.history-store"); - icon = new ItemStack(Material.WRITTEN_BOOK); - clickHandler = (panel, user1, clickType, i) -> { - this.settings.setStoreHistory(!this.settings.isStoreHistory()); - - // Need to rebuild all as new buttons will show up. - this.build(); - return true; - }; - glow = this.settings.isStoreHistory(); - break; - } - case PURGE_HISTORY: - { - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.history-lifespan")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", Integer.toString(this.settings.getLifeSpan()))); - name = this.user.getTranslation("challenges.gui.buttons.admin.history-lifespan"); - icon = new ItemStack(Material.FLINT_AND_STEEL); - clickHandler = (panel, user1, clickType, i) -> { - new NumberGUI(this.user, - this.settings.getLifeSpan(), - 0, - this.settings.getLoreLineLength(), - (status, value) -> { - if (status) - { - this.settings.setLifeSpan(value); - } - - panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); - }); - - return true; - }; - glow = false; - break; - } - case STORE_MODE: - { - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.island-store")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - this.settings.isStoreAsIslandData() ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - name = this.user.getTranslation("challenges.gui.buttons.admin.island-store"); - icon = new ItemStack(Material.GRASS_BLOCK); - clickHandler = (panel, user1, clickType, i) -> { - this.settings.setStoreAsIslandData(!this.settings.isStoreAsIslandData()); - // TODO: Data Migration must be added here. - panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); - return true; - }; - glow = this.settings.isStoreAsIslandData(); - break; - } - case LOCKED_LEVEL_ICON: - { - description = new ArrayList<>(1); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.default-locked-icon")); - name = this.user.getTranslation("challenges.gui.buttons.admin.default-locked-icon"); - icon = this.settings.getLockedLevelIcon(); - clickHandler = (panel, user, clickType, slot) -> { - - new SelectBlocksGUI(this.user, true, (status, materials) -> { - if (status) - { - materials.forEach(material -> - this.settings.setLockedLevelIcon(new ItemStack(material))); - } - - this.build(); - }); - - return true; - }; - glow = false; - break; - } - case ENABLE_TITLE: - { - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.title-enable")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - this.settings.isShowCompletionTitle() ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); - name = this.user.getTranslation("challenges.gui.buttons.admin.title-enable"); - icon = new ItemStack(Material.OAK_SIGN); - clickHandler = (panel, user1, clickType, i) -> { - this.settings.setShowCompletionTitle(!this.settings.isShowCompletionTitle()); - - // Need to rebuild all as new buttons will show up. - this.build(); - return true; - }; - glow = this.settings.isShowCompletionTitle(); - break; - } - case TITLE_SHOWTIME: - { - description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.title-showtime")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", Integer.toString(this.settings.getTitleShowtime()))); - name = this.user.getTranslation("challenges.gui.buttons.admin.title-showtime"); - icon = new ItemStack(Material.CLOCK); - clickHandler = (panel, user1, clickType, i) -> { - new NumberGUI(this.user, - this.settings.getTitleShowtime(), - 0, - this.settings.getLoreLineLength(), - (status, value) -> { - if (status) - { - this.settings.setTitleShowtime(value); - } - - panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); - }); - - return true; - }; - glow = false; - break; - } - case VISIBILITY_MODE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.visibility-mode"); - - List values = new ArrayList<>(5); - values.add(this.user.getTranslation("challenges.gui.descriptions.admin.visibility-mode")); - - values.add((this.settings.getVisibilityMode().equals(VisibilityMode.VISIBLE) ? "&2" : "&c") + - this.user.getTranslation("challenges.gui.descriptions.visibility.visible")); - values.add((this.settings.getVisibilityMode().equals(VisibilityMode.HIDDEN) ? "&2" : "&c") + - this.user.getTranslation("challenges.gui.descriptions.visibility.hidden")); - values.add((this.settings.getVisibilityMode().equals(VisibilityMode.TOGGLEABLE) ? "&2" : "&c") + - this.user.getTranslation("challenges.gui.descriptions.visibility.toggleable")); - - values.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]",this.settings.getVisibilityMode().name())); - - description = values; - - if (this.settings.getVisibilityMode().equals(VisibilityMode.VISIBLE)) - { - icon = new ItemStack(Material.OAK_PLANKS); - } - else if (this.settings.getVisibilityMode().equals(VisibilityMode.HIDDEN)) - { - icon = new ItemStack(Material.OAK_SLAB); - } - else - { - icon = new ItemStack(Material.OAK_BUTTON); - } - - clickHandler = (panel, user, clickType, slot) -> { - if (clickType.isRightClick()) - { - this.settings.setVisibilityMode( - Utils.getPreviousValue(VisibilityMode.values(), - this.settings.getVisibilityMode())); - } - else - { - this.settings.setVisibilityMode( - Utils.getNextValue(VisibilityMode.values(), - this.settings.getVisibilityMode())); - } - - // Rebuild just this icon - panel.getInventory().setItem(slot, - this.getSettingsButton(button).getItem()); - - return true; - }; - glow = false; - break; - } - default: - return new PanelItemBuilder().build(); - } - - return new PanelItemBuilder(). - icon(icon). - name(name). - description(GuiUtils.stringSplit(description, this.settings.getLoreLineLength())). - glow(glow). - clickHandler(clickHandler). - build(); - } - - - // --------------------------------------------------------------------- - // Section: Variables - // --------------------------------------------------------------------- - - - /** - * This enum holds all settings buttons that must have been displayed in this panel. - */ - private enum Button - { - RESET_CHALLENGES, - BROADCAST, - REMOVE_COMPLETED, - LORE_LENGTH, - LEVEL_LORE, - CHALLENGE_LORE, - FREE_AT_TOP, - GAMEMODE_GUI_VIEW_MODE, - GAMEMODE_GUI, - HISTORY, - PURGE_HISTORY, - STORE_MODE, - GLOW_COMPLETED, - LOCKED_LEVEL_ICON, - ENABLE_TITLE, - TITLE_SHOWTIME, - - /** - * This allows to switch between different challenges visibility modes. - */ - VISIBILITY_MODE - } - - - /** - * This allows faster access to challenges settings object. - */ - private Settings settings; -} diff --git a/src/main/java/world/bentobox/challenges/panel/admin/EditSettingsPanel.java b/src/main/java/world/bentobox/challenges/panel/admin/EditSettingsPanel.java new file mode 100644 index 0000000..660f7c4 --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/admin/EditSettingsPanel.java @@ -0,0 +1,576 @@ +package world.bentobox.challenges.panel.admin; + + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.ItemStack; + +import world.bentobox.bentobox.api.panels.PanelItem; +import world.bentobox.bentobox.api.panels.PanelListener; +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.config.Settings; +import world.bentobox.challenges.config.SettingsUtils.GuiMode; +import world.bentobox.challenges.config.SettingsUtils.VisibilityMode; +import world.bentobox.challenges.panel.CommonPanel; +import world.bentobox.challenges.panel.ConversationUtils; +import world.bentobox.challenges.utils.Constants; +import world.bentobox.challenges.utils.GuiUtils; +import world.bentobox.challenges.utils.Utils; + + +/** + * This Class creates GUI that allows to change Challenges Addon Settings via in-game + * menu. + */ +public class EditSettingsPanel extends CommonPanel +{ + // --------------------------------------------------------------------- + // Section: Constructors + // --------------------------------------------------------------------- + + + /** + * @param addon Addon where panel operates. + * @param world World from which panel was created. + * @param user User who created panel. + * @param topLabel Command top label which creates panel (f.e. island or ai) + * @param permissionPrefix Command permission prefix (f.e. bskyblock.) + */ + private EditSettingsPanel(ChallengesAddon addon, + User user, + World world, + String topLabel, + String permissionPrefix) + { + super(addon, user, world, topLabel, permissionPrefix); + this.settings = this.addon.getChallengesSettings(); + } + + + /** + * @param parentGUI Parent GUI. + */ + private EditSettingsPanel(CommonPanel parentGUI) + { + super(parentGUI); + this.settings = this.addon.getChallengesSettings(); + } + + + /** + * Open the Challenges Admin GUI. + * + * @param addon the addon + * @param world the world + * @param user the user + * @param topLabel the top label + * @param permissionPrefix the permission prefix + */ + public static void open(ChallengesAddon addon, + World world, + User user, + String topLabel, + String permissionPrefix) + { + new EditSettingsPanel(addon, user, world, topLabel, permissionPrefix).build(); + } + + + /** + * Open the Challenges Admin GUI. + */ + public static void open(CommonPanel parentGUI) + { + new EditSettingsPanel(parentGUI).build(); + } + + + // --------------------------------------------------------------------- + // Section: Methods + // --------------------------------------------------------------------- + + + @Override + protected void build() + { + PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name( + this.user.getTranslation(Constants.TITLE + "settings")); + + GuiUtils.fillBorder(panelBuilder); + + panelBuilder.item(10, this.getSettingsButton(Button.SHOW_TITLE)); + + if (this.settings.isShowCompletionTitle()) + { + panelBuilder.item(19, this.getSettingsButton(Button.TITLE_SHOWTIME)); + } + + panelBuilder.item(28, this.getSettingsButton(Button.BROADCAST)); + + panelBuilder.item(11, this.getSettingsButton(Button.GLOW_COMPLETED)); + panelBuilder.item(20, this.getSettingsButton(Button.REMOVE_COMPLETED)); + panelBuilder.item(29, this.getSettingsButton(Button.VISIBILITY_MODE)); + + panelBuilder.item(21, this.getSettingsButton(Button.LOCKED_LEVEL_ICON)); + + panelBuilder.item(22, this.getSettingsButton(Button.GAMEMODE_GUI)); + + if (this.settings.isUseCommonGUI()) + { + // This should be active only when single gui is enabled. + panelBuilder.item(31, this.getSettingsButton(Button.ACTIVE_WORLD_LIST)); + } + + panelBuilder.item(24, this.getSettingsButton(Button.STORE_HISTORY)); + + if (this.settings.isStoreHistory()) + { + panelBuilder.item(33, this.getSettingsButton(Button.PURGE_HISTORY)); + } + + panelBuilder.item(25, this.getSettingsButton(Button.RESET_ON_NEW)); + panelBuilder.item(34, this.getSettingsButton(Button.DATA_PER_ISLAND)); + + // Return Button + panelBuilder.item(44, this.returnButton); + panelBuilder.listener(new IconChanger()); + panelBuilder.build(); + } + + + private PanelItem getSettingsButton(Button button) + { + final String reference = Constants.BUTTON + button.name().toLowerCase() + "."; + + final String name = this.user.getTranslation(reference + "name"); + final List description = new ArrayList<>(3); + description.add(this.user.getTranslation(reference + "description")); + + ItemStack icon; + boolean glow; + PanelItem.ClickHandler clickHandler; + + switch (button) + { + case RESET_ON_NEW -> { + description.add(this.user.getTranslation(reference + + (this.settings.isResetChallenges() ? "enabled" : "disabled"))); + + icon = new ItemStack(Material.LAVA_BUCKET); + clickHandler = (panel, user1, clickType, i) -> { + this.settings.setResetChallenges(!this.settings.isResetChallenges()); + panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); + this.addon.saveSettings(); + return true; + }; + glow = this.settings.isResetChallenges(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle")); + } + case BROADCAST -> { + description.add(this.user.getTranslation(reference + + (this.settings.isBroadcastMessages() ? "enabled" : "disabled"))); + + icon = new ItemStack(Material.JUKEBOX); + clickHandler = (panel, user1, clickType, i) -> { + this.settings.setBroadcastMessages(!this.settings.isBroadcastMessages()); + panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); + this.addon.saveSettings(); + return true; + }; + glow = this.settings.isBroadcastMessages(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle")); + } + case REMOVE_COMPLETED -> { + description.add(this.user.getTranslation(reference + + (this.settings.isRemoveCompleteOneTimeChallenges() ? "enabled" : "disabled"))); + + icon = new ItemStack(Material.MAGMA_BLOCK); + clickHandler = (panel, user1, clickType, i) -> { + this.settings.setRemoveCompleteOneTimeChallenges(!this.settings.isRemoveCompleteOneTimeChallenges()); + panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); + this.addon.saveSettings(); + return true; + }; + glow = this.settings.isRemoveCompleteOneTimeChallenges(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle")); + } + case ACTIVE_WORLD_LIST -> { + description.add(this.user.getTranslation(reference + + (this.settings.getUserGuiMode().equals(GuiMode.GAMEMODE_LIST) ? + "disabled" : "enabled"))); + + icon = new ItemStack(Material.STONE_BUTTON); + clickHandler = (panel, user1, clickType, i) -> { + if (this.settings.getUserGuiMode().equals(GuiMode.GAMEMODE_LIST)) + { + this.settings.setUserGuiMode(GuiMode.CURRENT_WORLD); + } + else + { + this.settings.setUserGuiMode(GuiMode.GAMEMODE_LIST); + } + + this.addon.saveSettings(); + panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); + return true; + }; + glow = this.settings.getUserGuiMode().equals(GuiMode.GAMEMODE_LIST); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case GAMEMODE_GUI -> { + description.add(this.user.getTranslation(reference + + (this.settings.isUseCommonGUI() ? "enabled" : "disabled"))); + + icon = new ItemStack(Material.BLACK_STAINED_GLASS_PANE); + clickHandler = (panel, user1, clickType, i) -> { + this.settings.setUseCommonGUI(!this.settings.isUseCommonGUI()); + // Need to rebuild more icons + this.build(); + this.addon.saveSettings(); + return true; + }; + glow = this.settings.isUseCommonGUI(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle")); + } + case STORE_HISTORY -> { + description.add(this.user.getTranslation(reference + + (this.settings.isStoreHistory() ? "enabled" : "disabled"))); + + icon = new ItemStack(Material.WRITTEN_BOOK); + clickHandler = (panel, user1, clickType, i) -> { + this.settings.setStoreHistory(!this.settings.isStoreHistory()); + panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); + this.addon.saveSettings(); + return true; + }; + glow = this.settings.isStoreHistory(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle")); + } + case PURGE_HISTORY -> { + description.add(this.user.getTranslation(reference + "value", + Constants.NUMBER, String.valueOf(this.settings.getLifeSpan()))); + + icon = new ItemStack(Material.FLINT_AND_STEEL, Math.max(1, this.settings.getLifeSpan())); + clickHandler = (panel, user, clickType, i) -> { + Consumer numberConsumer = number -> { + if (number != null) + { + this.settings.setLifeSpan(number.intValue()); + this.addon.saveSettings(); + } + + // reopen panel + this.build(); + }; + + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 0, + 2000); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case DATA_PER_ISLAND -> { + description.add(this.user.getTranslation(reference + + (this.settings.isStoreAsIslandData() ? "enabled" : "disabled"))); + + icon = new ItemStack(Material.GRASS_BLOCK); + clickHandler = (panel, user1, clickType, i) -> { + this.settings.setStoreAsIslandData(!this.settings.isStoreAsIslandData()); + // TODO: Migration + panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); + this.addon.saveSettings(); + return true; + }; + glow = this.settings.isStoreAsIslandData(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle")); + } + case GLOW_COMPLETED -> { + description.add(this.user.getTranslation(reference + + (this.settings.isAddCompletedGlow() ? "enabled" : "disabled"))); + + icon = new ItemStack(Material.GLOWSTONE); + clickHandler = (panel, user1, clickType, i) -> { + this.settings.setAddCompletedGlow(!this.settings.isAddCompletedGlow()); + panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); + this.addon.saveSettings(); + return true; + }; + glow = this.settings.isAddCompletedGlow(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle")); + } + case LOCKED_LEVEL_ICON -> { + icon = this.settings.getLockedLevelIcon(); + + clickHandler = (panel, user, clickType, i) -> + { + if (this.selectedButton != null) + { + this.selectedButton = null; + } + else + { + this.selectedButton = button; + } + + panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); + return true; + }; + + if (this.selectedButton != button) + { + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + else + { + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-on-item")); + } + + glow = this.selectedButton == button; + } + case SHOW_TITLE -> { + description.add(this.user.getTranslation(reference + + (this.settings.isShowCompletionTitle() ? "enabled" : "disabled"))); + + icon = new ItemStack(Material.OAK_SIGN); + clickHandler = (panel, user1, clickType, i) -> { + this.settings.setShowCompletionTitle(!this.settings.isShowCompletionTitle()); + panel.getInventory().setItem(i, this.getSettingsButton(button).getItem()); + this.addon.saveSettings(); + return true; + }; + glow = this.settings.isShowCompletionTitle(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle")); + } + case TITLE_SHOWTIME -> { + description.add(this.user.getTranslation(reference + "value", + Constants.NUMBER, String.valueOf(this.settings.getTitleShowtime()))); + + icon = new ItemStack(Material.CLOCK, Math.max(1, this.settings.getTitleShowtime())); + clickHandler = (panel, user, clickType, i) -> { + Consumer numberConsumer = number -> { + if (number != null) + { + this.settings.setTitleShowtime(number.intValue()); + this.addon.saveSettings(); + } + + // reopen panel + this.build(); + }; + + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 0, + 2000); + + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-change")); + } + case VISIBILITY_MODE -> { + description.add(this.user.getTranslation(reference + + (this.settings.getVisibilityMode().equals(VisibilityMode.VISIBLE) ? "enabled" : "disabled")) + + this.user.getTranslation(reference + "visible")); + description.add(this.user.getTranslation(reference + + (this.settings.getVisibilityMode().equals(VisibilityMode.HIDDEN) ? "enabled" : "disabled")) + + this.user.getTranslation(reference + "hidden")); + description.add(this.user.getTranslation(reference + + (this.settings.getVisibilityMode().equals(VisibilityMode.TOGGLEABLE) ? "enabled" : "disabled")) + + this.user.getTranslation(reference + "toggleable")); + + if (this.settings.getVisibilityMode().equals(VisibilityMode.VISIBLE)) + { + icon = new ItemStack(Material.OAK_PLANKS); + } + else if (this.settings.getVisibilityMode().equals(VisibilityMode.HIDDEN)) + { + icon = new ItemStack(Material.OAK_SLAB); + } + else + { + icon = new ItemStack(Material.OAK_BUTTON); + } + + clickHandler = (panel, user, clickType, slot) -> { + if (clickType.isRightClick()) + { + this.settings.setVisibilityMode(Utils.getPreviousValue(VisibilityMode.values(), + this.settings.getVisibilityMode())); + } + else + { + this.settings.setVisibilityMode(Utils.getNextValue(VisibilityMode.values(), + this.settings.getVisibilityMode())); + } + + // Rebuild just this icon + panel.getInventory().setItem(slot, this.getSettingsButton(button).getItem()); + this.addon.saveSettings(); + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "left-click-to-cycle")); + description.add(this.user.getTranslation(Constants.TIPS + "right-click-to-cycle")); + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + glow = false; + } + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + glow(glow). + clickHandler(clickHandler). + build(); + } + + + // --------------------------------------------------------------------- + // Section: Classes + // --------------------------------------------------------------------- + + + /** + * This class allows changing icon for Generator Tier + */ + private class IconChanger implements PanelListener + { + /** + * Process inventory click. If generator icon is selected and user clicks on item in his inventory, then change + * icon to the item from inventory. + * + * @param user the user + * @param event the event + */ + @Override + public void onInventoryClick(User user, InventoryClickEvent event) + { + // Handle icon changing + if (EditSettingsPanel.this.selectedButton != null && + event.getCurrentItem() != null && + !event.getCurrentItem().getType().equals(Material.AIR) && + event.getRawSlot() > 44) + { + // set material and amount only. Other data should be removed. + + if (EditSettingsPanel.this.selectedButton == Button.LOCKED_LEVEL_ICON) + { + EditSettingsPanel.this.settings.setLockedLevelIcon(event.getCurrentItem().clone()); + EditSettingsPanel.this.addon.saveSettings(); + + // Deselect icon + EditSettingsPanel.this.selectedButton = null; + EditSettingsPanel.this.build(); + } + } + } + + + /** + * On inventory close. + * + * @param event the event + */ + @Override + public void onInventoryClose(InventoryCloseEvent event) + { + // Do nothing + } + + + /** + * Setup current listener. + */ + @Override + public void setup() + { + // Do nothing + } + } + + + // --------------------------------------------------------------------- + // Section: Variables + // --------------------------------------------------------------------- + + + /** + * This enum holds all settings buttons that must have been displayed in this panel. + */ + private enum Button + { + RESET_ON_NEW, + BROADCAST, + REMOVE_COMPLETED, + ACTIVE_WORLD_LIST, + GAMEMODE_GUI, + STORE_HISTORY, + PURGE_HISTORY, + DATA_PER_ISLAND, + GLOW_COMPLETED, + LOCKED_LEVEL_ICON, + SHOW_TITLE, + TITLE_SHOWTIME, + /** + * This allows to switch between different challenges visibility modes. + */ + VISIBILITY_MODE + } + + + /** + * This allows faster access to challenges settings object. + */ + private final Settings settings; + + /** + * Allows changing locked level icon. + */ + private Button selectedButton; +} diff --git a/src/main/java/world/bentobox/challenges/panel/admin/ListChallengesGUI.java b/src/main/java/world/bentobox/challenges/panel/admin/ListChallengesPanel.java similarity index 54% rename from src/main/java/world/bentobox/challenges/panel/admin/ListChallengesGUI.java rename to src/main/java/world/bentobox/challenges/panel/admin/ListChallengesPanel.java index ccdb1cf..70eb3e7 100644 --- a/src/main/java/world/bentobox/challenges/panel/admin/ListChallengesGUI.java +++ b/src/main/java/world/bentobox/challenges/panel/admin/ListChallengesPanel.java @@ -1,9 +1,8 @@ package world.bentobox.challenges.panel.admin; -import java.util.List; +import java.util.function.Consumer; -import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.World; @@ -11,18 +10,22 @@ 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.bentobox.util.Util; import world.bentobox.challenges.ChallengesAddon; import world.bentobox.challenges.database.object.Challenge; -import world.bentobox.challenges.panel.CommonGUI; -import world.bentobox.challenges.panel.util.ConfirmationGUI; +import world.bentobox.challenges.panel.CommonPagedPanel; +import world.bentobox.challenges.panel.CommonPanel; +import world.bentobox.challenges.panel.ConversationUtils; +import world.bentobox.challenges.utils.Constants; import world.bentobox.challenges.utils.GuiUtils; +import world.bentobox.challenges.utils.Utils; /** * This class contains all necessary elements to create GUI that lists all challenges. * It allows to edit them or remove, depending on given input mode. */ -public class ListChallengesGUI extends CommonGUI +public class ListChallengesPanel extends CommonPagedPanel { // --------------------------------------------------------------------- // Section: Constructor @@ -37,38 +40,57 @@ public class ListChallengesGUI extends CommonGUI * @param permissionPrefix Command permission prefix (f.e. bskyblock.) * @param mode - mode that indicate what should do icon clicking. */ - public ListChallengesGUI(ChallengesAddon addon, + private ListChallengesPanel(ChallengesAddon addon, World world, User user, Mode mode, String topLabel, String permissionPrefix) { - this(addon, world, user, mode, topLabel, permissionPrefix, null); + super(addon, user, world, topLabel, permissionPrefix); + this.currentMode = mode; } /** - * @param addon Addon where panel operates. - * @param world World from which panel was created. - * @param user User who created panel. - * @param topLabel Command top label which creates panel (f.e. island or ai) - * @param permissionPrefix Command permission prefix (f.e. bskyblock.) * @param mode - mode that indicate what should do icon clicking. */ - public ListChallengesGUI(ChallengesAddon addon, - World world, - User user, - Mode mode, - String topLabel, - String permissionPrefix, - CommonGUI parentGUI) + private ListChallengesPanel(CommonPanel parentGUI, Mode mode) { - super(addon, world, user, topLabel, permissionPrefix, parentGUI); + super(parentGUI); this.currentMode = mode; } + /** + * Open the Challenges Admin GUI. + * + * @param addon the addon + * @param world the world + * @param user the user + * @param topLabel the top label + * @param permissionPrefix the permission prefix + */ + public static void open(ChallengesAddon addon, + World world, + User user, + String topLabel, + String permissionPrefix, + Mode mode) + { + new ListChallengesPanel(addon, world, user, mode, topLabel, permissionPrefix).build(); + } + + + /** + * Open the Challenges Admin GUI. + */ + public static void open(CommonPanel parentGUI, Mode mode) + { + new ListChallengesPanel(parentGUI, mode).build(); + } + + // --------------------------------------------------------------------- // Section: Methods // --------------------------------------------------------------------- @@ -78,10 +100,10 @@ public class ListChallengesGUI extends CommonGUI * {@inheritDoc} */ @Override - public void build() + protected void build() { PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name( - this.user.getTranslation("challenges.gui.title.admin.choose-challenge-title")); + this.user.getTranslation(Constants.TITLE + "choose-challenge")); if (this.currentMode.equals(Mode.DELETE)) { @@ -92,42 +114,9 @@ public class ListChallengesGUI extends CommonGUI GuiUtils.fillBorder(panelBuilder); } - List challengeList = this.addon.getChallengesManager().getAllChallenges(this.world); - - final int MAX_ELEMENTS = 21; - - if (this.pageIndex < 0) - { - this.pageIndex = challengeList.size() / MAX_ELEMENTS; - } - else if (this.pageIndex > (challengeList.size() / MAX_ELEMENTS)) - { - this.pageIndex = 0; - } - - int challengeIndex = MAX_ELEMENTS * this.pageIndex; - - // I want first row to be only for navigation and return button. - int index = 10; - - while (challengeIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) && - challengeIndex < challengeList.size() && - index < 36) - { - if (!panelBuilder.slotOccupied(index)) - { - panelBuilder.item(index, this.createChallengeIcon(challengeList.get(challengeIndex++))); - } - - index++; - } - - // Navigation buttons only if necessary - if (challengeList.size() > MAX_ELEMENTS) - { - panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS)); - panelBuilder.item(26, this.getButton(CommonButtons.NEXT)); - } + this.populateElements(panelBuilder, + this.addon.getChallengesManager().getAllChallenges(this.world), + o -> this.createChallengeIcon((Challenge) o)); panelBuilder.item(44, this.returnButton); @@ -143,36 +132,46 @@ public class ListChallengesGUI extends CommonGUI private PanelItem createChallengeIcon(Challenge challenge) { PanelItemBuilder itemBuilder = new PanelItemBuilder(). - name(ChatColor.translateAlternateColorCodes('&', challenge.getFriendlyName())). - description(GuiUtils.stringSplit(this.generateChallengeDescription(challenge, this.user.getPlayer()), - this.addon.getChallengesSettings().getLoreLineLength())). - icon(challenge.getIcon()). - glow(challenge.isDeployed()); + name(Util.translateColorCodes(challenge.getFriendlyName())). + description(this.generateChallengeDescription(challenge, null)). + icon(challenge.getIcon()). + glow(!challenge.isDeployed()); if (this.currentMode.equals(Mode.EDIT)) { + itemBuilder.description(""); + itemBuilder.description(this.user.getTranslation(Constants.TIPS + "click-to-edit")); + itemBuilder.clickHandler((panel, user1, clickType, i) -> { - new EditChallengeGUI(this.addon, - this.world, - this.user, - challenge, - this.topLabel, - this.permissionPrefix, - this).build(); + EditChallengePanel.open(this, challenge); return true; }); } else if (this.currentMode.equals(Mode.DELETE)) { + itemBuilder.description(""); + itemBuilder.description(this.user.getTranslation(Constants.TIPS + "click-to-remove")); + itemBuilder.clickHandler((panel, user1, clickType, i) -> { - new ConfirmationGUI(this.user, value -> { + Consumer consumer = value -> { if (value) { this.addon.getChallengesManager().deleteChallenge(challenge); } this.build(); - }); + }; + + // Create conversation that gets user acceptance to delete generator data. + ConversationUtils.createConfirmation( + consumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "confirm-challenge-deletion", + Constants.GAMEMODE, Utils.getGameMode(this.world), + Constants.CHALLENGE, challenge.getFriendlyName()), + this.user.getTranslation(Constants.CONVERSATIONS + "challenge-removed", + Constants.GAMEMODE, Utils.getGameMode(this.world), + Constants.CHALLENGE, challenge.getFriendlyName())); return true; }); } @@ -203,5 +202,5 @@ public class ListChallengesGUI extends CommonGUI /** * Current mode in which icons will act. */ - private Mode currentMode; + private final Mode currentMode; } diff --git a/src/main/java/world/bentobox/challenges/panel/admin/ListLevelsGUI.java b/src/main/java/world/bentobox/challenges/panel/admin/ListLevelsPanel.java similarity index 53% rename from src/main/java/world/bentobox/challenges/panel/admin/ListLevelsGUI.java rename to src/main/java/world/bentobox/challenges/panel/admin/ListLevelsPanel.java index 4a9dad5..b437b88 100644 --- a/src/main/java/world/bentobox/challenges/panel/admin/ListLevelsGUI.java +++ b/src/main/java/world/bentobox/challenges/panel/admin/ListLevelsPanel.java @@ -1,28 +1,31 @@ package world.bentobox.challenges.panel.admin; -import java.util.List; - -import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.World; +import java.util.function.Consumer; + 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.bentobox.util.Util; import world.bentobox.challenges.ChallengesAddon; import world.bentobox.challenges.database.object.ChallengeLevel; -import world.bentobox.challenges.panel.CommonGUI; -import world.bentobox.challenges.panel.util.ConfirmationGUI; +import world.bentobox.challenges.panel.CommonPagedPanel; +import world.bentobox.challenges.panel.CommonPanel; +import world.bentobox.challenges.panel.ConversationUtils; +import world.bentobox.challenges.utils.Constants; import world.bentobox.challenges.utils.GuiUtils; +import world.bentobox.challenges.utils.Utils; /** * This class creates GUI that lists all Levels. Clicking on Level icon will be processed * by input mode. */ -public class ListLevelsGUI extends CommonGUI +public class ListLevelsPanel extends CommonPagedPanel { // --------------------------------------------------------------------- // Section: Constructor @@ -37,38 +40,57 @@ public class ListLevelsGUI extends CommonGUI * @param permissionPrefix Command permission prefix (f.e. bskyblock.) * @param mode - mode that indicate what should do icon clicking. */ - public ListLevelsGUI(ChallengesAddon addon, + private ListLevelsPanel(ChallengesAddon addon, World world, User user, Mode mode, String topLabel, String permissionPrefix) { - this(addon, world, user, mode, topLabel, permissionPrefix, null); + super(addon, user, world, topLabel, permissionPrefix); + this.currentMode = mode; } /** - * @param addon Addon where panel operates. - * @param world World from which panel was created. - * @param user User who created panel. - * @param topLabel Command top label which creates panel (f.e. island or ai) - * @param permissionPrefix Command permission prefix (f.e. bskyblock.) * @param mode - mode that indicate what should do icon clicking. */ - public ListLevelsGUI(ChallengesAddon addon, - World world, - User user, - Mode mode, - String topLabel, - String permissionPrefix, - CommonGUI parentGUI) + private ListLevelsPanel(CommonPanel parentGUI, Mode mode) { - super(addon, world, user, topLabel, permissionPrefix, parentGUI); + super(parentGUI); this.currentMode = mode; } + /** + * Open the Challenges Admin GUI. + * + * @param addon the addon + * @param world the world + * @param user the user + * @param topLabel the top label + * @param permissionPrefix the permission prefix + */ + public static void open(ChallengesAddon addon, + World world, + User user, + String topLabel, + String permissionPrefix, + Mode mode) + { + new ListLevelsPanel(addon, world, user, mode, topLabel, permissionPrefix).build(); + } + + + /** + * Open the Challenges Admin GUI. + */ + public static void open(CommonPanel parentGUI, Mode mode) + { + new ListLevelsPanel(parentGUI, mode).build(); + } + + // --------------------------------------------------------------------- // Section: Methods // --------------------------------------------------------------------- @@ -78,10 +100,10 @@ public class ListLevelsGUI extends CommonGUI * {@inheritDoc} */ @Override - public void build() + protected void build() { PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name( - this.user.getTranslation("challenges.gui.title.admin.choose-level-title")); + this.user.getTranslation(Constants.TITLE + "choose-level")); if (this.currentMode.equals(Mode.DELETE)) { @@ -92,42 +114,9 @@ public class ListLevelsGUI extends CommonGUI GuiUtils.fillBorder(panelBuilder); } - List levelList = this.addon.getChallengesManager().getLevels(this.world); - - final int MAX_ELEMENTS = 21; - - if (this.pageIndex < 0) - { - this.pageIndex = levelList.size() / MAX_ELEMENTS; - } - else if (this.pageIndex > (levelList.size() / MAX_ELEMENTS)) - { - this.pageIndex = 0; - } - - int levelIndex = MAX_ELEMENTS * this.pageIndex; - - // I want first row to be only for navigation and return button. - int index = 10; - - while (levelIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) && - levelIndex < levelList.size() && - index < 36) - { - if (!panelBuilder.slotOccupied(index)) - { - panelBuilder.item(index, this.createLevelIcon(levelList.get(levelIndex++))); - } - - index++; - } - - // Navigation buttons only if necessary - if (levelList.size() > MAX_ELEMENTS) - { - panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS)); - panelBuilder.item(26, this.getButton(CommonButtons.NEXT)); - } + this.populateElements(panelBuilder, + this.addon.getChallengesManager().getLevels(this.world), + o -> this.createLevelIcon((ChallengeLevel) o)); panelBuilder.item(44, this.returnButton); @@ -143,38 +132,45 @@ public class ListLevelsGUI extends CommonGUI private PanelItem createLevelIcon(ChallengeLevel challengeLevel) { PanelItemBuilder itemBuilder = new PanelItemBuilder(). - name(ChatColor.translateAlternateColorCodes('&', challengeLevel.getFriendlyName())). - description(GuiUtils.stringSplit( - this.generateLevelDescription(challengeLevel, this.user.getPlayer()), - this.addon.getChallengesSettings().getLoreLineLength())). - icon(challengeLevel.getIcon()). - glow(false); + name(Util.translateColorCodes(challengeLevel.getFriendlyName())). + description(this.generateLevelDescription(challengeLevel)). + icon(challengeLevel.getIcon()); if (this.currentMode.equals(Mode.EDIT)) { + itemBuilder.description(""); + itemBuilder.description(this.user.getTranslation(Constants.TIPS + "click-to-edit")); + itemBuilder.clickHandler((panel, user1, clickType, i) -> { - new EditLevelGUI(this.addon, - this.world, - this.user, - challengeLevel, - this.topLabel, - this.permissionPrefix, - this).build(); + EditLevelPanel.open(this, challengeLevel); return true; }); } else if (this.currentMode.equals(Mode.DELETE)) { + itemBuilder.description(""); + itemBuilder.description(this.user.getTranslation(Constants.TIPS + "click-to-remove")); + itemBuilder.clickHandler((panel, user1, clickType, i) -> { - new ConfirmationGUI(this.user, value -> { + Consumer consumer = value -> { if (value) { - this.addon.getChallengesManager(). - deleteChallengeLevel(challengeLevel); + this.addon.getChallengesManager().deleteChallengeLevel(challengeLevel); } this.build(); - }); + }; + + // Create conversation that gets user acceptance to delete generator data. + ConversationUtils.createConfirmation( + consumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "confirm-level-deletion", + Constants.GAMEMODE, Utils.getGameMode(this.world), + Constants.LEVEL, challengeLevel.getFriendlyName()), + this.user.getTranslation(Constants.CONVERSATIONS + "level-removed", + Constants.GAMEMODE, Utils.getGameMode(this.world), + Constants.LEVEL, challengeLevel.getFriendlyName())); return true; }); } @@ -202,8 +198,9 @@ public class ListLevelsGUI extends CommonGUI // Section: Variables // --------------------------------------------------------------------- + /** * Current mode in which icons will act. */ - private Mode currentMode; + private final Mode currentMode; } diff --git a/src/main/java/world/bentobox/challenges/panel/admin/ListLibraryGUI.java b/src/main/java/world/bentobox/challenges/panel/admin/ListLibraryPanel.java similarity index 53% rename from src/main/java/world/bentobox/challenges/panel/admin/ListLibraryGUI.java rename to src/main/java/world/bentobox/challenges/panel/admin/ListLibraryPanel.java index d153da3..7a6c861 100644 --- a/src/main/java/world/bentobox/challenges/panel/admin/ListLibraryGUI.java +++ b/src/main/java/world/bentobox/challenges/panel/admin/ListLibraryPanel.java @@ -7,15 +7,21 @@ import java.util.List; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.World; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.scheduler.BukkitTask; import world.bentobox.bentobox.api.panels.PanelItem; +import world.bentobox.bentobox.api.panels.PanelListener; 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.panel.CommonGUI; +import world.bentobox.challenges.panel.CommonPagedPanel; +import world.bentobox.challenges.panel.CommonPanel; +import world.bentobox.challenges.utils.Constants; import world.bentobox.challenges.utils.GuiUtils; +import world.bentobox.challenges.utils.Utils; import world.bentobox.challenges.web.object.LibraryEntry; @@ -23,7 +29,7 @@ import world.bentobox.challenges.web.object.LibraryEntry; * This class contains all necessary elements to create GUI that lists all challenges. * It allows to edit them or remove, depending on given input mode. */ -public class ListLibraryGUI extends CommonGUI +public class ListLibraryPanel extends CommonPagedPanel { // --------------------------------------------------------------------- // Section: Constructor @@ -32,7 +38,7 @@ public class ListLibraryGUI extends CommonGUI /** * @param parentGUI ParentGUI object. */ - public ListLibraryGUI(CommonGUI parentGUI) + private ListLibraryPanel(CommonPanel parentGUI) { super(parentGUI); } @@ -45,23 +51,43 @@ public class ListLibraryGUI extends CommonGUI * @param topLabel Command top label which creates panel (f.e. island or ai) * @param permissionPrefix Command permission prefix (f.e. bskyblock.) */ - public ListLibraryGUI(ChallengesAddon addon, + private ListLibraryPanel(ChallengesAddon addon, World world, User user, String topLabel, String permissionPrefix) { - super(addon, world, user, topLabel, permissionPrefix, null); + super(addon, user, world, topLabel, permissionPrefix); } + /** + * Open the Challenges Admin GUI. + * + * @param addon the addon + * @param world the world + * @param user the user + * @param topLabel the top label + * @param permissionPrefix the permission prefix + */ + public static void open(ChallengesAddon addon, + World world, + User user, + String topLabel, + String permissionPrefix) + { + new ListLibraryPanel(addon, world, user, topLabel, permissionPrefix).build(); + } + + + /** * This static method allows to easier open Library GUI. * @param parentGui ParentGUI object. */ - public static void open(CommonGUI parentGui) + public static void open(CommonPanel parentGui) { - new ListLibraryGUI(parentGui).build(); + new ListLibraryPanel(parentGui).build(); } @@ -74,52 +100,21 @@ public class ListLibraryGUI extends CommonGUI * {@inheritDoc} */ @Override - public void build() + protected void build() { PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name( - this.user.getTranslation("challenges.gui.title.admin.library-title")); + this.user.getTranslation(Constants.TITLE + "library")); GuiUtils.fillBorder(panelBuilder); - List libraryEntries = this.addon.getWebManager().getLibraryEntries(); - - final int MAX_ELEMENTS = 21; - - if (this.pageIndex < 0) - { - this.pageIndex = libraryEntries.size() / MAX_ELEMENTS; - } - else if (this.pageIndex > (libraryEntries.size() / MAX_ELEMENTS)) - { - this.pageIndex = 0; - } - - int entryIndex = MAX_ELEMENTS * this.pageIndex; - - // I want first row to be only for navigation and return button. - int index = 10; - - while (entryIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) && - entryIndex < libraryEntries.size() && - index < 36) - { - if (!panelBuilder.slotOccupied(index)) - { - panelBuilder.item(index, this.createEntryIcon(libraryEntries.get(entryIndex++))); - } - - index++; - } - - // Navigation buttons only if necessary - if (libraryEntries.size() > MAX_ELEMENTS) - { - panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS)); - panelBuilder.item(26, this.getButton(CommonButtons.NEXT)); - } + this.populateElements(panelBuilder, + this.addon.getWebManager().getLibraryEntries(), + o -> this.createEntryIcon((LibraryEntry) o)); panelBuilder.item(4, this.createDownloadNow()); - panelBuilder.item(44, this.createReturnButton()); + panelBuilder.item(44, this.returnButton); + + panelBuilder.listener(new DownloadCanceller()); panelBuilder.build(); } @@ -131,17 +126,20 @@ public class ListLibraryGUI extends CommonGUI */ private PanelItem createDownloadNow() { - List description = new ArrayList<>(2); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.download")); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", - "[value]", - this.clearCache ? - this.user.getTranslation("challenges.gui.descriptions.enabled") : - this.user.getTranslation("challenges.gui.descriptions.disabled"))); + final String reference = Constants.BUTTON + "download."; + + final List description = new ArrayList<>(3); + description.add(this.user.getTranslation(reference + "description")); + description.add(this.user.getTranslation(reference + + (this.clearCache ? "enabled" : "disabled"))); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "left-click-to-download")); + description.add(this.user.getTranslation(Constants.TIPS + "right-click-to-toggle")); PanelItemBuilder itemBuilder = new PanelItemBuilder(). - name(this.user.getTranslation("challenges.gui.buttons.admin.download")). - description(GuiUtils.stringSplit(description, this.addon.getChallengesSettings().getLoreLineLength())). + name(this.user.getTranslation(reference + "name")). + description(description). icon(Material.HOPPER). glow(this.clearCache); @@ -176,33 +174,6 @@ public class ListLibraryGUI extends CommonGUI } - /** - * This creates return button, that allows to exist or return to parent gui, - * @return PanelItem for return button. - */ - private PanelItem createReturnButton() - { - return new PanelItemBuilder(). - name(this.user.getTranslation("challenges.gui.buttons.return")). - icon(Material.OAK_DOOR). - clickHandler((panel, user1, clickType, i) -> { - if (this.updateTask != null) - { - this.updateTask.cancel(); - } - - if (this.parentGUI == null) - { - this.user.closeInventory(); - return true; - } - - this.parentGUI.build(); - return true; - }).build(); - } - - /** * This method creates button for given library entry. * @param libraryEntry LibraryEntry which button must be created. @@ -211,10 +182,12 @@ public class ListLibraryGUI extends CommonGUI private PanelItem createEntryIcon(LibraryEntry libraryEntry) { PanelItemBuilder itemBuilder = new PanelItemBuilder(). - name(ChatColor.translateAlternateColorCodes('&', libraryEntry.getName())). - description(this.generateEntryDescription(libraryEntry)). - icon(libraryEntry.getIcon()). - glow(false); + name(ChatColor.translateAlternateColorCodes('&', libraryEntry.getName())). + description(this.generateEntryDescription(libraryEntry)). + description(""). + description(this.user.getTranslation(Constants.TIPS + "click-to-install")). + icon(libraryEntry.getIcon()). + glow(false); itemBuilder.clickHandler((panel, user1, clickType, i) -> { @@ -222,7 +195,8 @@ public class ListLibraryGUI extends CommonGUI { this.blockedForDownland = true; - this.user.sendMessage("challenges.messages.admin.start-downloading"); + Utils.sendMessage(this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "start-downloading")); // Run download task after 5 ticks. this.addon.getPlugin().getServer().getScheduler(). @@ -231,24 +205,7 @@ public class ListLibraryGUI extends CommonGUI () -> this.addon.getWebManager().requestEntryGitHubData(this.user, this.world, libraryEntry), 5L); - if (this.parentGUI != null) - { - if (this.updateTask != null) - { - this.updateTask.cancel(); - } - - this.parentGUI.build(); - } - else - { - if (this.updateTask != null) - { - this.updateTask.cancel(); - } - - this.user.closeInventory(); - } + this.build(); } return true; @@ -265,25 +222,66 @@ public class ListLibraryGUI extends CommonGUI */ private List generateEntryDescription(LibraryEntry entry) { + final String reference = Constants.DESCRIPTIONS + "library."; + List description = new ArrayList<>(); - description.add(this.user.getTranslation(REFERENCE_DESCRIPTION + "library-author", - "[author]", - entry.getAuthor())); + description.add(this.user.getTranslation(reference + "author", + "[author]", entry.getAuthor())); description.add(entry.getDescription()); - description.add(this.user.getTranslation(REFERENCE_DESCRIPTION + "library-gamemode", - "[gamemode]", - entry.getForGameMode())); - description.add(this.user.getTranslation(REFERENCE_DESCRIPTION + "library-lang", - "[lang]", - entry.getLanguage())); - description.add(this.user.getTranslation(REFERENCE_DESCRIPTION + "library-version", - "[version]", - entry.getVersion())); + description.add(this.user.getTranslation(reference + "gamemode", + "[gamemode]", entry.getForGameMode())); + description.add(this.user.getTranslation(reference + "lang", + "[lang]", entry.getLanguage())); + description.add(this.user.getTranslation(reference + "version", + "[version]", entry.getVersion())); - return GuiUtils.stringSplit(description, - this.addon.getChallengesSettings().getLoreLineLength()); + return description; + } + + + /** + * This class allows changing icon for Generator Tier + */ + private class DownloadCanceller implements PanelListener + { + /** + * On inventory click. + * + * @param user the user + * @param event the event + */ + @Override + public void onInventoryClick(User user, InventoryClickEvent event) + { + // do nothing + } + + + /** + * On inventory close. + * + * @param event the event + */ + @Override + public void onInventoryClose(InventoryCloseEvent event) + { + if (ListLibraryPanel.this.updateTask != null) + { + ListLibraryPanel.this.updateTask.cancel(); + } + } + + + /** + * Setup current listener. + */ + @Override + public void setup() + { + // Do nothing + } } @@ -305,9 +303,4 @@ public class ListLibraryGUI extends CommonGUI * This variable will protect against spam-click. */ private boolean blockedForDownland; - - /** - * Reference string to description. - */ - private static final String REFERENCE_DESCRIPTION = "challenges.gui.descriptions.admin."; } diff --git a/src/main/java/world/bentobox/challenges/panel/admin/ListUsersGUI.java b/src/main/java/world/bentobox/challenges/panel/admin/ListUsersGUI.java deleted file mode 100644 index 03d9034..0000000 --- a/src/main/java/world/bentobox/challenges/panel/admin/ListUsersGUI.java +++ /dev/null @@ -1,334 +0,0 @@ -package world.bentobox.challenges.panel.admin; - - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.entity.Player; - -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.bentobox.database.objects.Players; -import world.bentobox.challenges.ChallengesAddon; -import world.bentobox.challenges.managers.ChallengesManager; -import world.bentobox.challenges.database.object.Challenge; -import world.bentobox.challenges.panel.CommonGUI; -import world.bentobox.challenges.panel.util.ConfirmationGUI; -import world.bentobox.challenges.panel.util.SelectChallengeGUI; -import world.bentobox.challenges.utils.GuiUtils; - - -/** - * This class contains methods that allows to select specific user. - */ -public class ListUsersGUI extends CommonGUI -{ - // --------------------------------------------------------------------- - // Section: Variables - // --------------------------------------------------------------------- - - /** - * List with players that should be in GUI. - */ - private List onlineUsers; - - /** - * Current operation mode. - */ - private Mode operationMode; - - /** - * Current index of view mode - */ - private int modeIndex = 2; - - /** - * This allows to switch which users should be in the list. - */ - private enum ViewMode - { - ONLINE, - WITH_ISLAND, - IN_WORLD - } - - /** - * This allows to decide what User Icon should do. - */ - public enum Mode - { - COMPLETE, - RESET, - RESET_ALL - } - - - // --------------------------------------------------------------------- - // Section: Constructors - // --------------------------------------------------------------------- - - - /** - * @param addon Addon where panel operates. - * @param world World from which panel was created. - * @param user User who created panel. - * @param topLabel Command top label which creates panel (f.e. island or ai) - * @param permissionPrefix Command permission prefix (f.e. bskyblock.) - * @param operationMode Indicate what should happen on player icon click. - */ - public ListUsersGUI(ChallengesAddon addon, - World world, - User user, - Mode operationMode, - String topLabel, - String permissionPrefix) - { - this(addon, world, user, operationMode, topLabel, permissionPrefix, null); - } - - - /** - * @param addon Addon where panel operates. - * @param world World from which panel was created. - * @param user User who created panel. - * @param topLabel Command top label which creates panel (f.e. island or ai) - * @param permissionPrefix Command permission prefix (f.e. bskyblock.) - * @param operationMode Indicate what should happen on player icon click. - */ - public ListUsersGUI(ChallengesAddon addon, - World world, - User user, - Mode operationMode, - String topLabel, - String permissionPrefix, - CommonGUI parentPanel) - { - super(addon, world, user, topLabel, permissionPrefix, parentPanel); - this.onlineUsers = this.collectUsers(ViewMode.IN_WORLD); - this.operationMode = operationMode; - } - - - // --------------------------------------------------------------------- - // Section: Methods - // --------------------------------------------------------------------- - - - @Override - public void build() - { - PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name( - this.user.getTranslation("challenges.gui.title.admin.choose-user-title")); - - GuiUtils.fillBorder(panelBuilder); - - final int MAX_ELEMENTS = 21; - - if (this.pageIndex < 0) - { - this.pageIndex = this.onlineUsers.size() / MAX_ELEMENTS; - } - else if (this.pageIndex > (this.onlineUsers.size() / MAX_ELEMENTS)) - { - this.pageIndex = 0; - } - - int playerIndex = MAX_ELEMENTS * this.pageIndex; - - // I want first row to be only for navigation and return button. - int index = 10; - - while (playerIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) && - playerIndex < this.onlineUsers.size() && - index < 36) - { - if (!panelBuilder.slotOccupied(index)) - { - panelBuilder.item(index, this.createPlayerIcon(this.onlineUsers.get(playerIndex++))); - } - - index++; - } - - // Add button that allows to toggle different player lists. - panelBuilder.item( 4, this.createToggleButton()); - - // Navigation buttons only if necessary - if (this.onlineUsers.size() > MAX_ELEMENTS) - { - panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS)); - panelBuilder.item(26, this.getButton(CommonButtons.NEXT)); - } - - panelBuilder.item(44, this.returnButton); - - - panelBuilder.build(); - } - - - /** - * This method creates button for given user. If user has island it will add valid click handler. - * @param player Player which button must be created. - * @return Player button. - */ - private PanelItem createPlayerIcon(Player player) - { - int lineLength = this.addon.getChallengesSettings().getLoreLineLength(); - - if (this.addon.getIslands().getIsland(this.world, player.getUniqueId()) != null) - { - return new PanelItemBuilder().name(player.getName()).icon(player.getName()).clickHandler( - (panel, user1, clickType, slot) -> { - ChallengesManager manager = this.addon.getChallengesManager(); - Map> challengeDescriptionMap; - - switch (this.operationMode) - { - case COMPLETE: - challengeDescriptionMap = new LinkedHashMap<>(); - - for (Challenge challenge : manager.getAllChallenges(this.world)) - { - if (!manager.isChallengeComplete(player.getUniqueId(), this.world, challenge)) - { - challengeDescriptionMap.put(challenge, this.generateChallengeDescription(challenge, player)); - } - } - - new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, valueSet) -> { - if (status) - { - valueSet.forEach(challenge -> manager.setChallengeComplete(player.getUniqueId(), this.world, challenge, this.user.getUniqueId())); - } - - this.build(); - }); - break; - case RESET: - challengeDescriptionMap = new LinkedHashMap<>(); - - for (Challenge challenge : manager.getAllChallenges(this.world)) - { - if (manager.isChallengeComplete(player.getUniqueId(), this.world, challenge)) - { - challengeDescriptionMap.put(challenge, this.generateChallengeDescription(challenge, player)); - } - } - - new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, valueSet) -> { - if (status) - { - valueSet.forEach(challenge -> manager.resetChallenge(player.getUniqueId(), this.world, challenge, this.user.getUniqueId())); - } - - this.build(); - }); - break; - case RESET_ALL: - new ConfirmationGUI(this.user, status -> { - if (status) - { - manager.resetAllChallenges(player.getUniqueId(), this.world, this.user.getUniqueId()); - } - - this.build(); - }); - break; - } - - return true; - }).build(); - } - else - { - return new PanelItemBuilder(). - name(player.getName()). - icon(Material.BARRIER). - description(GuiUtils.stringSplit(this.user.getTranslation("general.errors.player-has-no-island"), lineLength)). - clickHandler((panel, user1, clickType, slot) -> false). - build(); - } - } - - - /** - * This method collects users based on view mode. - * @param mode Given view mode. - * @return List with players in necessary view mode. - */ - private List collectUsers(ViewMode mode) - { - if (mode.equals(ViewMode.ONLINE)) - { - return new ArrayList<>(Bukkit.getOnlinePlayers()); - } - else if (mode.equals(ViewMode.WITH_ISLAND)) - { - return this.addon.getPlayers().getPlayers().stream(). - filter(player -> this.addon.getIslands().getIsland(this.world, player.getPlayerUUID()) != null). - map(Players::getPlayer). - collect(Collectors.toList()); - } - else - { - return new ArrayList<>(this.world.getPlayers()); - } - } - - - /** - * This method creates Player List view Mode toggle button. - * @return Button that toggles through player view mode. - */ - private PanelItem createToggleButton() - { - List description = new ArrayList<>(ViewMode.values().length + 1); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.toggle-user-list")); - description.add((ViewMode.ONLINE == ViewMode.values()[this.modeIndex] ? "&2" : "&c") + - this.user.getTranslation("challenges.gui.descriptions.admin.mode-online")); - description.add((ViewMode.WITH_ISLAND == ViewMode.values()[this.modeIndex] ? "&2" : "&c") + - this.user.getTranslation("challenges.gui.descriptions.admin.mode-in-world")); - description.add((ViewMode.IN_WORLD == ViewMode.values()[this.modeIndex] ? "&2" : "&c") + - this.user.getTranslation("challenges.gui.descriptions.admin.mode-with-island")); - - return new PanelItemBuilder(). - name(this.user.getTranslation("challenges.gui.buttons.admin.toggle-user-list")). - description(GuiUtils.stringSplit(description, this.addon.getChallengesSettings().getLoreLineLength())). - icon(Material.STONE_BUTTON). - clickHandler( - (panel, user1, clickType, slot) -> { - if (clickType.isRightClick()) - { - this.modeIndex--; - - if (this.modeIndex < 0) - { - this.modeIndex = ViewMode.values().length - 1; - } - } - else - { - this.modeIndex++; - - if (this.modeIndex >= ViewMode.values().length) - { - this.modeIndex = 0; - } - } - - this.onlineUsers = this.collectUsers(ViewMode.values()[this.modeIndex]); - this.pageIndex = 0; - this.build(); - return true; - }).build(); - } -} \ No newline at end of file diff --git a/src/main/java/world/bentobox/challenges/panel/admin/ListUsersPanel.java b/src/main/java/world/bentobox/challenges/panel/admin/ListUsersPanel.java new file mode 100644 index 0000000..94a6e24 --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/admin/ListUsersPanel.java @@ -0,0 +1,376 @@ +package world.bentobox.challenges.panel.admin; + + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.entity.Player; + +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.bentobox.database.objects.Island; +import world.bentobox.bentobox.database.objects.Players; +import world.bentobox.challenges.ChallengesAddon; +import world.bentobox.challenges.database.object.Challenge; +import world.bentobox.challenges.panel.CommonPagedPanel; +import world.bentobox.challenges.panel.CommonPanel; +import world.bentobox.challenges.panel.util.ChallengeSelector; +import world.bentobox.challenges.utils.Constants; +import world.bentobox.challenges.utils.GuiUtils; +import world.bentobox.challenges.utils.Utils; + + +/** + * This class contains methods that allows to select specific user. + */ +public class ListUsersPanel extends CommonPagedPanel +{ + // --------------------------------------------------------------------- + // Section: Constructors + // --------------------------------------------------------------------- + + + /** + * @param addon Addon where panel operates. + * @param world World from which panel was created. + * @param user User who created panel. + * @param topLabel Command top label which creates panel (f.e. island or ai) + * @param permissionPrefix Command permission prefix (f.e. bskyblock.) + * @param operationMode Indicate what should happen on player icon click. + */ + private ListUsersPanel(ChallengesAddon addon, + User user, + World world, + String topLabel, + String permissionPrefix, + Mode operationMode) + { + super(addon, user, world, topLabel, permissionPrefix); + this.onlineUsers = this.collectUsers(ViewMode.IN_WORLD); + this.operationMode = operationMode; + } + + + /** + * @param operationMode Indicate what should happen on player icon click. + */ + private ListUsersPanel(CommonPanel panel, Mode operationMode) + { + super(panel); + this.onlineUsers = this.collectUsers(ViewMode.IN_WORLD); + this.operationMode = operationMode; + } + + + /** + * Open the Challenges Admin GUI. + * + * @param addon the addon + * @param world the world + * @param user the user + * @param topLabel the top label + * @param permissionPrefix the permission prefix + */ + public static void open(ChallengesAddon addon, + World world, + User user, + String topLabel, + String permissionPrefix, + Mode mode) + { + new ListUsersPanel(addon, user, world, topLabel, permissionPrefix, mode).build(); + } + + + /** + * Open the Challenges Admin GUI. + */ + public static void open(CommonPanel parentGUI, Mode mode) + { + new ListUsersPanel(parentGUI, mode).build(); + } + + + // --------------------------------------------------------------------- + // Section: Methods + // --------------------------------------------------------------------- + + + @Override + protected void build() + { + PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name( + this.user.getTranslation(Constants.TITLE + "choose-player")); + + GuiUtils.fillBorder(panelBuilder); + + this.populateElements(panelBuilder, + this.onlineUsers, + o -> this.createPlayerIcon((Player) o)); + + // Add button that allows to toggle different player lists. + panelBuilder.item( 4, this.createToggleButton()); + panelBuilder.item(44, this.returnButton); + + panelBuilder.build(); + } + + + /** + * This method creates button for given user. If user has island it will add valid click handler. + * @param player Player which button must be created. + * @return Player button. + */ + private PanelItem createPlayerIcon(Player player) + { + final String reference = Constants.BUTTON + "player."; + + Island island = this.addon.getIslands().getIsland(this.world, player.getUniqueId()); + + if (island == null) + { + return new PanelItemBuilder(). + name(this.user.getTranslation(reference + "name", "[name]", player.getName())). + icon(Material.BARRIER). + description(this.user.getTranslation(reference + "no-island")). + build(); + } + + List description = new ArrayList<>(4); + description.add(this.user.getTranslation(reference + "description", + "[owner]", this.addon.getPlayers().getName(island.getOwner()))); + + // Is owner in his own island member set? I assume yes. Need testing. + if (island.getMemberSet().size() > 1) + { + description.add(this.user.getTranslation(reference + "members")); + island.getMemberSet().forEach(member -> { + if (member != island.getOwner()) + { + description.add(this.user.getTranslation(reference + "member", + "[name]", this.addon.getPlayers().getName(member))); + } + }); + } + + description.add(""); + + if (this.operationMode == Mode.RESET_ALL && this.selectedPlayer != null) + { + description.add(this.user.getTranslation(Constants.TIPS + "click-to-reset-all")); + } + else + { + description.add(this.user.getTranslation(Constants.TIPS + "click-to-choose")); + } + + return new PanelItemBuilder(). + name(this.user.getTranslation(reference + "name", "[name]", player.getName())). + icon(player.getName()). + description(description). + glow(this.operationMode == Mode.RESET_ALL && this.selectedPlayer == player). + clickHandler((panel, user1, clickType, i) -> { + switch (this.operationMode) + { + case COMPLETE -> { + // Get all challenge that is in current level. + List challengeList = this.manager.getAllChallenges(this.world); + + // Generate descriptions for these challenges + Map> challengeDescriptionMap = challengeList.stream(). + filter(challenge -> !this.manager.isChallengeComplete(player.getUniqueId(), this.world, challenge)). + collect(Collectors.toMap(challenge -> challenge, + challenge -> this.generateChallengeDescription(challenge, User.getInstance(player)), + (a, b) -> b, + () -> new LinkedHashMap<>(challengeList.size()))); + + // Open select gui + ChallengeSelector.open(this.user, + Material.LIME_STAINED_GLASS_PANE, + challengeDescriptionMap, + (status, valueSet) -> { + if (status) + { + valueSet.forEach(challenge -> + manager.setChallengeComplete(player.getUniqueId(), + this.world, + challenge, + this.user.getUniqueId())); + } + + this.build(); + }); + } + case RESET -> { + // Get all challenge that is in current level. + List challengeList = this.manager.getAllChallenges(this.world); + + // Generate descriptions for these challenges + Map> challengeDescriptionMap = challengeList.stream(). + filter(challenge -> this.manager.isChallengeComplete(player.getUniqueId(), this.world, challenge)). + collect(Collectors.toMap(challenge -> challenge, + challenge -> this.generateChallengeDescription(challenge, User.getInstance(player)), + (a, b) -> b, + () -> new LinkedHashMap<>(challengeList.size()))); + + // Open select gui + ChallengeSelector.open(this.user, + Material.ORANGE_STAINED_GLASS_PANE, + challengeDescriptionMap, + (status, valueSet) -> { + if (status) + { + valueSet.forEach(challenge -> + this.manager.resetChallenge(player.getUniqueId(), + this.world, + challenge, + this.user.getUniqueId())); + } + + this.build(); + }); + } + case RESET_ALL -> { + if (this.selectedPlayer == null) + { + this.selectedPlayer = player; + } + else + { + this.manager.resetAllChallenges(player.getUniqueId(), this.world, this.user.getUniqueId()); + this.selectedPlayer = null; + } + + this.build(); + } + } + + return true; + }). + build(); + } + + + /** + * This method collects users based on view mode. + * @param mode Given view mode. + * @return List with players in necessary view mode. + */ + private List collectUsers(ViewMode mode) + { + return switch (mode) { + case ONLINE -> new ArrayList<>(Bukkit.getOnlinePlayers()); + case WITH_ISLAND -> this.addon.getPlayers().getPlayers().stream(). + filter(player -> this.addon.getIslands().getIsland(this.world, player.getPlayerUUID()) != null). + map(Players::getPlayer). + collect(Collectors.toList()); + default -> new ArrayList<>(this.world.getPlayers()); + }; + } + + + /** + * This method creates Player List view Mode toggle button. + * @return Button that toggles through player view mode. + */ + private PanelItem createToggleButton() + { + final String reference = Constants.BUTTON + "player_list."; + + List description = new ArrayList<>(5); + + description.add(this.user.getTranslation(reference + "description")); + description.add(this.user.getTranslation(reference + + (ViewMode.ONLINE == this.mode ? "enabled" : "disabled")) + + this.user.getTranslation(reference + "online")); + description.add(this.user.getTranslation(reference + + (ViewMode.WITH_ISLAND == this.mode ? "enabled" : "disabled")) + + this.user.getTranslation(reference + "with_island")); + description.add(this.user.getTranslation(reference + + (ViewMode.IN_WORLD == this.mode ? "enabled" : "disabled")) + + this.user.getTranslation(reference + "in_world")); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "left-click-to-cycle")); + description.add(this.user.getTranslation(Constants.TIPS + "right-click-to-cycle")); + + return new PanelItemBuilder(). + name(this.user.getTranslation(reference + "name")). + icon(Material.STONE_BUTTON). + description(description). + clickHandler((panel, user1, clickType, slot) -> { + if (clickType.isRightClick()) + { + this.mode = Utils.getPreviousValue(ViewMode.values(), this.mode); + this.onlineUsers = this.collectUsers(this.mode); + } + else + { + this.mode = Utils.getNextValue(ViewMode.values(), this.mode); + this.onlineUsers = this.collectUsers(this.mode); + } + + this.build(); + return true; + }).build(); + } + + +// --------------------------------------------------------------------- +// Section: Enums +// --------------------------------------------------------------------- + + + /** + * This allows to switch which users should be in the list. + */ + private enum ViewMode + { + ONLINE, + WITH_ISLAND, + IN_WORLD + } + + /** + * This allows to decide what User Icon should do. + */ + public enum Mode + { + COMPLETE, + RESET, + RESET_ALL + } + + +// --------------------------------------------------------------------- +// Section: Variables +// --------------------------------------------------------------------- + + /** + * List with players that should be in GUI. + */ + private List onlineUsers; + + /** + * Current operation mode. + */ + private final Mode operationMode; + + /** + * Current index of view mode + */ + private ViewMode mode = ViewMode.ONLINE; + + /** + * Stores clicked player. + */ + private Player selectedPlayer; +} \ No newline at end of file diff --git a/src/main/java/world/bentobox/challenges/panel/admin/ManageBlocksGUI.java b/src/main/java/world/bentobox/challenges/panel/admin/ManageBlocksGUI.java deleted file mode 100644 index eab6371..0000000 --- a/src/main/java/world/bentobox/challenges/panel/admin/ManageBlocksGUI.java +++ /dev/null @@ -1,241 +0,0 @@ -package world.bentobox.challenges.panel.admin; - - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.lang.WordUtils; -import org.bukkit.Material; -import org.bukkit.World; - -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.panel.CommonGUI; -import world.bentobox.challenges.panel.util.NumberGUI; -import world.bentobox.challenges.panel.util.SelectBlocksGUI; -import world.bentobox.challenges.utils.GuiUtils; - - -/** - * This class allows to edit material that are in required material map. - */ -public class ManageBlocksGUI extends CommonGUI -{ - public ManageBlocksGUI(ChallengesAddon addon, - World world, - User user, - Map materialMap, - String topLabel, - String permissionPrefix, - CommonGUI parentGUI) - { - super(addon, world, user, topLabel, permissionPrefix, parentGUI); - this.materialMap = materialMap; - - this.materialList = new ArrayList<>(this.materialMap.keySet()); - - // Sort materials by their ordinal value. - this.materialList.sort(Comparator.comparing(Enum::ordinal)); - - this.selectedMaterials = new HashSet<>(); - } - - -// --------------------------------------------------------------------- -// Section: Methods -// --------------------------------------------------------------------- - - - /** - * This method builds all necessary elements in GUI panel. - */ - @Override - public void build() - { - PanelBuilder panelBuilder = new PanelBuilder().user(this.user). - name(this.user.getTranslation("challenges.gui.title.admin.manage-blocks")); - - // Create nice border. - GuiUtils.fillBorder(panelBuilder); - - panelBuilder.item(3, this.createButton(Button.ADD)); - panelBuilder.item(5, this.createButton(Button.REMOVE)); - - final int MAX_ELEMENTS = 21; - - if (this.pageIndex < 0) - { - this.pageIndex = this.materialList.size() / MAX_ELEMENTS; - } - else if (this.pageIndex > (this.materialList.size() / MAX_ELEMENTS)) - { - this.pageIndex = 0; - } - - int entitiesIndex = MAX_ELEMENTS * this.pageIndex; - - // I want first row to be only for navigation and return button. - int index = 10; - - while (entitiesIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) && - entitiesIndex < this.materialList.size() && - index < 36) - { - if (!panelBuilder.slotOccupied(index)) - { - panelBuilder.item(index, this.createElementButton(this.materialList.get(entitiesIndex++))); - } - - index++; - } - - // Navigation buttons only if necessary - if (this.materialList.size() > MAX_ELEMENTS) - { - panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS)); - panelBuilder.item(26, this.getButton(CommonButtons.NEXT)); - } - - // Add return button. - panelBuilder.item(44, this.returnButton); - - panelBuilder.build(); - } - - - /** - * This method creates PanelItem button of requested type. - * @param button Button which must be created. - * @return new PanelItem with requested functionality. - */ - private PanelItem createButton(Button button) - { - int lineLength = this.addon.getChallengesSettings().getLoreLineLength(); - PanelItemBuilder builder = new PanelItemBuilder(); - - switch (button) - { - case ADD: - builder.name(this.user.getTranslation("challenges.gui.buttons.admin.add")); - builder.icon(Material.BUCKET); - builder.clickHandler((panel, user1, clickType, slot) -> { - - new SelectBlocksGUI(this.user, false, new HashSet<>(this.materialList), (status, materials) -> { - if (status) - { - materials.forEach(material -> { - this.materialMap.put(material, 1); - this.materialList.add(material); - }); - } - - this.build(); - }); - return true; - }); - break; - case REMOVE: - builder.name(this.user.getTranslation("challenges.gui.buttons.admin.remove-selected")); - builder.description(GuiUtils.stringSplit(this.user.getTranslation("challenges.gui.descriptions.admin.remove-selected"), lineLength)); - builder.icon(Material.LAVA_BUCKET); - builder.clickHandler((panel, user1, clickType, slot) -> { - this.materialMap.keySet().removeAll(this.selectedMaterials); - this.materialList.removeAll(this.selectedMaterials); - this.build(); - return true; - }); - break; - } - - return builder.build(); - } - - - /** - * This method creates button for given material. - * @param material material which button must be created. - * @return new Button for material. - */ - private PanelItem createElementButton(Material material) - { - return new PanelItemBuilder(). - name(WordUtils.capitalize(material.name().toLowerCase().replace("_", " "))). - icon(GuiUtils.getMaterialItem(material, this.materialMap.get(material))). - description(this.selectedMaterials.contains(material) ? - this.user.getTranslation("challenges.gui.descriptions.admin.selected") : ""). - clickHandler((panel, user1, clickType, slot) -> { - // On right click change which entities are selected for deletion. - if (clickType.isRightClick()) - { - if (!this.selectedMaterials.add(material)) - { - // Remove material if it is already selected - this.selectedMaterials.remove(material); - } - - this.build(); - } - else - { - new NumberGUI(this.user, - this.materialMap.get(material), - 1, - this.addon.getChallengesSettings().getLoreLineLength(), - (status, value) -> { - if (status) - { - // Update value only when something changes. - this.materialMap.put(material, value); - } - - this.build(); - }); - } - return true; - }). - glow(this.selectedMaterials.contains(material)). - build(); - } - - -// --------------------------------------------------------------------- -// Section: Enums -// --------------------------------------------------------------------- - - - /** - * Functional buttons in current GUI. - */ - private enum Button - { - ADD, - REMOVE - } - - -// --------------------------------------------------------------------- -// Section: Variables -// --------------------------------------------------------------------- - - /** - * Contains selected materials. - */ - private Set selectedMaterials; - - /** - * List of materials to avoid order issues. - */ - private List materialList; - - /** - * List of required materials. - */ - private Map materialMap; -} diff --git a/src/main/java/world/bentobox/challenges/panel/admin/ManageBlocksPanel.java b/src/main/java/world/bentobox/challenges/panel/admin/ManageBlocksPanel.java new file mode 100644 index 0000000..dd86bf0 --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/admin/ManageBlocksPanel.java @@ -0,0 +1,282 @@ +package world.bentobox.challenges.panel.admin; + + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Consumer; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +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.challenges.panel.CommonPagedPanel; +import world.bentobox.challenges.panel.CommonPanel; +import world.bentobox.challenges.panel.ConversationUtils; +import world.bentobox.challenges.panel.util.MultiBlockSelector; +import world.bentobox.challenges.utils.Constants; +import world.bentobox.challenges.utils.GuiUtils; +import world.bentobox.challenges.utils.Utils; + + +/** + * This class allows to edit material that are in required material map. + */ +public class ManageBlocksPanel extends CommonPagedPanel +{ + private ManageBlocksPanel(CommonPanel parentGUI, Map materialMap) + { + super(parentGUI); + this.materialMap = materialMap; + this.materialList = new ArrayList<>(this.materialMap.keySet()); + + // Sort materials by their ordinal value. + this.materialList.sort(Comparator.comparing(Enum::ordinal)); + + this.selectedMaterials = new HashSet<>(); + } + + + /** + * Open the Challenges Admin GUI. + */ + public static void open(CommonPanel parentGUI, Map materialMap) + { + new ManageBlocksPanel(parentGUI, materialMap).build(); + } + + +// --------------------------------------------------------------------- +// Section: Methods +// --------------------------------------------------------------------- + + + /** + * This method builds all necessary elements in GUI panel. + */ + @Override + public void build() + { + PanelBuilder panelBuilder = new PanelBuilder().user(this.user). + name(this.user.getTranslation(Constants.TITLE + "manage-blocks")); + + // Create nice border. + GuiUtils.fillBorder(panelBuilder); + + panelBuilder.item(3, this.createButton(Button.ADD_BLOCK)); + panelBuilder.item(5, this.createButton(Button.REMOVE_BLOCK)); + + this.populateElements(panelBuilder, + this.materialList, + o -> this.createElementButton((Material) o)); + + // Add return button. + panelBuilder.item(44, this.returnButton); + + panelBuilder.build(); + } + + + /** + * This method creates PanelItem button of requested type. + * @param button Button which must be created. + * @return new PanelItem with requested functionality. + */ + private PanelItem createButton(Button button) + { + final String reference = Constants.BUTTON + button.name().toLowerCase() + "."; + + final String name = this.user.getTranslation(reference + "name"); + final List description = new ArrayList<>(3); + description.add(this.user.getTranslation(reference + "description")); + + ItemStack icon; + PanelItem.ClickHandler clickHandler; + boolean glow; + + switch (button) + { + case ADD_BLOCK -> { + icon = new ItemStack(Material.BUCKET); + clickHandler = (panel, user1, clickType, slot) -> + { + MultiBlockSelector.open(this.user, + MultiBlockSelector.Mode.BLOCKS, + new HashSet<>(this.materialList), + (status, materials) -> + { + if (status) + { + materials.forEach(material -> + { + this.materialMap.put(material, 1); + this.materialList.add(material); + }); + } + + this.build(); + }); + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-add")); + } + case REMOVE_BLOCK -> { + + if (!this.selectedMaterials.isEmpty()) + { + description.add(this.user.getTranslation(reference + "title")); + this.selectedMaterials.forEach(material -> { + description.add(this.user.getTranslation(reference + "material", + "[material]", Utils.prettifyObject(material, this.user))); + }); + } + + icon = new ItemStack(Material.LAVA_BUCKET); + + clickHandler = (panel, user1, clickType, slot) -> + { + if (!this.selectedMaterials.isEmpty()) + { + this.materialMap.keySet().removeAll(this.selectedMaterials); + this.materialList.removeAll(this.selectedMaterials); + this.selectedMaterials.clear(); + this.build(); + } + + return true; + }; + + glow = !this.selectedMaterials.isEmpty(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-remove")); + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + glow = false; + } + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + clickHandler(clickHandler). + glow(glow). + build(); + } + + + /** + * This method creates button for given material. + * @param material material which button must be created. + * @return new Button for material. + */ + private PanelItem createElementButton(Material material) + { + final String reference = Constants.BUTTON + "material."; + + List description = new ArrayList<>(); + + if (this.selectedMaterials.contains(material)) + { + description.add(this.user.getTranslation(reference + "selected")); + } + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "left-click-to-choose")); + + if (this.selectedMaterials.contains(material)) + { + description.add(this.user.getTranslation(Constants.TIPS + "right-click-to-deselect")); + } + else + { + description.add(this.user.getTranslation(Constants.TIPS + "right-click-to-select")); + } + + return new PanelItemBuilder(). + name(this.user.getTranslation(reference + "name", "[material]", + Utils.prettifyObject(material, this.user))). + icon(GuiUtils.getMaterialItem(material, this.materialMap.get(material))). + description(description). + clickHandler((panel, user1, clickType, slot) -> { + // On right click change which entities are selected for deletion. + if (clickType.isRightClick()) + { + if (!this.selectedMaterials.add(material)) + { + // Remove material if it is already selected + this.selectedMaterials.remove(material); + } + + this.build(); + } + else + { + Consumer numberConsumer = number -> { + if (number != null) + { + this.materialMap.put(material, number.intValue()); + } + + // reopen panel + this.build(); + }; + + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 1, + Integer.MAX_VALUE); + } + return true; + }). + glow(this.selectedMaterials.contains(material)). + build(); + } + + +// --------------------------------------------------------------------- +// Section: Enums +// --------------------------------------------------------------------- + + + /** + * Functional buttons in current GUI. + */ + private enum Button + { + ADD_BLOCK, + REMOVE_BLOCK + } + + +// --------------------------------------------------------------------- +// Section: Variables +// --------------------------------------------------------------------- + + /** + * Contains selected materials. + */ + private final Set selectedMaterials; + + /** + * List of materials to avoid order issues. + */ + private final List materialList; + + /** + * List of required materials. + */ + private final Map materialMap; +} diff --git a/src/main/java/world/bentobox/challenges/panel/admin/ManageEntitiesGUI.java b/src/main/java/world/bentobox/challenges/panel/admin/ManageEntitiesGUI.java deleted file mode 100644 index ed29747..0000000 --- a/src/main/java/world/bentobox/challenges/panel/admin/ManageEntitiesGUI.java +++ /dev/null @@ -1,258 +0,0 @@ -package world.bentobox.challenges.panel.admin; - - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.lang.WordUtils; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.entity.EntityType; - -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.panel.CommonGUI; -import world.bentobox.challenges.panel.util.NumberGUI; -import world.bentobox.challenges.panel.util.SelectEntityGUI; -import world.bentobox.challenges.utils.GuiUtils; - - -/** - * This class allows to edit entities that are in required entities map. - */ -public class ManageEntitiesGUI extends CommonGUI -{ - public ManageEntitiesGUI(ChallengesAddon addon, - World world, - User user, - Map requiredEntities, - String topLabel, - String permissionPrefix, - CommonGUI parentGUI) - { - super(addon, world, user, topLabel, permissionPrefix, parentGUI); - this.requiredEntities = requiredEntities; - - this.entityList = new ArrayList<>(this.requiredEntities.keySet()); - this.entityList.sort(Comparator.comparing(Enum::name)); - - this.selectedEntities = new HashSet<>(EntityType.values().length); - } - - -// --------------------------------------------------------------------- -// Section: Methods -// --------------------------------------------------------------------- - - - /** - * This method builds all necessary elements in GUI panel. - */ - @Override - public void build() - { - PanelBuilder panelBuilder = new PanelBuilder().user(this.user). - name(this.user.getTranslation("challenges.gui.title.admin.manage-entities")); - - // create border - GuiUtils.fillBorder(panelBuilder); - - panelBuilder.item(3, this.createButton(Button.ADD)); - panelBuilder.item(5, this.createButton(Button.REMOVE)); - panelBuilder.item(8, this.createButton(Button.SWITCH)); - - final int MAX_ELEMENTS = 21; - - if (this.pageIndex < 0) - { - this.pageIndex = this.entityList.size() / MAX_ELEMENTS; - } - else if (this.pageIndex > (this.entityList.size() / MAX_ELEMENTS)) - { - this.pageIndex = 0; - } - - int entitiesIndex = MAX_ELEMENTS * this.pageIndex; - - // I want first row to be only for navigation and return button. - int index = 10; - - while (entitiesIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) && - entitiesIndex < this.entityList.size() && - index < 26) - { - if (!panelBuilder.slotOccupied(index)) - { - panelBuilder.item(index, this.createEntityButton(this.entityList.get(entitiesIndex++))); - } - - index++; - } - - // Navigation buttons only if necessary - if (this.entityList.size() > MAX_ELEMENTS) - { - panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS)); - panelBuilder.item(26, this.getButton(CommonButtons.NEXT)); - } - - // Add return button. - panelBuilder.item(44, this.returnButton); - - panelBuilder.build(); - } - - - /** - * This method creates PanelItem button of requested type. - * @param button Button which must be created. - * @return new PanelItem with requested functionality. - */ - private PanelItem createButton(Button button) - { - int lineLength = this.addon.getChallengesSettings().getLoreLineLength(); - PanelItemBuilder builder = new PanelItemBuilder(); - - switch (button) - { - case ADD: - builder.name(this.user.getTranslation("challenges.gui.buttons.admin.add")); - builder.icon(Material.BUCKET); - builder.clickHandler((panel, user1, clickType, slot) -> { - new SelectEntityGUI(this.user, this.requiredEntities.keySet(), this.asEggs, (status, entities) -> { - if (status) - { - entities.forEach(entity -> { - this.requiredEntities.put(entity, 1); - this.entityList.add(entity); - }); - } - - this.build(); - }); - return true; - }); - break; - case REMOVE: - builder.name(this.user.getTranslation("challenges.gui.buttons.admin.remove-selected")); - builder.description(GuiUtils.stringSplit(this.user.getTranslation("challenges.gui.descriptions.admin.remove-selected"), lineLength)); - builder.icon(Material.LAVA_BUCKET); - builder.clickHandler((panel, user1, clickType, slot) -> { - this.requiredEntities.keySet().removeAll(this.selectedEntities); - this.entityList.removeAll(this.selectedEntities); - this.build(); - return true; - }); - break; - case SWITCH: - builder.name(this.user.getTranslation("challenges.gui.buttons.admin.show-eggs")); - builder.description(GuiUtils.stringSplit(this.user.getTranslation("challenges.gui.descriptions.admin.show-eggs"), lineLength)); - builder.icon(this.asEggs ? Material.EGG : Material.PLAYER_HEAD); - builder.clickHandler((panel, user1, clickType, slot) -> { - this.asEggs = !this.asEggs; - this.build(); - return true; - }); - break; - } - - return builder.build(); - } - - - /** - * This method creates button for given entity. - * @param entity Entity which button must be created. - * @return new Button for entity. - */ - private PanelItem createEntityButton(EntityType entity) - { - return new PanelItemBuilder(). - name(WordUtils.capitalize(entity.name().toLowerCase().replace("_", " "))). - description(this.selectedEntities.contains(entity) ? - this.user.getTranslation("challenges.gui.descriptions.admin.selected") : ""). - icon(this.asEggs ? - GuiUtils.getEntityEgg(entity, this.requiredEntities.get(entity)) : - GuiUtils.getEntityHead(entity, this.requiredEntities.get(entity))). - clickHandler((panel, user1, clickType, slot) -> { - // On right click change which entities are selected for deletion. - if (clickType.isRightClick()) - { - if (!this.selectedEntities.add(entity)) - { - // Remove entity if it is already selected - this.selectedEntities.remove(entity); - } - - this.build(); - } - else - { - new NumberGUI(this.user, - this.requiredEntities.get(entity), - 1, - this.addon.getChallengesSettings().getLoreLineLength(), - (status, value) -> { - if (status) - { - // Update value only when something changes. - this.requiredEntities.put(entity, value); - } - - this.build(); - }); - } - return true; - }). - glow(this.selectedEntities.contains(entity)). - build(); - } - - -// --------------------------------------------------------------------- -// Section: Enums -// --------------------------------------------------------------------- - - - /** - * Functional buttons in current GUI. - */ - private enum Button - { - ADD, - REMOVE, - SWITCH - } - - -// --------------------------------------------------------------------- -// Section: Variables -// --------------------------------------------------------------------- - - /** - * List with entities to avoid list irregularities. - */ - private List entityList; - - /** - * Set with entities that are selected. - */ - private Set selectedEntities; - - /** - * Map that contains all entities and their cound. - */ - private Map requiredEntities; - - /** - * Boolean indicate if entities should be displayed as eggs or mob heads. - */ - private boolean asEggs; -} diff --git a/src/main/java/world/bentobox/challenges/panel/admin/ManageEntitiesPanel.java b/src/main/java/world/bentobox/challenges/panel/admin/ManageEntitiesPanel.java new file mode 100644 index 0000000..923c139 --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/admin/ManageEntitiesPanel.java @@ -0,0 +1,302 @@ +package world.bentobox.challenges.panel.admin; + + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Consumer; + +import org.bukkit.Material; +import org.bukkit.entity.EntityType; +import org.bukkit.inventory.ItemStack; + +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.challenges.panel.CommonPagedPanel; +import world.bentobox.challenges.panel.CommonPanel; +import world.bentobox.challenges.panel.ConversationUtils; +import world.bentobox.challenges.panel.util.MultiEntitySelector; +import world.bentobox.challenges.utils.Constants; +import world.bentobox.challenges.utils.GuiUtils; +import world.bentobox.challenges.utils.Utils; + + +/** + * This class allows to edit entities that are in required entities map. + */ +public class ManageEntitiesPanel extends CommonPagedPanel +{ + private ManageEntitiesPanel(CommonPanel parentGUI, Map requiredEntities) + { + super(parentGUI); + this.requiredEntities = requiredEntities; + + this.entityList = new ArrayList<>(this.requiredEntities.keySet()); + this.entityList.sort(Comparator.comparing(Enum::name)); + + this.selectedEntities = new HashSet<>(EntityType.values().length); + } + + + /** + * Open the Challenges Admin GUI. + */ + public static void open(CommonPanel parentGUI, Map requiredEntities) + { + new ManageEntitiesPanel(parentGUI, requiredEntities).build(); + } + + +// --------------------------------------------------------------------- +// Section: Methods +// --------------------------------------------------------------------- + + + /** + * This method builds all necessary elements in GUI panel. + */ + @Override + public void build() + { + PanelBuilder panelBuilder = new PanelBuilder().user(this.user). + name(this.user.getTranslation(Constants.TITLE + "manage-entities")); + + // create border + GuiUtils.fillBorder(panelBuilder); + + panelBuilder.item(3, this.createButton(Button.ADD_ENTITY)); + panelBuilder.item(5, this.createButton(Button.REMOVE_ENTITY)); + panelBuilder.item(8, this.createButton(Button.SWITCH_ENTITY)); + + this.populateElements(panelBuilder, + this.entityList, + o -> this.createEntityButton((EntityType) o)); + + // Add return button. + panelBuilder.item(44, this.returnButton); + + panelBuilder.build(); + } + + + /** + * This method creates PanelItem button of requested type. + * @param button Button which must be created. + * @return new PanelItem with requested functionality. + */ + private PanelItem createButton(Button button) + { + final String reference = Constants.BUTTON + button.name().toLowerCase() + "."; + + final String name = this.user.getTranslation(reference + "name"); + final List description = new ArrayList<>(3); + description.add(this.user.getTranslation(reference + "description")); + + ItemStack icon; + PanelItem.ClickHandler clickHandler; + boolean glow; + + switch (button) + { + case ADD_ENTITY -> { + icon = new ItemStack(Material.BUCKET); + clickHandler = (panel, user1, clickType, slot) -> { + MultiEntitySelector.open(this.user, + this.asEggs, + MultiEntitySelector.Mode.ALIVE, + this.requiredEntities.keySet(), + (status, entities) -> { + if (status) + { + entities.forEach(entity -> { + this.requiredEntities.put(entity, 1); + this.entityList.add(entity); + }); + } + + this.build(); + }); + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-add")); + } + case REMOVE_ENTITY -> { + + if (!this.selectedEntities.isEmpty()) + { + description.add(this.user.getTranslation(reference + "title")); + this.selectedEntities.forEach(entity -> { + description.add(this.user.getTranslation(reference + "entity", + "[entity]", Utils.prettifyObject(entity, this.user))); + }); + } + + icon = new ItemStack(Material.LAVA_BUCKET); + + clickHandler = (panel, user1, clickType, slot) -> + { + if (!this.selectedEntities.isEmpty()) + { + this.requiredEntities.keySet().removeAll(this.selectedEntities); + this.entityList.removeAll(this.selectedEntities); + this.selectedEntities.clear(); + this.build(); + } + + return true; + }; + + glow = !this.entityList.isEmpty(); + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-remove")); + } + case SWITCH_ENTITY -> { + icon = new ItemStack(this.asEggs ? Material.EGG : Material.PLAYER_HEAD); + + clickHandler = (panel, user1, clickType, slot) -> { + this.asEggs = !this.asEggs; + this.build(); + return true; + }; + glow = false; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle")); + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + glow = false; + } + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + clickHandler(clickHandler). + glow(glow). + build(); + } + + + /** + * This method creates button for given entity. + * @param entity Entity which button must be created. + * @return new Button for entity. + */ + private PanelItem createEntityButton(EntityType entity) + { + final String reference = Constants.BUTTON + "entity."; + + List description = new ArrayList<>(); + + if (this.selectedEntities.contains(entity)) + { + description.add(this.user.getTranslation(reference + "selected")); + } + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "left-click-to-choose")); + + if (this.selectedEntities.contains(entity)) + { + description.add(this.user.getTranslation(Constants.TIPS + "right-click-to-deselect")); + } + else + { + description.add(this.user.getTranslation(Constants.TIPS + "right-click-to-select")); + } + + return new PanelItemBuilder(). + name(this.user.getTranslation(reference + "name", "[entity]", + Utils.prettifyObject(entity, this.user))). + icon(this.asEggs ? + GuiUtils.getEntityEgg(entity, this.requiredEntities.get(entity)) : + GuiUtils.getEntityHead(entity, this.requiredEntities.get(entity))). + description(description). + clickHandler((panel, user1, clickType, slot) -> { + // On right click change which entities are selected for deletion. + if (clickType.isRightClick()) + { + if (!this.selectedEntities.add(entity)) + { + // Remove entity if it is already selected + this.selectedEntities.remove(entity); + } + + this.build(); + } + else + { + Consumer numberConsumer = number -> { + if (number != null) + { + this.requiredEntities.put(entity, number.intValue()); + } + + // reopen panel + this.build(); + }; + + ConversationUtils.createNumericInput(numberConsumer, + this.user, + this.user.getTranslation(Constants.CONVERSATIONS + "input-number"), + 1, + Integer.MAX_VALUE); + } + return true; + }). + glow(this.selectedEntities.contains(entity)). + build(); + } + + +// --------------------------------------------------------------------- +// Section: Enums +// --------------------------------------------------------------------- + + + /** + * Functional buttons in current GUI. + */ + private enum Button + { + ADD_ENTITY, + REMOVE_ENTITY, + SWITCH_ENTITY + } + + +// --------------------------------------------------------------------- +// Section: Variables +// --------------------------------------------------------------------- + + /** + * List with entities to avoid list irregularities. + */ + private final List entityList; + + /** + * Set with entities that are selected. + */ + private final Set selectedEntities; + + /** + * Map that contains all entities and their cound. + */ + private final Map requiredEntities; + + /** + * Boolean indicate if entities should be displayed as eggs or mob heads. + */ + private boolean asEggs; +} diff --git a/src/main/java/world/bentobox/challenges/panel/user/ChallengesGUI.java b/src/main/java/world/bentobox/challenges/panel/user/ChallengesGUI.java deleted file mode 100644 index 5a29cad..0000000 --- a/src/main/java/world/bentobox/challenges/panel/user/ChallengesGUI.java +++ /dev/null @@ -1,528 +0,0 @@ -package world.bentobox.challenges.panel.user; - - -import java.util.List; - -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.inventory.ItemStack; - -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.managers.ChallengesManager; -import world.bentobox.challenges.config.SettingsUtils.VisibilityMode; -import world.bentobox.challenges.database.object.Challenge; -import world.bentobox.challenges.panel.CommonGUI; -import world.bentobox.challenges.tasks.TryToComplete; -import world.bentobox.challenges.utils.GuiUtils; -import world.bentobox.challenges.utils.LevelStatus; - - -/** - * This is UserGUI class. It contains everything necessary for user to use it. - */ -public class ChallengesGUI extends CommonGUI -{ -// --------------------------------------------------------------------- -// Section: Constructors -// --------------------------------------------------------------------- - - /** - * Default constructor that inits panels with minimal requirements, without parent panel. - * - * @param addon Addon where panel operates. - * @param world World from which panel was created. - * @param user User who created panel. - * @param topLabel Command top label which creates panel (f.e. island or ai) - * @param permissionPrefix Command permission prefix (f.e. bskyblock.) - */ - public ChallengesGUI(ChallengesAddon addon, - World world, - User user, - String topLabel, - String permissionPrefix) - { - super(addon, world, user, topLabel, permissionPrefix); - this.challengesManager = this.addon.getChallengesManager(); - - this.levelStatusList = this.challengesManager.getAllChallengeLevelStatus(this.user, this.world); - - for (LevelStatus levelStatus : this.levelStatusList) - { - if (levelStatus.isUnlocked()) - { - this.lastSelectedLevel = levelStatus; - } - else - { - break; - } - } - - this.containsChallenges = this.challengesManager.hasAnyChallengeData(this.world); - } - -// --------------------------------------------------------------------- -// Section: Methods -// --------------------------------------------------------------------- - - - /** - * This method builds all necessary elements in GUI panel. - */ - @Override - public void build() - { - // Do not open gui if there is no challenges. - if (!this.containsChallenges) - { - this.addon.logError("There are no challenges set up!"); - this.user.sendMessage("challenges.errors.no-challenges"); - return; - } - - PanelBuilder panelBuilder = new PanelBuilder().user(this.user). - name(this.user.getTranslation("challenges.gui.title.challenges")); - - // TODO: get last completed level. - - int nextItemIndex = 0; - - if (this.addon.getChallengesSettings().isFreeChallengesFirst()) - { - this.addFreeChallenges(panelBuilder, nextItemIndex); - - // Start new row for challenges. - if (panelBuilder.nextSlot() % 9 != 0) - { - nextItemIndex = panelBuilder.nextSlot() - panelBuilder.nextSlot() % 9 + 9; - } - else - { - nextItemIndex = panelBuilder.nextSlot(); - } - } - - this.addChallenges(panelBuilder, nextItemIndex); - - // Start new row for levels. - // Start new row for challenges. - if (panelBuilder.nextSlot() % 9 != 0) - { - nextItemIndex = panelBuilder.nextSlot() - panelBuilder.nextSlot() % 9 + 9; - } - else - { - nextItemIndex = panelBuilder.nextSlot(); - } - - this.addChallengeLevels(panelBuilder, nextItemIndex); - - if (!this.addon.getChallengesSettings().isFreeChallengesFirst()) - { - // Start new row for free challenges. - if (panelBuilder.nextSlot() % 9 != 0) - { - nextItemIndex = panelBuilder.nextSlot() - panelBuilder.nextSlot() % 9 + 9; - } - else - { - nextItemIndex = panelBuilder.nextSlot(); - } - - this.addFreeChallenges(panelBuilder, nextItemIndex); - } - - panelBuilder.build(); - } - - - /** - * This method adds free challenges to panelBuilder. - * @param panelBuilder where free challenges must be added. - * @param firstItemIndex index of first element. - */ - private void addFreeChallenges(PanelBuilder panelBuilder, int firstItemIndex) - { - List freeChallenges = this.challengesManager.getFreeChallenges(this.world); - - if (this.addon.getChallengesSettings().isRemoveCompleteOneTimeChallenges()) - { - freeChallenges.removeIf(challenge -> !challenge.isRepeatable() && - this.challengesManager.isChallengeComplete(this.user, this.world, challenge)); - } - - // Remove all undeployed challenges if VisibilityMode is set to Hidden. - if (this.addon.getChallengesSettings().getVisibilityMode().equals(VisibilityMode.HIDDEN)) - { - freeChallenges.removeIf(challenge -> !challenge.isDeployed()); - } - - final int freeChallengesCount = freeChallenges.size(); - - if (freeChallengesCount > 18) - { - int index = firstItemIndex; - - if (this.freeChallengeIndex > 0) - { - panelBuilder.item(index++, new PanelItemBuilder(). - icon(Material.OAK_SIGN). - name(this.user.getTranslation("challenges.gui.buttons.previous")). - clickHandler((panel, user1, clickType, slot) -> { - this.freeChallengeIndex--; - this.build(); - return true; - }).build()); - } - - int currentIndex = this.freeChallengeIndex; - - while (panelBuilder.nextSlot() != firstItemIndex + 18 && currentIndex < freeChallengesCount) - { - panelBuilder.item(index++, this.getChallengeButton(freeChallenges.get(currentIndex++))); - } - - // Check if one challenge is left - if (currentIndex + 1 == freeChallengesCount) - { - panelBuilder.item(index, this.getChallengeButton(freeChallenges.get(currentIndex))); - } - else if (currentIndex < freeChallengesCount) - { - panelBuilder.item(index, new PanelItemBuilder(). - icon(Material.OAK_SIGN). - name(this.user.getTranslation("challenges.gui.buttons.next")). - clickHandler((panel, user1, clickType, slot) -> { - this.freeChallengeIndex++; - this.build(); - return true; - }).build()); - } - } - else - { - for (Challenge challenge : freeChallenges) - { - // there are no limitations. Just bunch insert. - panelBuilder.item(firstItemIndex++, this.getChallengeButton(challenge)); - } - } - } - - - /** - * This method adds last selected level challenges to panelBuilder. - * @param panelBuilder where last selected level challenges must be added. - * @param firstItemIndex index of first element. - */ - private void addChallenges(PanelBuilder panelBuilder, int firstItemIndex) - { - if (this.lastSelectedLevel != null) - { - List challenges = this.challengesManager.getLevelChallenges(this.lastSelectedLevel.getLevel()); - - if (this.addon.getChallengesSettings().isRemoveCompleteOneTimeChallenges()) - { - challenges.removeIf(challenge -> !challenge.isRepeatable() && - this.challengesManager.isChallengeComplete(this.user, this.world, challenge)); - } - - // Remove all undeployed challenges if VisibilityMode is set to Hidden. - if (this.addon.getChallengesSettings().getVisibilityMode().equals(VisibilityMode.HIDDEN)) - { - challenges.removeIf(challenge -> !challenge.isDeployed()); - } - - final int challengesCount = challenges.size(); - - if (challengesCount > 18) - { - int index = firstItemIndex; - - if (this.pageIndex > 0) - { - panelBuilder.item(index++, new PanelItemBuilder(). - icon(Material.OAK_SIGN). - name(this.user.getTranslation("challenges.gui.buttons.previous")). - clickHandler((panel, user1, clickType, slot) -> { - this.pageIndex--; - this.build(); - return true; - }).build()); - } - - int currentIndex = this.pageIndex; - - while (panelBuilder.nextSlot() != firstItemIndex + 18 && currentIndex < challengesCount) - { - panelBuilder.item(index++, this.getChallengeButton(challenges.get(currentIndex++))); - } - - // Check if one challenge is left - if (currentIndex + 1 == challengesCount) - { - panelBuilder.item(index, this.getChallengeButton(challenges.get(currentIndex))); - } - else if (currentIndex < challengesCount) - { - panelBuilder.item(index, new PanelItemBuilder(). - icon(Material.OAK_SIGN). - name(this.user.getTranslation("challenges.gui.buttons.next")). - clickHandler((panel, user1, clickType, slot) -> { - this.pageIndex++; - this.build(); - return true; - }).build()); - } - } - else - { - for (Challenge challenge : challenges) - { - // there are no limitations. Just bunch insert. - panelBuilder.item(firstItemIndex++, this.getChallengeButton(challenge)); - } - } - } - } - - - /** - * This method adds challenge levels to panelBuilder. - * @param panelBuilder where challenge levels must be added. - * @param firstItemIndex index of first element. - */ - private void addChallengeLevels(PanelBuilder panelBuilder, int firstItemIndex) - { - final int levelCounts = this.levelStatusList.size(); - - if (levelCounts > 9) - { - int index = firstItemIndex; - - if (this.levelIndex > 0) - { - panelBuilder.item(index++, new PanelItemBuilder(). - icon(Material.OAK_SIGN). - name(this.user.getTranslation("challenges.gui.buttons.previous")). - clickHandler((panel, user1, clickType, slot) -> { - this.levelIndex--; - this.build(); - return true; - }).build()); - } - - int currentIndex = this.levelIndex; - - while (panelBuilder.nextSlot() != firstItemIndex + 9 && currentIndex < levelCounts) - { - panelBuilder.item(index++, this.getLevelButton(this.levelStatusList.get(currentIndex++))); - } - - // Check if one challenge is left - if (currentIndex + 1 == levelCounts) - { - panelBuilder.item(index, this.getLevelButton(this.levelStatusList.get(currentIndex))); - } - else if (currentIndex < levelCounts) - { - panelBuilder.item(index, new PanelItemBuilder(). - icon(Material.OAK_SIGN). - name(this.user.getTranslation("challenges.gui.buttons.next")). - clickHandler((panel, user1, clickType, slot) -> { - this.levelIndex++; - this.build(); - return true; - }).build()); - } - } - else - { - for (LevelStatus level : this.levelStatusList) - { - // there are no limitations. Just bunch insert. - panelBuilder.item(firstItemIndex++, this.getLevelButton(level)); - } - } - } - - -// --------------------------------------------------------------------- -// Section: Icon building -// --------------------------------------------------------------------- - - - /** - * This method creates given challenges icon that on press tries to complete it. - * @param challenge which icon must be constructed. - * @return PanelItem icon for challenge. - */ - private PanelItem getChallengeButton(Challenge challenge) - { - return new PanelItemBuilder(). - icon(challenge.getIcon()). - name(challenge.getFriendlyName().isEmpty() ? - challenge.getUniqueId() : - ChatColor.translateAlternateColorCodes('&', challenge.getFriendlyName())). - description(GuiUtils.stringSplit(this.generateChallengeDescription(challenge, this.user.getPlayer()), - this.addon.getChallengesSettings().getLoreLineLength())). - clickHandler((panel, user1, clickType, slot) -> { - - // Add ability to input how many repeats player should do. - // Do not open if challenge is not repeatable. - - if (clickType.isRightClick() && - challenge.isRepeatable() && - this.user.hasPermission(this.permissionPrefix + "challenges.multiple")) - { - new MultipleGUI(this.user, - this.addon.getChallengesSettings().getLoreLineLength(), - value -> { - TryToComplete.complete(this.addon, - this.user, - challenge, - this.world, - this.topLabel, - this.permissionPrefix, - value); - - this.build(); - }); - } - else - { - if (TryToComplete.complete(this.addon, - this.user, - challenge, - this.world, - this.topLabel, - this.permissionPrefix)) - { - panel.getInventory().setItem(slot, this.getChallengeButton(challenge).getItem()); - } - } - - return true; - }). - glow(this.addon.getChallengesSettings().isAddCompletedGlow() && - this.challengesManager.isChallengeComplete(this.user, this.world, challenge)). - build(); - } - - - /** - * This method creates button for given level. - * @param level which button must be created. - * @return Button for given level. - */ - private PanelItem getLevelButton(LevelStatus level) - { - // Create a nice name for the level - String name = level.getLevel().getFriendlyName().isEmpty() ? - level.getLevel().getUniqueId() : - level.getLevel().getFriendlyName(); - - ItemStack icon; - List description; - PanelItem.ClickHandler clickHandler; - boolean glow; - - if (level == this.lastSelectedLevel) - { - icon = level.getLevel().getIcon(); - description = GuiUtils.stringSplit( - this.generateLevelDescription(level.getLevel(), user.getPlayer()), - this.addon.getChallengesSettings().getLoreLineLength()); - clickHandler = null; - glow = true; - } - else if (level.isUnlocked()) - { - icon = level.getLevel().getIcon(); - description = GuiUtils.stringSplit( - this.generateLevelDescription(level.getLevel(), user.getPlayer()), - this.addon.getChallengesSettings().getLoreLineLength()); - clickHandler = (panel, user1, clickType, slot) -> { - this.lastSelectedLevel = level; - - // Reset page index for challenges. - this.pageIndex = 0; - - this.build(); - return true; - }; - glow = this.addon.getChallengesSettings().isAddCompletedGlow() && - this.challengesManager.isLevelCompleted(this.user, this.world, level.getLevel()); - } - else - { - if (level.getLevel().getLockedIcon() != null) - { - // Clone will prevent issues with description storing. - // It can be done only here as it can be null. - icon = level.getLevel().getLockedIcon().clone(); - } - else - { - icon = this.addon.getChallengesSettings().getLockedLevelIcon(); - } - - description = GuiUtils.stringSplit( - this.user.getTranslation("challenges.gui.descriptions.level-locked", - "[count]", Integer.toString(level.getNumberOfChallengesStillToDo()), - "[level]", level.getPreviousLevel().getFriendlyName()), - this.addon.getChallengesSettings().getLoreLineLength()); - - clickHandler = null; - glow = false; - } - - return new PanelItemBuilder(). - icon(icon). - name(ChatColor.translateAlternateColorCodes('&', name)). - description(description). - glow(glow). - clickHandler(clickHandler). - build(); - } - - -// --------------------------------------------------------------------- -// Section: Variables -// --------------------------------------------------------------------- - - /** - * This will be used if free challenges are more then 18. - */ - private int freeChallengeIndex = 0; - - /** - * This will be used if levels are more then 9. - */ - private int levelIndex; - - /** - * This list contains all information about level completion in current world. - */ - private List levelStatusList; - - /** - * This indicate last selected level. - */ - private LevelStatus lastSelectedLevel; - - /** - * Challenge Manager object. - */ - private ChallengesManager challengesManager; - - /** - * This boolean indicates if in the world there exist challenges for displaying in GUI. - */ - private final boolean containsChallenges; -} diff --git a/src/main/java/world/bentobox/challenges/panel/user/MultipleGUI.java b/src/main/java/world/bentobox/challenges/panel/user/MultipleGUI.java deleted file mode 100644 index 26a9690..0000000 --- a/src/main/java/world/bentobox/challenges/panel/user/MultipleGUI.java +++ /dev/null @@ -1,215 +0,0 @@ - -package world.bentobox.challenges.panel.user; - -import java.util.function.Consumer; - -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; - -import world.bentobox.bentobox.api.panels.Panel; -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.utils.GuiUtils; - - -/** - * This GUI will pop out when user uses right click on challenge. It is meant to choose - * how many times player will complete challenges. - */ -public class MultipleGUI -{ - /** - * Default constructor. - * @param user User who opens gui. - * @param lineLength Length of lore message. - * @param action Action that will be performed on value clicking. - */ - public MultipleGUI(User user, int lineLength, Consumer action) - { - this.user = user; - this.lineLength = lineLength; - this.action = action; - - this.build(); - } - - /** - * This method builds panel that allows to change given number value. - */ - private void build() - { - PanelBuilder panelBuilder = new PanelBuilder(). - user(this.user). - type(Panel.Type.HOPPER). - name(this.user.getTranslation("challenges.gui.title.multiple-complete")); - - panelBuilder.item(2, this.getButton(Button.VALUE)); - - // Reduce - panelBuilder.item(0, this.getButton(Button.REDUCE_LOT)); - panelBuilder.item(1, this.getButton(Button.REDUCE)); - - // Increase - panelBuilder.item(3, this.getButton(Button.INCREASE)); - panelBuilder.item(4, this.getButton(Button.INCREASE_LOT)); - - panelBuilder.build(); - } - - - /** - * This method creates PanelItem with required functionality. - * @param button Functionality requirement. - * @return PanelItem with functionality. - */ - private PanelItem getButton(Button button) - { - ItemStack icon; - String name; - String description; - PanelItem.ClickHandler clickHandler; - boolean glow; - - switch (button) - { - case VALUE: - { - name = this.user.getTranslation("challenges.gui.buttons.value"); - description = this.user.getTranslation("challenges.gui.descriptions.current-value", "[value]", Integer.toString(this.value)); - icon = new ItemStack(Material.GREEN_STAINED_GLASS_PANE); - clickHandler = (panel, user, clickType, slot) -> { - this.action.accept(this.value); - return true; - }; - glow = false; - break; - } - case INCREASE: - { - name = this.user.getTranslation("challenges.gui.buttons.increase"); - description = this.user.getTranslation("challenges.gui.descriptions.increase-by", "[value]", "1"); - icon = new ItemStack(Material.BLUE_STAINED_GLASS_PANE); - clickHandler = (panel, user, clickType, slot) -> { - this.value++; - // Necessary just to update second item - panel.getInventory().setItem(2, this.getButton(Button.VALUE).getItem()); - return true; - }; - glow = false; - break; - } - case INCREASE_LOT: - { - name = this.user.getTranslation("challenges.gui.buttons.increase"); - description = this.user.getTranslation("challenges.gui.descriptions.increase-by", "[value]", "5"); - icon = new ItemStack(Material.MAGENTA_STAINED_GLASS_PANE); - clickHandler = (panel, user, clickType, slot) -> { - this.value += 5; - // Necessary just to update second item - panel.getInventory().setItem(2, this.getButton(Button.VALUE).getItem()); - return true; - }; - glow = false; - break; - } - case REDUCE: - { - name = this.user.getTranslation("challenges.gui.buttons.reduce"); - description = this.user.getTranslation("challenges.gui.descriptions.reduce-by", "[value]", "1"); - icon = new ItemStack(Material.ORANGE_STAINED_GLASS_PANE); - clickHandler = (panel, user, clickType, slot) -> { - this.value--; - - if (this.value < 1) - { - this.value = 1; - } - - // Necessary just to update second item - panel.getInventory().setItem(2, this.getButton(Button.VALUE).getItem()); - - return true; - }; - glow = false; - break; - } - case REDUCE_LOT: - { - name = this.user.getTranslation("challenges.gui.buttons.reduce"); - description = this.user.getTranslation("challenges.gui.descriptions.reduce-by", "[value]", "5"); - icon = new ItemStack(Material.RED_STAINED_GLASS_PANE); - clickHandler = (panel, user, clickType, slot) -> { - this.value -= 5; - - if (this.value < 1) - { - this.value = 1; - } - - // Necessary just to update second item - panel.getInventory().setItem(2, this.getButton(Button.VALUE).getItem()); - - return true; - }; - glow = false; - break; - } - default: - return null; - } - - return new PanelItemBuilder(). - icon(icon). - name(name). - description(GuiUtils.stringSplit(description, this.lineLength)). - glow(glow). - clickHandler(clickHandler). - build(); - } - - -// --------------------------------------------------------------------- -// Section: Enums -// --------------------------------------------------------------------- - - - /** - * This enum allows to easier define available buttons. - */ - enum Button - { - VALUE, - REDUCE, - REDUCE_LOT, - INCREASE, - INCREASE_LOT - } - - -// --------------------------------------------------------------------- -// Section: Instance variables -// --------------------------------------------------------------------- - - - /** - * This variable allows to access to user object. - */ - private User user; - - /** - * This variable holds action that will be performed on accept. - */ - private Consumer action; - - /** - * This variable holds a number of characters in single line for lore message. - */ - private int lineLength; - - /** - * This integer holds current value of completion count. - */ - private int value = 1; -} diff --git a/src/main/java/world/bentobox/challenges/panel/util/ConfirmationGUI.java b/src/main/java/world/bentobox/challenges/panel/util/ConfirmationGUI.java deleted file mode 100644 index 5a979cc..0000000 --- a/src/main/java/world/bentobox/challenges/panel/util/ConfirmationGUI.java +++ /dev/null @@ -1,114 +0,0 @@ -package world.bentobox.challenges.panel.util; - - -import java.util.function.Consumer; - -import org.bukkit.Material; - -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.utils.GuiUtils; - - -/** - * This GUI is used to confirm that user wants to run command, that should be created from - * command string list. - */ -public class ConfirmationGUI -{ - /** - * This constructor inits and opens ConfirmationGUI. - * - * @param user Gui Caller. - */ - public ConfirmationGUI(User user, Consumer consumer) - { - this.user = user; - this.consumer = consumer; - - this.build(); - } - - - /** - * This method builds confirmation panel with 2 buttons. - */ - public void build() - { - PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(this.user.getTranslation("challenges.gui.title.admin.confirm-title")); - - GuiUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE); - - // Accept buttons - panelBuilder.item(10, this.getButton(true)); - panelBuilder.item(11, this.getButton(true)); - panelBuilder.item(12, this.getButton(true)); - - panelBuilder.item(19, this.getButton(true)); - panelBuilder.item(20, this.getButton(true)); - panelBuilder.item(21, this.getButton(true)); - - panelBuilder.item(28, this.getButton(true)); - panelBuilder.item(29, this.getButton(true)); - panelBuilder.item(30, this.getButton(true)); - - // Cancel Buttons - panelBuilder.item(14, this.getButton(false)); - panelBuilder.item(15, this.getButton(false)); - panelBuilder.item(16, this.getButton(false)); - - panelBuilder.item(23, this.getButton(false)); - panelBuilder.item(24, this.getButton(false)); - panelBuilder.item(25, this.getButton(false)); - - panelBuilder.item(32, this.getButton(false)); - panelBuilder.item(33, this.getButton(false)); - panelBuilder.item(34, this.getButton(false)); - - panelBuilder.item(44, - new PanelItemBuilder(). - icon(Material.OAK_DOOR). - name(this.user.getTranslation("challenges.gui.buttons.return")). - clickHandler( (panel, user1, clickType, slot) -> { - this.consumer.accept(false); - return true; - }).build()); - - panelBuilder.build(); - } - - - /** - * This method creates button with requested value. - * @param returnValue requested value - * @return PanelItem button. - */ - private PanelItem getButton(boolean returnValue) - { - return new PanelItemBuilder(). - name(this.user.getTranslation("challenges.gui.buttons.admin." + (returnValue ? "accept" : "cancel"))). - icon(returnValue ? Material.GREEN_STAINED_GLASS_PANE : Material.RED_STAINED_GLASS_PANE). - clickHandler((panel, user1, clickType, i) -> { - this.consumer.accept(returnValue); - return true; - }). - build(); - } - - -// --------------------------------------------------------------------- -// Section: Variables -// --------------------------------------------------------------------- - - /** - * User who wants to run command. - */ - private User user; - - /** - * Stores current Consumer - */ - private Consumer consumer; -} diff --git a/src/main/java/world/bentobox/challenges/panel/util/NumberGUI.java b/src/main/java/world/bentobox/challenges/panel/util/NumberGUI.java deleted file mode 100644 index e58a153..0000000 --- a/src/main/java/world/bentobox/challenges/panel/util/NumberGUI.java +++ /dev/null @@ -1,559 +0,0 @@ -package world.bentobox.challenges.panel.util; - - -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -import org.bukkit.Material; -import org.bukkit.conversations.Conversation; -import org.bukkit.conversations.ConversationContext; -import org.bukkit.conversations.ConversationFactory; -import org.bukkit.conversations.NumericPrompt; -import org.bukkit.conversations.Prompt; -import org.bukkit.inventory.ItemStack; -import org.eclipse.jdt.annotation.NonNull; - -import world.bentobox.bentobox.BentoBox; -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.utils.GuiUtils; - - -/** - * This gui allows to change current number and returns it to previous GUI - */ -public class NumberGUI -{ - public NumberGUI(User user, int value, int lineLength, BiConsumer consumer) - { - this(user, value, Integer.MIN_VALUE, Integer.MAX_VALUE, lineLength, consumer); - } - - - public NumberGUI(User user, int value, int minValue, int lineLength, BiConsumer consumer) - { - this(user, value, minValue, Integer.MAX_VALUE, lineLength, consumer); - } - - - public NumberGUI(User user, int value, int minValue, int maxValue, int lineLength, BiConsumer consumer) - { - this.user = user; - this.value = value; - this.consumer = consumer; - - this.minValue = minValue; - this.maxValue = maxValue; - - this.currentOperation = Button.SET; - - this.lineLength = lineLength; - - this.build(); - } - - - /** - * This method builds panel that allows to change given number value. - */ - private void build() - { - PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(this.user.getTranslation("challenges.gui.title.admin.manage-numbers")); - - GuiUtils.fillBorder(panelBuilder); - - // Others - panelBuilder.item(1, this.getButton(Button.SAVE)); - - panelBuilder.item(19, this.getButton(Button.VALUE)); - panelBuilder.item(44, this.getButton(Button.CANCEL)); - - panelBuilder.item(2, this.getButton(Button.INPUT)); - - // operations - panelBuilder.item(3, this.getButton(Button.SET)); - panelBuilder.item(4, this.getButton(Button.INCREASE)); - panelBuilder.item(5, this.getButton(Button.REDUCE)); - panelBuilder.item(6, this.getButton(Button.MULTIPLY)); - - // Numbers - panelBuilder.item(11, this.createNumberButton(1)); - panelBuilder.item(12, this.createNumberButton(10)); - panelBuilder.item(13, this.createNumberButton(100)); - panelBuilder.item(14, this.createNumberButton(1000)); - panelBuilder.item(15, this.createNumberButton(10000)); - - panelBuilder.item(20, this.createNumberButton(2)); - panelBuilder.item(21, this.createNumberButton(20)); - panelBuilder.item(22, this.createNumberButton(200)); - panelBuilder.item(23, this.createNumberButton(2000)); - panelBuilder.item(24, this.createNumberButton(20000)); - - panelBuilder.item(29, this.createNumberButton(5)); - panelBuilder.item(30, this.createNumberButton(50)); - panelBuilder.item(31, this.createNumberButton(500)); - panelBuilder.item(32, this.createNumberButton(5000)); - panelBuilder.item(33, this.createNumberButton(50000)); - - panelBuilder.build(); - } - - - /** - * This method creates PanelItem with required functionality. - * @param button Functionality requirement. - * @return PanelItem with functionality. - */ - private PanelItem getButton(Button button) - { - ItemStack icon; - String name; - String description; - PanelItem.ClickHandler clickHandler; - boolean glow; - - switch (button) - { - case SAVE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.save"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.save"); - icon = new ItemStack(Material.COMMAND_BLOCK); - clickHandler = (panel, user, clickType, slot) -> { - this.consumer.accept(true, this.value); - return true; - }; - glow = false; - break; - } - case CANCEL: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.cancel"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.cancel"); - icon = new ItemStack(Material.OAK_DOOR); - clickHandler = (panel, user, clickType, slot) -> { - this.consumer.accept(false, this.value); - return true; - }; - glow = false; - break; - } - case INPUT: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.input"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.input"); - icon = new ItemStack(Material.ANVIL); - clickHandler = (panel, user, clickType, slot) -> { - - this.getNumberInput(number -> { - if (number != null) - { - // Null value is passed if user write cancel. - this.value = number.intValue(); - } - - this.build(); - }, - this.user.getTranslation("challenges.gui.questions.admin.number")); - - return true; - }; - glow = false; - break; - } - case VALUE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.value"); - description = this.user.getTranslation("challenges.gui.descriptions.current-value", "[value]", Integer.toString(this.value)); - icon = new ItemStack(Material.PAPER); - clickHandler = (panel, user, clickType, slot) -> true; - glow = false; - break; - } - case SET: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.set"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.set"); - icon = new ItemStack(Material.WHITE_STAINED_GLASS_PANE); - clickHandler = (panel, user, clickType, slot) -> { - this.currentOperation = Button.SET; - this.build(); - return true; - }; - glow = this.currentOperation.equals(Button.SET); - break; - } - case INCREASE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.increase"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.increase"); - icon = new ItemStack(Material.GREEN_STAINED_GLASS_PANE); - clickHandler = (panel, user, clickType, slot) -> { - this.currentOperation = Button.INCREASE; - this.build(); - return true; - }; - glow = this.currentOperation.equals(Button.INCREASE); - break; - } - case REDUCE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.reduce"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.reduce"); - icon = new ItemStack(Material.RED_STAINED_GLASS_PANE); - clickHandler = (panel, user, clickType, slot) -> { - this.currentOperation = Button.REDUCE; - this.build(); - return true; - }; - glow = this.currentOperation.equals(Button.REDUCE); - break; - } - case MULTIPLY: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.multiply"); - description = this.user.getTranslation("challenges.gui.descriptions.admin.multiply"); - icon = new ItemStack(Material.BLUE_STAINED_GLASS_PANE); - clickHandler = (panel, user, clickType, slot) -> { - this.currentOperation = Button.MULTIPLY; - this.build(); - return true; - }; - glow = this.currentOperation.equals(Button.MULTIPLY); - break; - } - default: - return null; - } - - return new PanelItemBuilder(). - icon(icon). - name(name). - description(GuiUtils.stringSplit(description, this.lineLength)). - glow(glow). - clickHandler(clickHandler). - build(); - } - - - /** - * This method creates Number Button based on input number. - * @param number Number which button must be created. - * @return PanelItem that represents number button. - */ - private PanelItem createNumberButton(int number) - { - PanelItemBuilder itemBuilder = new PanelItemBuilder(); - - switch (this.currentOperation) - { - case SET: - { - itemBuilder.name(this.user.getTranslation("challenges.gui.buttons.admin.number","[number]", Integer.toString(number))); - itemBuilder.icon(Material.WHITE_STAINED_GLASS_PANE); - itemBuilder.clickHandler((panel, user1, clickType, i) -> { - this.value = number; - - if (this.value > this.maxValue) - { - this.user.sendMessage("challenges.errors.not-valid-integer", - "[value]", Integer.toString(this.value), - "[min]", Integer.toString(this.minValue), - "[max]", Integer.toString(this.maxValue)); - - this.value = this.maxValue; - } - - if (this.value < this.minValue) - { - this.user.sendMessage("challenges.errors.not-valid-integer", - "[value]", Integer.toString(this.value), - "[min]", Integer.toString(this.minValue), - "[max]", Integer.toString(this.maxValue)); - - this.value = this.minValue; - } - - this.build(); - return true; - }); - - break; - } - case INCREASE: - { - itemBuilder.name(this.user.getTranslation("challenges.gui.buttons.admin.number","[number]", Integer.toString(number))); - itemBuilder.icon(Material.GREEN_STAINED_GLASS_PANE); - itemBuilder.clickHandler((panel, user1, clickType, i) -> { - this.value += number; - - if (this.value > this.maxValue) - { - this.user.sendMessage("challenges.errors.not-valid-integer", - "[value]", Integer.toString(this.value), - "[min]", Integer.toString(this.minValue), - "[max]", Integer.toString(this.maxValue)); - - this.value = this.maxValue; - } - - this.build(); - return true; - }); - - break; - } - case REDUCE: - { - itemBuilder.name(this.user.getTranslation("challenges.gui.buttons.admin.number","[number]", Integer.toString(number))); - itemBuilder.icon(Material.RED_STAINED_GLASS_PANE); - itemBuilder.clickHandler((panel, user1, clickType, i) -> { - this.value -= number; - - if (this.value < this.minValue) - { - this.user.sendMessage("challenges.errors.not-valid-integer", - "[value]", Integer.toString(this.value), - "[min]", Integer.toString(this.minValue), - "[max]", Integer.toString(this.maxValue)); - - this.value = this.minValue; - } - - this.build(); - return true; - }); - - break; - } - case MULTIPLY: - { - itemBuilder.name(this.user.getTranslation("challenges.gui.buttons.admin.number","[number]", Integer.toString(number))); - itemBuilder.icon(Material.BLUE_STAINED_GLASS_PANE); - itemBuilder.clickHandler((panel, user1, clickType, i) -> { - this.value *= number; - - if (this.value > this.maxValue) - { - this.user.sendMessage("challenges.errors.not-valid-integer", - "[value]", Integer.toString(this.value), - "[min]", Integer.toString(this.minValue), - "[max]", Integer.toString(this.maxValue)); - - this.value = this.maxValue; - } - - this.build(); - return true; - }); - - break; - } - default: - break; - } - - return itemBuilder.build(); - } - - - // --------------------------------------------------------------------- - // Section: Conversation - // --------------------------------------------------------------------- - - - /** - * This method will close opened gui and writes inputText in chat. After players answers on - * inputText in chat, message will trigger consumer and gui will reopen. - * @param consumer Consumer that accepts player output text. - * @param question Message that will be displayed in chat when player triggers conversion. - */ - private void getNumberInput(Consumer consumer, @NonNull String question) - { - final User user = this.user; - - Conversation conversation = - new ConversationFactory(BentoBox.getInstance()).withFirstPrompt( - new NumericPrompt() - { - /** - * Override this method to perform some action with - * the user's integer response. - * - * @param context Context information about the - * conversation. - * @param input The user's response as a {@link - * Number}. - * @return The next {@link Prompt} in the prompt - * graph. - */ - @Override - protected Prompt acceptValidatedInput(ConversationContext context, Number input) - { - // Add answer to consumer. - consumer.accept(input); - // Reopen GUI - NumberGUI.this.build(); - // End conversation - return Prompt.END_OF_CONVERSATION; - } - - - /** - * Override this method to do further validation on - * the numeric player input after the input has been - * determined to actually be a number. - * - * @param context Context information about the - * conversation. - * @param input The number the player provided. - * @return The validity of the player's input. - */ - @Override - protected boolean isNumberValid(ConversationContext context, Number input) - { - return input.intValue() >= NumberGUI.this.minValue && - input.intValue() <= NumberGUI.this.maxValue; - } - - - /** - * Optionally override this method to display an - * additional message if the user enters an invalid - * number. - * - * @param context Context information about the - * conversation. - * @param invalidInput The invalid input provided by - * the user. - * @return A message explaining how to correct the - * input. - */ - @Override - protected String getInputNotNumericText(ConversationContext context, - String invalidInput) - { - return NumberGUI.this.user - .getTranslation("challenges.errors.not-a-integer", "[value]", invalidInput); - } - - - /** - * Optionally override this method to display an - * additional message if the user enters an invalid - * numeric input. - * - * @param context Context information about the - * conversation. - * @param invalidInput The invalid input provided by - * the user. - * @return A message explaining how to correct the - * input. - */ - @Override - protected String getFailedValidationText(ConversationContext context, - Number invalidInput) - { - return NumberGUI.this.user.getTranslation("challenges.errors.not-valid-integer", - "[value]", invalidInput.toString(), - "[min]", Integer.toString(NumberGUI.this.minValue), - "[max]", Integer.toString(NumberGUI.this.maxValue)); - } - - - /** - * @see Prompt#getPromptText(ConversationContext) - */ - @Override - public String getPromptText(ConversationContext conversationContext) - { - // Close input GUI. - user.closeInventory(); - - // There are no editable message. Just return question. - return question; - } - }). - withLocalEcho(false). - // On cancel conversation will be closed. - withEscapeSequence("cancel"). - // Use null value in consumer to detect if user has abandoned conversation. - addConversationAbandonedListener(abandonedEvent -> - { - if (!abandonedEvent.gracefulExit()) - { - consumer.accept(null); - } - }). - withPrefix(context -> - NumberGUI.this.user.getTranslation("challenges.gui.questions.prefix")). - buildConversation(user.getPlayer()); - - conversation.begin(); - } - - - // --------------------------------------------------------------------- - // Section: Enums - // --------------------------------------------------------------------- - - - /** - * This enum contains all button types. - */ - private enum Button - { - SAVE, - CANCEL, - INPUT, - - VALUE, - - SET, - INCREASE, - REDUCE, - MULTIPLY - } - - - // --------------------------------------------------------------------- - // Section: Variables - // --------------------------------------------------------------------- - - /** - * This variable stores current GUI consumer. - */ - private BiConsumer consumer; - - /** - * User who runs GUI. - */ - private User user; - - /** - * Current value. - */ - private int value; - - /** - * Minimal value that is allowed to set. - */ - private int minValue; - - /** - * Maximal value that is allowed to set. - */ - private int maxValue; - - /** - * This variable holds which operation now is processed. - */ - private Button currentOperation; - - /** - * This variable stores how large line can be, before warp it. - */ - private int lineLength; -} diff --git a/src/main/java/world/bentobox/challenges/panel/util/StringListGUI.java b/src/main/java/world/bentobox/challenges/panel/util/StringListGUI.java deleted file mode 100644 index 07f30a3..0000000 --- a/src/main/java/world/bentobox/challenges/panel/util/StringListGUI.java +++ /dev/null @@ -1,366 +0,0 @@ -package world.bentobox.challenges.panel.util; - - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -import org.bukkit.Material; -import org.bukkit.conversations.Conversation; -import org.bukkit.conversations.ConversationContext; -import org.bukkit.conversations.ConversationFactory; -import org.bukkit.conversations.Prompt; -import org.bukkit.conversations.StringPrompt; -import org.bukkit.inventory.ItemStack; -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; - -import net.md_5.bungee.api.chat.ClickEvent; -import net.md_5.bungee.api.chat.TextComponent; -import world.bentobox.bentobox.BentoBox; -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.utils.GuiUtils; - - -/** - * This GUI allows to edit List of strings. AnvilGUI has limited text space, so splitting - * text in multiple rows allows to edit each row separately. - */ -public class StringListGUI -{ - public StringListGUI(User user, String value, int lineLength, BiConsumer> consumer) - { - this(user, Collections.singleton(value), lineLength, consumer); - } - - - public StringListGUI(User user, Collection value, int lineLength, BiConsumer> consumer) - { - this(user, new ArrayList<>(value), lineLength, consumer); - } - - - public StringListGUI(User user, List value, int lineLength, BiConsumer> consumer) - { - this.consumer = consumer; - this.user = user; - this.value = value; - this.lineLength = lineLength; - - if (this.value.size() > 21) - { - // TODO: throw error that so large list cannot be edited. - this.consumer.accept(false, this.value); - } - else - { - this.build(); - } - } - - - /** - * This method builds panel that allows to change given string value. - */ - private void build() - { - PanelBuilder panelBuilder = new PanelBuilder().user(this.user). - name(this.user.getTranslation("challenges.gui.title.admin.edit-text-fields")); - - GuiUtils.fillBorder(panelBuilder, Material.BLACK_STAINED_GLASS_PANE); - - panelBuilder.item(1, this.getButton(Button.SAVE)); - panelBuilder.item(2, this.getButton(Button.VALUE)); - - panelBuilder.item(4, this.getButton(Button.ADD)); - panelBuilder.item(5, this.getButton(Button.REMOVE)); - panelBuilder.item(6, this.getButton(Button.CLEAR)); - - panelBuilder.item(44, this.getButton(Button.CANCEL)); - - int slot = 10; - - for (int stringIndex = 0; stringIndex < this.value.size() && slot < 36; stringIndex++) - { - if (!panelBuilder.slotOccupied(slot)) - { - panelBuilder.item(slot, - this.createStringElement(this.value.get(stringIndex), stringIndex)); - } - - slot++; - } - - panelBuilder.build(); - } - - - /** - * This method create button that does some functionality in current gui. - * @param button Button functionality. - * @return PanelItem. - */ - private PanelItem getButton(Button button) - { - ItemStack icon; - String name; - List description; - PanelItem.ClickHandler clickHandler; - - switch (button) - { - case SAVE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.save"); - description = Collections.singletonList(this.user.getTranslation("challenges.gui.descriptions.admin.save")); - icon = new ItemStack(Material.GREEN_STAINED_GLASS_PANE); - clickHandler = (panel, user, clickType, slot) -> { - this.consumer.accept(true, this.value); - - return true; - }; - break; - } - case CANCEL: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.cancel"); - description = Collections.singletonList(this.user.getTranslation("challenges.gui.descriptions.admin.cancel")); - icon = new ItemStack(Material.OAK_DOOR); - clickHandler = (panel, user, clickType, slot) -> { - this.consumer.accept(false, this.value); - - return true; - }; - break; - } - case VALUE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.value"); - description = new ArrayList<>(); - description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", "[value]", "")); - description.addAll(this.value); - icon = new ItemStack(Material.PAPER); - clickHandler = (panel, user, clickType, slot) -> true; - break; - } - case ADD: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.add"); - description = Collections.emptyList(); - icon = new ItemStack(Material.WHITE_STAINED_GLASS_PANE); - clickHandler = (panel, user, clickType, slot) -> { - - this.getStringInput(value -> { - if (value != null) - { - this.value.add(value); - } - - // Reopen GUI. - this.build(); - }, - this.user.getTranslation("challenges.gui.descriptions.admin.add-text-line")); - - return true; - }; - break; - } - case CLEAR: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.clear"); - description = Collections.emptyList(); - icon = new ItemStack(Material.RED_STAINED_GLASS_PANE); - clickHandler = (panel, user, clickType, slot) -> { - this.value.clear(); - this.build(); - return true; - }; - break; - } - case REMOVE: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.remove-empty"); - description = Collections.emptyList(); - icon = new ItemStack(Material.BLUE_STAINED_GLASS_PANE); - clickHandler = (panel, user, clickType, slot) -> { - this.value.removeIf(String::isEmpty); - - this.build(); - return true; - }; - break; - } - default: - return null; - } - - return new PanelItemBuilder(). - icon(icon). - name(name). - description(GuiUtils.stringSplit(description, this.lineLength)). - glow(false). - clickHandler(clickHandler). - build(); - } - - - /** - * This method creates paper icon that represents single line from list. - * @param element Paper Icon name - * @return PanelItem. - */ - private PanelItem createStringElement(String element, int stringIndex) - { - return new PanelItemBuilder(). - name(element). - icon(Material.PAPER). - clickHandler((panel, user1, clickType, i) -> { - - this.getStringInput( - value -> { - if (value != null) - { - this.value.set(stringIndex, value); - } - - // Reopen GUI - this.build(); - }, - this.user.getTranslation("challenges.gui.descriptions.admin.edit-text-line"), - element); - - return true; - }).build(); - } - - - /** - * This method will close opened gui and writes inputText in chat. After players answers on inputText in - * chat, message will trigger consumer and gui will reopen. - * @param consumer Consumer that accepts player output text. - * @param question Message that will be displayed in chat when player triggers conversion. - */ - private void getStringInput(Consumer consumer, @NonNull String question) - { - this.getStringInput(consumer, question, null); - } - - - /** - * This method will close opened gui and writes inputText in chat. After players answers on inputText in - * chat, message will trigger consumer and gui will reopen. - * @param consumer Consumer that accepts player output text. - * @param question Message that will be displayed in chat when player triggers conversion. - * @param message Message that will be set in player text field when clicked on question. - */ - private void getStringInput(Consumer consumer, @NonNull String question, @Nullable String message) - { - final User user = this.user; - - Conversation conversation = - new ConversationFactory(BentoBox.getInstance()).withFirstPrompt( - new StringPrompt() - { - /** - * @see Prompt#getPromptText(ConversationContext) - */ - @Override - public String getPromptText(ConversationContext conversationContext) - { - // Close input GUI. - user.closeInventory(); - - if (message != null) - { - // Create Edit Text message. - TextComponent component = new TextComponent(user.getTranslation("challenges.gui.descriptions.admin.click-to-edit")); - component.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, message)); - // Send question and message to player. - user.getPlayer().spigot().sendMessage(component); - } - - // There are no editable message. Just return question. - return question; - } - - - /** - * @see Prompt#acceptInput(ConversationContext, String) - */ - @Override - public Prompt acceptInput(ConversationContext conversationContext, String answer) - { - // Add answer to consumer. - consumer.accept(answer); - // End conversation - return Prompt.END_OF_CONVERSATION; - } - }). - // On cancel conversation will be closed. - withEscapeSequence("cancel"). - // Use null value in consumer to detect if user has abandoned conversation. - addConversationAbandonedListener(abandonedEvent -> - { - if (!abandonedEvent.gracefulExit()) - { - consumer.accept(null); - } - }). - withLocalEcho(false). - withPrefix(context -> user.getTranslation("challenges.gui.questions.prefix")). - buildConversation(user.getPlayer()); - - conversation.begin(); - } - - -// --------------------------------------------------------------------- -// Section: Enums -// --------------------------------------------------------------------- - - - /** - * This enum holds all button values in current gui. - */ - private enum Button - { - VALUE, - ADD, - REMOVE, - CANCEL, - CLEAR, - SAVE - } - - -// --------------------------------------------------------------------- -// Section: Variables -// --------------------------------------------------------------------- - - - /** - * This variable stores consumer. - */ - private BiConsumer> consumer; - - /** - * User who runs GUI. - */ - private User user; - - /** - * Current value. - */ - private List value; - - /** - * This variable stores how large line can be, before warp it. - */ - private int lineLength; -} diff --git a/src/main/java/world/bentobox/challenges/utils/Constants.java b/src/main/java/world/bentobox/challenges/utils/Constants.java new file mode 100644 index 0000000..195fef0 --- /dev/null +++ b/src/main/java/world/bentobox/challenges/utils/Constants.java @@ -0,0 +1,291 @@ +// +// Created by BONNe +// Copyright - 2020 +// + + +package world.bentobox.challenges.utils; + + +/** + * This class contains String constants used in messages and guis. + */ +public class Constants +{ + /** + * Reference string to ADDON_NAME in translations. + */ + public static final String ADDON_NAME = "challenges."; + +// --------------------------------------------------------------------- +// Section: Commands +// --------------------------------------------------------------------- + + + /** + * Reference string to Commands in translations. + */ + public static final String COMMANDS = ADDON_NAME + "commands."; + + /** + * Reference string to Admin in translations. + */ + public static final String ADMIN_COMMANDS = COMMANDS + "admin."; + + /** + * Reference string to Player in translations. + */ + public static final String PLAYER_COMMANDS = COMMANDS + "player."; + +// --------------------------------------------------------------------- +// Section: GUI +// --------------------------------------------------------------------- + + /** + * Reference string to GUI in translations. + */ + public static final String GUI = ADDON_NAME + "gui."; + + /** + * Reference string to TITLE in translations. + */ + public static final String TITLE = GUI + "titles."; + + /** + * Reference string to BUTTON in translations. + */ + public static final String BUTTON = GUI + "buttons."; + + /** + * Reference string to Biome group Buttons in translations. + */ + public static final String BIOME_GROUP_BUTTON = BUTTON + "biome-groups."; + + /** + * Reference string to generator type Buttons in translations. + */ + public static final String GENERATOR_TYPE_BUTTON = BUTTON + "generator-types."; + + /** + * Reference string to TIPS in translations. + */ + public static final String TIPS = GUI + "tips."; + + /** + * Reference string to DESCRIPTION in translations. + */ + public static final String DESCRIPTIONS = GUI + "descriptions."; + + /** + * Reference string to Messages in translations. + */ + public static final String MESSAGES = ADDON_NAME + "messages."; + + /** + * Reference string to Errors in translations. + */ + public static final String ERRORS = ADDON_NAME + "errors."; + + /** + * Reference string to Questions in translations. + */ + public static final String CONVERSATIONS = ADDON_NAME + "conversations."; + +// --------------------------------------------------------------------- +// Section: Other +// --------------------------------------------------------------------- + + /** + * Reference string to Biomes in translations. + */ + public static final String BIOMES = ADDON_NAME + "biomes."; + + /** + * Reference string to materials in translations. + */ + public static final String MATERIALS = ADDON_NAME + "materials."; + + /** + * Reference string to entities in translations. + */ + public static final String ENTITIES = ADDON_NAME + "entities."; + + /** + * Reference string to Types in translations. + */ + public static final String TYPES = ADDON_NAME + "types."; + +// --------------------------------------------------------------------- +// Section: Parameters +// --------------------------------------------------------------------- + + /** + * Reference string to generator parameter in translations. + */ + public static final String GENERATOR = "[generator]"; + + /** + * Reference string to bundle parameter in translations. + */ + public static final String BUNDLE = "[bundle]"; + + /** + * Reference string to gamemode parameter in translations. + */ + public static final String GAMEMODE = "[gamemode]"; + + /** + * Reference string to world parameter in translations. + */ + public static final String WORLD = "[world]"; + + /** + * Reference string to value parameter in translations. + */ + public static final String VALUE = "[value]"; + + /** + * Reference string to block parameter in translations. + */ + public static final String BLOCK = "[material]"; + + /** + * Reference string to file parameter in translations. + */ + public static final String FILE = "[file]"; + + /** + * Reference string to id parameter in translations. + */ + public static final String ID = "[id]"; + + /** + * Reference string to min parameter in translations. + */ + public static final String MIN = "[min]"; + + /** + * Reference string to max parameter in translations. + */ + public static final String MAX = "[max]"; + + /** + * Reference to an author parameter in translation. + */ + public static final String AUTHOR = "[author]"; + + /** + * Reference to an lang parameter in translation. + */ + public static final String LANG = "[lang]"; + + /** + * Reference to an version parameter in translation. + */ + public static final String VERSION = "[version]"; + + /** + * Reference to an generators parameter in translation. + */ + public static final String GENERATORS = "[generators]"; + + /** + * Reference to an bundles parameter in translation. + */ + public static final String BUNDLES = "[bundles]"; + + /** + * Reference to number formant in 0.X + */ + public static final String TENS = "[#.#]"; + + /** + * Reference to number formant in 0.0X + */ + public static final String HUNDREDS = "[#.##]"; + + /** + * Reference to number formant in 0.00X + */ + public static final String THOUSANDS = "[#.###]"; + + /** + * Reference to number formant in 0.000X + */ + public static final String TEN_THOUSANDS = "[#.####]"; + + /** + * Reference to number formant in 0.0000X + */ + public static final String HUNDRED_THOUSANDS = "[#.#####]"; + + /** + * Reference to island in translations. + */ + public static final String ISLAND = "[island]"; + + /** + * Reference string to number parameter in translations. + */ + public static final String NUMBER = "[number]"; + + /** + * Reference string to type parameter in translations. + */ + public static final String TYPE = "[type]"; + + /** + * Reference string to permission parameter in translations. + */ + public static final String PERMISSION = "[permission]"; + + /** + * Reference string to biome parameter in translations. + */ + public static final String BIOME = "[biome]"; + + /** + * Reference string to player parameter in translations. + */ + public static final String PLAYER = "[player]"; + + /** + * Reference string to owner parameter in translations. + */ + public static final String OWNER = "[owner]"; + + /** + * Reference string to members parameter in translations. + */ + public static final String MEMBERS = "[members]"; + + /** + * Reference string to name parameter in translations. + */ + public static final String NAME = "[name]"; + + /** + * Reference string to description parameter in translations. + */ + public static final String DESCRIPTION = "[description]"; + + public static final String CHALLENGE = "[challenge]"; + + public static final String REQUIREMENTS = "[requirements]"; + + public static final String REWARDS = "[rewards]"; + + public static final String STATUS = "[status]"; + + public static final String LEVEL = "[level]"; + + public static final String ENVIRONMENT = "[environment]"; + + public static final String TYPE_REQUIREMENT = "[type-requirement]"; + + public static final String PERMISSIONS = "[permissions]"; + + public static final String MATERIAL = "[material]"; + + public static final String ENTITY = "[entity]"; +} diff --git a/src/main/java/world/bentobox/challenges/utils/GuiUtils.java b/src/main/java/world/bentobox/challenges/utils/GuiUtils.java index 55edbb9..2e6da65 100644 --- a/src/main/java/world/bentobox/challenges/utils/GuiUtils.java +++ b/src/main/java/world/bentobox/challenges/utils/GuiUtils.java @@ -3,8 +3,6 @@ package world.bentobox.challenges.utils; import java.util.*; -import org.apache.commons.lang.WordUtils; -import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; @@ -366,74 +364,9 @@ public class GuiUtils private static BorderBlock getPanelBorder(Material material) { ItemStack itemStack = new ItemStack(material); - itemStack.getItemMeta().setDisplayName(" "); + itemStack.getItemMeta().setDisplayName("&r&8"); return new BorderBlock(itemStack); } } - - - /** - * Simple splitter - * - * @param string - string to be split - * @param warpLength - whn warp should be affected. - * @return list of split strings - */ - public static List stringSplit(String string, int warpLength) - { - // Remove all ending lines from string. - string = string.replaceAll("([\\r\\n])", "\\|"); - string = ChatColor.translateAlternateColorCodes('&', string); - // Check length of lines - List result = new ArrayList<>(); - - Arrays.stream(string.split("\\|")). - map(line -> Arrays.asList(WordUtils.wrap(line, warpLength).split(System.getProperty("line.separator")))). - forEach(result::addAll); - - // Fix colors, as splitting my lost that information. - - for (int i = 0, resultSize = result.size(); i < resultSize; i++) - { - if (i > 0) - { - String lastColor = ChatColor.getLastColors(result.get(i - 1)); - result.set(i, lastColor + result.get(i)); - } - } - - return result; - } - - - /** - * Simple splitter for all strings in list. - * @param stringList - list of string to be split - * @param warpLength - whn warp should be affected. - * @return list of split strings - */ - public static List stringSplit(List stringList, int warpLength) - { - if (stringList.isEmpty()) - { - return stringList; - } - - List newList = new ArrayList<>(stringList.size()); - stringList.stream().map(string -> GuiUtils.stringSplit(string, warpLength)).forEach(newList::addAll); - return newList; - } - - - /** - * Sanitizes the provided input. - * It replaces spaces and hyphens with underscores and lower cases the input. - * @param input input to sanitize - * @return sanitized input - */ - public static String sanitizeInput(String input) - { - return input.toLowerCase(Locale.ENGLISH).replace(" ", "_").replace("-", "_"); - } } \ No newline at end of file diff --git a/src/main/java/world/bentobox/challenges/utils/Utils.java b/src/main/java/world/bentobox/challenges/utils/Utils.java index b67593a..68ba3f5 100644 --- a/src/main/java/world/bentobox/challenges/utils/Utils.java +++ b/src/main/java/world/bentobox/challenges/utils/Utils.java @@ -3,12 +3,19 @@ package world.bentobox.challenges.utils; import java.util.ArrayList; import java.util.List; +import java.util.Locale; +import org.bukkit.ChatColor; import org.bukkit.Material; +import org.bukkit.Statistic; import org.bukkit.World; +import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; +import org.eclipse.jdt.annotation.Nullable; import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.util.Util; /** @@ -152,4 +159,103 @@ public class Utils return currentValue; } + + + /** + * Sanitizes the provided input. It replaces spaces and hyphens with underscores and lower cases the input. + * This code also removes all color codes from the input. + * @param input input to sanitize + * @return sanitized input + */ + public static String sanitizeInput(String input) + { + return ChatColor.stripColor( + Util.translateColorCodes(input.toLowerCase(Locale.ENGLISH). + replace(" ", "_"). + replace("-", "_"))); + } + + + /** + * Send given message to user and add prefix to the start of the message. + * + * @param user User who need to receive message. + * @param message String of message that must be send. + */ + public static void sendMessage(User user, String message) + { + user.sendMessage(user.getTranslation(Constants.CONVERSATIONS + "prefix") + message); + } + + + + public static String prettifyObject(World.Environment object, User user) + { + return Util.prettifyText(object.name()); + } + + public static String prettifyObject(@Nullable Material object, User user) + { + if (object == null) + { + return ""; + } + + return Util.prettifyText(object.name()); + } + + + public static String prettifyObject(@Nullable EntityType object, User user) + { + if (object == null) + { + return ""; + } + + return Util.prettifyText(object.name()); + } + + + public static String prettifyObject(@Nullable ItemStack object, User user) + { + if (object == null) + { + return ""; + } + + return Util.prettifyText(object.getType().name()); + } + + + public static String prettifyObject(@Nullable Statistic object, User user) + { + if (object == null) + { + return ""; + } + + return Util.prettifyText(object.name()); + } + + + public static String prettifyDescription(@Nullable Statistic object, User user) + { + if (object == null) + { + return ""; + } + + return Util.prettifyText(object.name()); + } + + + public static String prettifyDescription(World.Environment object, User user) + { + if (object == null) + { + return ""; + } + + return Util.prettifyText(object.name()); + } }