diff --git a/src/main/java/world/bentobox/challenges/panel/util/ChallengeSelector.java b/src/main/java/world/bentobox/challenges/panel/util/ChallengeSelector.java new file mode 100644 index 0000000..ab70595 --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/util/ChallengeSelector.java @@ -0,0 +1,221 @@ +package world.bentobox.challenges.panel.util; + + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.BiConsumer; + +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.bentobox.api.user.User; +import world.bentobox.bentobox.util.Util; +import world.bentobox.challenges.database.object.Challenge; +import world.bentobox.challenges.utils.Constants; +import world.bentobox.challenges.utils.GuiUtils; + + +/** + * This class creates new GUI that allows to select single challenge, which is returned via consumer. + */ +public class ChallengeSelector extends PagedSelector +{ + private ChallengeSelector(User user, Material border, Map> challengesDescriptionMap, BiConsumer> consumer) + { + super(user); + this.consumer = consumer; + this.challengesDescriptionMap = challengesDescriptionMap; + this.border = border; + + this.elements = challengesDescriptionMap.keySet().stream().toList(); + this.selectedElements = new HashSet<>(this.elements.size()); + } + + + /** + * This method opens GUI that allows to select challenge type. + * + * @param user User who opens GUI. + * @param consumer Consumer that allows to get clicked type. + */ + public static void open(User user, Material border, Map> challengesDescriptionMap, BiConsumer> consumer) + { + new ChallengeSelector(user, border, challengesDescriptionMap, consumer).build(); + } + + + /** + * This method builds all necessary elements in GUI panel. + */ + @Override + protected void build() + { + PanelBuilder panelBuilder = new PanelBuilder().user(this.user); + panelBuilder.name(this.user.getTranslation(Constants.TITLE + "challenge-selector")); + + GuiUtils.fillBorder(panelBuilder, this.border); + + this.populateElements(panelBuilder, this.elements); + + panelBuilder.item(3, this.createButton(Button.ACCEPT_SELECTED)); + panelBuilder.item(5, this.createButton(Button.CANCEL)); + + 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; + + switch (button) + { + case ACCEPT_SELECTED -> { + if (!this.selectedElements.isEmpty()) + { + description.add(this.user.getTranslation(reference + "title")); + this.selectedElements.forEach(challenge -> { + description.add(this.user.getTranslation(reference + "element", + "[element]", challenge.getFriendlyName())); + }); + } + + icon = new ItemStack(Material.COMMAND_BLOCK); + clickHandler = (panel, user1, clickType, slot) -> + { + this.consumer.accept(true, this.selectedElements); + return true; + }; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-save")); + } + case CANCEL -> { + + icon = new ItemStack(Material.IRON_DOOR); + + clickHandler = (panel, user1, clickType, slot) -> + { + this.consumer.accept(false, null); + return true; + }; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-cancel")); + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + } + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + clickHandler(clickHandler). + build(); + } + + + /** + * This method creates button for given challenge. + * @param challenge challenge which button must be created. + * @return new Button for challenge. + */ + @Override + protected PanelItem createElementButton(Challenge challenge) + { + final String reference = Constants.BUTTON + "entity."; + + List description = new ArrayList<>(this.challengesDescriptionMap.get(challenge)); + description.add(""); + + if (this.selectedElements.contains(challenge)) + { + description.add(this.user.getTranslation(reference + "selected")); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-deselect")); + } + else + { + description.add(this.user.getTranslation(Constants.TIPS + "click-to-select")); + } + + return new PanelItemBuilder(). + name(Util.translateColorCodes(challenge.getFriendlyName())). + icon(challenge.getIcon()). + description(description). + clickHandler((panel, user1, clickType, slot) -> { + // On right click change which entities are selected for deletion. + if (!this.selectedElements.add(challenge)) + { + // Remove challenge if it is already selected + this.selectedElements.remove(challenge); + } + + this.build(); + return true; + }). + glow(this.selectedElements.contains(challenge)). + build(); + } + + + /** + * Functional buttons in current GUI. + */ + private enum Button + { + ACCEPT_SELECTED, + CANCEL + } + + +// --------------------------------------------------------------------- +// Section: Variables +// --------------------------------------------------------------------- + + + /** + * This variable stores consumer. + */ + private final BiConsumer> consumer; + + /** + * Current value. + */ + private final List elements; + + /** + * Selected challenges that will be returned to consumer. + */ + private final Set selectedElements; + + /** + * Map that contains all challenge descriptions + */ + private final Map> challengesDescriptionMap; + + /** + * Border Material. + */ + private final Material border; +} diff --git a/src/main/java/world/bentobox/challenges/panel/util/ChallengeTypeGUI.java b/src/main/java/world/bentobox/challenges/panel/util/ChallengeTypeGUI.java deleted file mode 100644 index 60a3a2b..0000000 --- a/src/main/java/world/bentobox/challenges/panel/util/ChallengeTypeGUI.java +++ /dev/null @@ -1,151 +0,0 @@ -// -// Created by BONNe -// Copyright - 2019 -// - - -package world.bentobox.challenges.panel.util; - - -import java.util.ArrayList; -import java.util.List; -import java.util.function.BiConsumer; - -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.database.object.Challenge; -import world.bentobox.challenges.database.object.requirements.*; -import world.bentobox.challenges.utils.GuiUtils; - - -/** - * This class creates GUI that allows to select challenge type. - */ -public class ChallengeTypeGUI -{ - /** - * Default constructor that builds gui. - * @param user User who opens GUI. - * @param lineLength Lore line length - * @param consumer Consumer that allows to get clicked type. - */ - private ChallengeTypeGUI(User user, int lineLength, BiConsumer consumer) - { - this.user = user; - this.lineLength = lineLength; - this.consumer = consumer; - } - - - /** - * This method opens GUI that allows to select challenge type. - * @param user User who opens GUI. - * @param lineLength Lore line length - * @param consumer Consumer that allows to get clicked type. - */ - public static void open(User user, int lineLength, BiConsumer consumer) - { - new ChallengeTypeGUI(user, lineLength, consumer).build(); - } - - - /** - * This method builds GUI that allows to select challenge type. - */ - private void build() - { - PanelBuilder panelBuilder = new PanelBuilder(). - user(this.user). - type(Panel.Type.HOPPER). - name(this.user.getTranslation("challenges.gui.title.admin.type-select")); - - panelBuilder.item(0, this.getButton(Challenge.ChallengeType.INVENTORY)); - panelBuilder.item(1, this.getButton(Challenge.ChallengeType.ISLAND)); - panelBuilder.item(2, this.getButton(Challenge.ChallengeType.OTHER)); - panelBuilder.item(3, this.getButton(Challenge.ChallengeType.STATISTIC)); - - panelBuilder.build(); - } - - - /** - * Creates ChallengeType button. - * @param type Challenge type which button must be created. - * @return PanelItem button. - */ - private PanelItem getButton(Challenge.ChallengeType type) - { - ItemStack icon; - String name = this.user.getTranslation("challenges.gui.buttons.admin.type." + type.name().toLowerCase()); - List description = new ArrayList<>(); - description.add(this.user.getTranslation("challenges.gui.descriptions.type." + type.name().toLowerCase())); - PanelItem.ClickHandler clickHandler; - - switch (type) - { - case INVENTORY: - icon = new ItemStack(Material.CHEST); - clickHandler = ((panel, user1, clickType, slot) -> { - this.consumer.accept(type, new InventoryRequirements()); - return true; - }); - break; - case ISLAND: - icon = new ItemStack(Material.GRASS_BLOCK); - clickHandler = ((panel, user1, clickType, slot) -> { - this.consumer.accept(type, new IslandRequirements()); - return true; - }); - break; - case OTHER: - icon = new ItemStack(Material.EXPERIENCE_BOTTLE); - clickHandler = ((panel, user1, clickType, slot) -> { - this.consumer.accept(type, new OtherRequirements()); - return true; - }); - break; - case STATISTIC: - icon = new ItemStack(Material.BOOK); - clickHandler = ((panel, user1, clickType, slot) -> { - this.consumer.accept(type, new StatisticRequirements()); - return true; - }); - break; - default: - return null; - } - - return new PanelItemBuilder(). - icon(icon). - name(name). - description(GuiUtils.stringSplit(description, this.lineLength)). - clickHandler(clickHandler). - build(); - } - - -// --------------------------------------------------------------------- -// Section: Variables -// --------------------------------------------------------------------- - - /** - * User who runs GUI. - */ - private final User user; - - /** - * Lore line max length. - */ - private final int lineLength; - - /** - * Consumer that returns Challenge Type. - */ - private final BiConsumer consumer; -} diff --git a/src/main/java/world/bentobox/challenges/panel/util/ChallengeTypeSelector.java b/src/main/java/world/bentobox/challenges/panel/util/ChallengeTypeSelector.java new file mode 100644 index 0000000..024f441 --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/util/ChallengeTypeSelector.java @@ -0,0 +1,133 @@ +// +// Created by BONNe +// Copyright - 2019 +// + + +package world.bentobox.challenges.panel.util; + + +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiConsumer; + +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.database.object.Challenge; +import world.bentobox.challenges.database.object.requirements.*; +import world.bentobox.challenges.utils.Constants; + + +/** + * This class creates GUI that allows to select challenge type. + */ +public record ChallengeTypeSelector(User user, BiConsumer consumer) +{ + /** + * This method opens GUI that allows to select challenge type. + * + * @param user User who opens GUI. + * @param consumer Consumer that allows to get clicked type. + */ + public static void open(User user, BiConsumer consumer) + { + new ChallengeTypeSelector(user, consumer).build(); + } + + + /** + * This method builds GUI that allows to select challenge type. + */ + private void build() + { + PanelBuilder panelBuilder = new PanelBuilder(). + user(this.user). + type(Panel.Type.HOPPER). + name(this.user.getTranslation(Constants.TITLE + "type-selector")); + + panelBuilder.item(0, this.getButton(Challenge.ChallengeType.INVENTORY_TYPE)); + panelBuilder.item(1, this.getButton(Challenge.ChallengeType.ISLAND_TYPE)); + panelBuilder.item(2, this.getButton(Challenge.ChallengeType.OTHER_TYPE)); + panelBuilder.item(3, this.getButton(Challenge.ChallengeType.STATISTIC_TYPE)); + + panelBuilder.build(); + } + + + /** + * Creates ChallengeType button. + * + * @param type Challenge type which button must be created. + * @return PanelItem button. + */ + private PanelItem getButton(Challenge.ChallengeType type) + { + final String reference = Constants.BUTTON + type.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; + PanelItem.ClickHandler clickHandler; + + switch (type) + { + case INVENTORY_TYPE -> { + icon = new ItemStack(Material.CHEST); + clickHandler = ( + (panel, user1, clickType, slot) -> + { + this.consumer.accept(type, new InventoryRequirements()); + return true; + }); + } + case ISLAND_TYPE -> { + icon = new ItemStack(Material.GRASS_BLOCK); + clickHandler = ( + (panel, user1, clickType, slot) -> + { + this.consumer.accept(type, new IslandRequirements()); + return true; + }); + } + case OTHER_TYPE -> { + icon = new ItemStack(Material.EXPERIENCE_BOTTLE); + clickHandler = ( + (panel, user1, clickType, slot) -> + { + this.consumer.accept(type, new OtherRequirements()); + return true; + }); + } + case STATISTIC_TYPE -> { + icon = new ItemStack(Material.BOOK); + clickHandler = ( + (panel, user1, clickType, slot) -> + { + this.consumer.accept(type, new StatisticRequirements()); + return true; + }); + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + } + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + clickHandler(clickHandler). + build(); + } +} diff --git a/src/main/java/world/bentobox/challenges/panel/util/EnvironmentSelector.java b/src/main/java/world/bentobox/challenges/panel/util/EnvironmentSelector.java new file mode 100644 index 0000000..562cd7c --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/util/EnvironmentSelector.java @@ -0,0 +1,196 @@ +package world.bentobox.challenges.panel.util; + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.function.BiConsumer; + +import org.bukkit.Material; +import org.bukkit.World; +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.Constants; +import world.bentobox.challenges.utils.Utils; + + +/** + * This class creates panel that allows to select and deselect World Environments. On save it runs + * input consumer with true and selected values. + */ +public record EnvironmentSelector(User user, Set values, BiConsumer> consumer) +{ + /** + * This method opens GUI that allows to select challenge type. + * + * @param user User who opens GUI. + * @param consumer Consumer that allows to get clicked type. + */ + public static void open(User user, Set values, BiConsumer> consumer) + { + new EnvironmentSelector(user, values, consumer).build(); + } + + + /** + * This method builds GUI that allows to select challenge type. + */ + private void build() + { + PanelBuilder panelBuilder = new PanelBuilder(). + user(this.user). + type(Panel.Type.HOPPER). + name(this.user.getTranslation(Constants.TITLE + "environment-selector")); + + panelBuilder.item(0, this.getButton(World.Environment.NORMAL)); + panelBuilder.item(1, this.getButton(World.Environment.NETHER)); + panelBuilder.item(2, this.getButton(World.Environment.THE_END)); + panelBuilder.item(3, this.getButton(Button.ACCEPT_SELECTED)); + panelBuilder.item(4, this.getButton(Button.CANCEL)); + + panelBuilder.build(); + } + + + /** + * This method create button that does some functionality in current gui. + * + * @param environment Environment + * @return PanelItem. + */ + private PanelItem getButton(World.Environment environment) + { + final String reference = Constants.BUTTON + "environment_element."; + + String name = this.user.getTranslation(reference + "name", + "[environment]", Utils.prettifyObject(environment, this.user)); + final List description = new ArrayList<>(3); + description.add(this.user.getTranslationOrNothing(reference + "description", + "[description]", Utils.prettifyDescription(environment, this.user))); + + if (this.values.contains(environment)) + { + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-deselect")); + } + else + { + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-select")); + } + + PanelItem.ClickHandler clickHandler = (panel, user, clickType, slot) -> + { + if (this.values.contains(environment)) + { + this.values.remove(environment); + } + else + { + this.values.add(environment); + } + + this.build(); + return true; + }; + + ItemStack icon; + + switch (environment) + { + case NORMAL -> icon = new ItemStack(Material.DIRT); + case NETHER -> icon = new ItemStack(Material.NETHERRACK); + case THE_END -> icon = new ItemStack(Material.END_STONE); + default -> icon = new ItemStack(Material.PAPER); + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + clickHandler(clickHandler). + glow(this.values.contains(environment)). + build(); + } + + + /** + * This method create button that does some functionality in current gui. + * + * @param button Button functionality. + * @return PanelItem. + */ + private PanelItem getButton(Button button) + { + final 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")); + + ItemStack icon; + PanelItem.ClickHandler clickHandler; + + switch (button) + { + case ACCEPT_SELECTED -> { + if (!this.values.isEmpty()) + { + description.add(this.user.getTranslation(reference + "title")); + this.values.forEach(element -> { + description.add(this.user.getTranslation(reference + "element", + "[element]", Utils.prettifyObject(element, this.user))); + }); + } + + icon = new ItemStack(Material.COMMAND_BLOCK); + clickHandler = (panel, user, clickType, slot) -> + { + this.consumer.accept(true, this.values); + return true; + }; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-save")); + } + case CANCEL -> { + icon = new ItemStack(Material.IRON_DOOR); + clickHandler = (panel, user, clickType, slot) -> + { + this.consumer.accept(false, Collections.emptySet()); + return true; + }; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-cancel")); + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + } + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + clickHandler(clickHandler). + build(); + } + + + /** + * This enum holds all button values in current gui. + */ + private enum Button + { + CANCEL, + ACCEPT_SELECTED + } +} diff --git a/src/main/java/world/bentobox/challenges/panel/util/ItemSwitchGUI.java b/src/main/java/world/bentobox/challenges/panel/util/ItemSelector.java similarity index 66% rename from src/main/java/world/bentobox/challenges/panel/util/ItemSwitchGUI.java rename to src/main/java/world/bentobox/challenges/panel/util/ItemSelector.java index e7caf56..605a2fe 100644 --- a/src/main/java/world/bentobox/challenges/panel/util/ItemSwitchGUI.java +++ b/src/main/java/world/bentobox/challenges/panel/util/ItemSelector.java @@ -16,21 +16,23 @@ 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.utils.GuiUtils; +import world.bentobox.challenges.utils.Constants; /** * This class allows to change Input ItemStacks to different ItemStacks. */ -public class ItemSwitchGUI +public record ItemSelector(User user, List itemStacks, BiConsumer> consumer) { - public ItemSwitchGUI(User user, List itemStacks, int lineLength, BiConsumer> consumer) + /** + * This method opens GUI that allows to select challenge type. + * + * @param user User who opens GUI. + * @param consumer Consumer that allows to get clicked type. + */ + public static void open(User user, List itemStacks, BiConsumer> consumer) { - this.consumer = consumer; - this.user = user; - this.itemStacks = itemStacks; - this.lineLength = lineLength; - this.build(); + new ItemSelector(user, itemStacks, consumer).build(); } @@ -39,7 +41,9 @@ public class ItemSwitchGUI */ private void build() { - PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(this.user.getTranslation("challenges.gui.title.admin.manage-items")); + PanelBuilder panelBuilder = new PanelBuilder(). + user(this.user). + name(this.user.getTranslation(Constants.TITLE + "item-selector")); // Size of inventory that user can set via GUI. panelBuilder.size(45); @@ -66,24 +70,27 @@ public class ItemSwitchGUI /** * This method create button that does some functionality in current gui. + * * @param button Button functionality. * @return PanelItem. */ private PanelItem getButton(Button button) { + final 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")); + 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(); + case SAVE -> { icon = new ItemStack(Material.COMMAND_BLOCK); - clickHandler = (panel, user, clickType, slot) -> { + clickHandler = (panel, user, clickType, slot) -> + { // Magic number 9 - second row. First row is for custom buttons. // Magic number 45 - This GUI is initialed with 45 elements. List returnItems = new ArrayList<>(36); @@ -102,36 +109,37 @@ public class ItemSwitchGUI return true; }; - break; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-save")); } - case CANCEL: - { - name = this.user.getTranslation("challenges.gui.buttons.admin.cancel"); - description = Collections.emptyList(); + case CANCEL -> { icon = new ItemStack(Material.IRON_DOOR); - clickHandler = (panel, user, clickType, slot) -> { + clickHandler = (panel, user, clickType, slot) -> + { this.consumer.accept(false, Collections.emptyList()); return true; }; - break; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-cancel")); } - case EMPTY: - { - name = ""; - description = Collections.emptyList(); + case EMPTY -> { + description.clear(); + name = "&r"; icon = new ItemStack(Material.BARRIER); - clickHandler = (panel, user, clickType, slot) -> true; - break; + clickHandler = null; + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; } - default: - return null; } return new PanelItemBuilder(). icon(icon). name(name). - description(GuiUtils.stringSplit(description, this.lineLength)). - glow(false). + description(description). clickHandler(clickHandler). build(); } @@ -143,11 +151,10 @@ public class ItemSwitchGUI /** - * This CustomPanelItem does no lose Item original MetaData. After PanelItem has been - * created it restores original meta data. It also does not allow to change anything that - * could destroy meta data. + * This CustomPanelItem does no lose Item original MetaData. After PanelItem has been created it + * restores original meta data. It also does not allow to change anything that could destroy meta data. */ - private class CustomPanelItem extends PanelItem + private static class CustomPanelItem extends PanelItem { CustomPanelItem(ItemStack item) { @@ -190,7 +197,7 @@ public class ItemSwitchGUI /** * This CustomPanelListener allows to move items in current panel. */ - private class CustomPanelListener implements PanelListener + private static class CustomPanelListener implements PanelListener { @Override public void setup() @@ -227,30 +234,4 @@ public class ItemSwitchGUI SAVE, EMPTY } - - -// --------------------------------------------------------------------- -// Section: Variables -// --------------------------------------------------------------------- - - - /** - * User who opens current gui. - */ - private User user; - - /** - * List with original items. - */ - private List itemStacks; - - /** - * Consumer that returns item stacks on save action. - */ - private BiConsumer> consumer; - - /** - * 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/MultiBlockSelector.java b/src/main/java/world/bentobox/challenges/panel/util/MultiBlockSelector.java new file mode 100644 index 0000000..37ffe5b --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/util/MultiBlockSelector.java @@ -0,0 +1,263 @@ +package world.bentobox.challenges.panel.util; + + +import java.util.*; +import java.util.function.BiConsumer; +import java.util.stream.Collectors; + +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.bentobox.api.user.User; +import world.bentobox.challenges.utils.Constants; +import world.bentobox.challenges.utils.GuiUtils; +import world.bentobox.challenges.utils.Utils; + + +/** + * This class contains all necessary things that allows to select single block from all ingame blocks. Selected + * block will be returned via BiConsumer. + */ +public class MultiBlockSelector extends PagedSelector +{ + private MultiBlockSelector(User user, Mode mode, Set excluded, BiConsumer> consumer) + { + super(user); + this.consumer = consumer; + + // Current GUI cannot display air blocks. It crashes with null-pointer + excluded.add(Material.AIR); + excluded.add(Material.CAVE_AIR); + excluded.add(Material.VOID_AIR); + + // Piston head and moving piston is not necessary. useless. + excluded.add(Material.PISTON_HEAD); + excluded.add(Material.MOVING_PISTON); + + // Barrier cannot be accessible to user. + excluded.add(Material.BARRIER); + + this.selectedElements = new HashSet<>(); + + this.elements = Arrays.stream(Material.values()). + filter(material -> !excluded.contains(material)). + filter(material -> { + switch (mode) + { + case BLOCKS -> { + return material.isBlock(); + } + case ITEMS -> { + return material.isItem(); + } + default -> { + return true; + } + } + }). + collect(Collectors.toList()); + } + + + /** + * This method opens GUI that allows to select challenge type. + * + * @param user User who opens GUI. + * @param consumer Consumer that allows to get clicked type. + */ + public static void open(User user, Mode mode, Set excluded, BiConsumer> consumer) + { + new MultiBlockSelector(user, mode, excluded, consumer).build(); + } + + + /** + * This method opens GUI that allows to select challenge type. + * + * @param user User who opens GUI. + * @param consumer Consumer that allows to get clicked type. + */ + public static void open(User user, BiConsumer> consumer) + { + new MultiBlockSelector(user, Mode.ANY, new HashSet<>(), consumer).build(); + } + + +// --------------------------------------------------------------------- +// Section: Methods +// --------------------------------------------------------------------- + + + /** + * This method builds all necessary elements in GUI panel. + */ + @Override + protected void build() + { + PanelBuilder panelBuilder = new PanelBuilder().user(this.user); + panelBuilder.name(this.user.getTranslation(Constants.TITLE + "block-selector")); + + GuiUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE); + + this.populateElements(panelBuilder, this.elements); + + panelBuilder.item(3, this.createButton(Button.ACCEPT_SELECTED)); + panelBuilder.item(5, this.createButton(Button.CANCEL)); + + 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; + + switch (button) + { + case ACCEPT_SELECTED -> { + if (!this.selectedElements.isEmpty()) + { + description.add(this.user.getTranslation(reference + "title")); + this.selectedElements.forEach(material -> { + description.add(this.user.getTranslation(reference + "element", + "[element]", Utils.prettifyObject(material, this.user))); + }); + } + + icon = new ItemStack(Material.COMMAND_BLOCK); + clickHandler = (panel, user1, clickType, slot) -> + { + this.consumer.accept(true, this.selectedElements); + return true; + }; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-save")); + } + case CANCEL -> { + + icon = new ItemStack(Material.IRON_DOOR); + + clickHandler = (panel, user1, clickType, slot) -> + { + this.consumer.accept(false, null); + return true; + }; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-cancel")); + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + } + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + clickHandler(clickHandler). + build(); + } + + + /** + * This method creates button for given material. + * @param material material which button must be created. + * @return new Button for material. + */ + @Override + protected PanelItem createElementButton(Material material) + { + final String reference = Constants.BUTTON + "material."; + + List description = new ArrayList<>(); + description.add(this.user.getTranslation(reference + "description", + "[id]", material.name())); + + if (this.selectedElements.contains(material)) + { + description.add(this.user.getTranslation(reference + "selected")); + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-deselect")); + } + else + { + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-select")); + } + + return new PanelItemBuilder(). + name(this.user.getTranslation(reference + "name", "[material]", + Utils.prettifyObject(material, this.user))). + icon(GuiUtils.getMaterialItem(material)). + description(description). + clickHandler((panel, user1, clickType, slot) -> { + // On right click change which entities are selected for deletion. + if (!this.selectedElements.add(material)) + { + // Remove material if it is already selected + this.selectedElements.remove(material); + } + + this.build(); + return true; + }). + glow(this.selectedElements.contains(material)). + build(); + } + + + /** + * Functional buttons in current GUI. + */ + private enum Button + { + ACCEPT_SELECTED, + CANCEL + } + + + public enum Mode + { + BLOCKS, + ITEMS, + ANY + } + + +// --------------------------------------------------------------------- +// Section: Variables +// --------------------------------------------------------------------- + + /** + * List with elements that will be displayed in current GUI. + */ + private final List elements; + + /** + * Set that contains selected materials. + */ + private final Set selectedElements; + + /** + * This variable stores consumer. + */ + private final BiConsumer> consumer; +} diff --git a/src/main/java/world/bentobox/challenges/panel/util/MultiEntitySelector.java b/src/main/java/world/bentobox/challenges/panel/util/MultiEntitySelector.java new file mode 100644 index 0000000..1cb6c3d --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/util/MultiEntitySelector.java @@ -0,0 +1,251 @@ +package world.bentobox.challenges.panel.util; + + +import org.bukkit.Material; +import org.bukkit.entity.EntityType; +import org.bukkit.inventory.ItemStack; +import java.util.*; +import java.util.function.BiConsumer; +import java.util.stream.Collectors; + +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.Constants; +import world.bentobox.challenges.utils.GuiUtils; +import world.bentobox.challenges.utils.Utils; + + +/** + * This class contains all necessary things that allows to select single block from all ingame blocks. Selected + * block will be returned via BiConsumer. + */ +public class MultiEntitySelector extends PagedSelector +{ + private MultiEntitySelector(User user, boolean asEgg, Mode mode, Set excluded, BiConsumer> consumer) + { + super(user); + + this.consumer = consumer; + this.asEgg = asEgg; + this.selectedElements = new HashSet<>(); + + this.elements = Arrays.stream(EntityType.values()). + filter(entity -> !excluded.contains(entity)). + filter(entity -> { + if (mode == Mode.ALIVE) + { + return entity.isAlive(); + } + else + { + return true; + } + }). + collect(Collectors.toList()); + } + + + /** + * This method opens GUI that allows to select challenge type. + * + * @param user User who opens GUI. + * @param consumer Consumer that allows to get clicked type. + */ + public static void open(User user, boolean asEgg, Mode mode, Set excluded, BiConsumer> consumer) + { + new MultiEntitySelector(user, asEgg, mode, excluded, consumer).build(); + } + + + /** + * This method opens GUI that allows to select challenge type. + * + * @param user User who opens GUI. + * @param consumer Consumer that allows to get clicked type. + */ + public static void open(User user, boolean asEgg, BiConsumer> consumer) + { + new MultiEntitySelector(user, asEgg, Mode.ANY, new HashSet<>(), consumer).build(); + } + + +// --------------------------------------------------------------------- +// Section: Methods +// --------------------------------------------------------------------- + + + /** + * This method builds all necessary elements in GUI panel. + */ + protected void build() + { + PanelBuilder panelBuilder = new PanelBuilder().user(this.user); + panelBuilder.name(this.user.getTranslation(Constants.TITLE + "entity-selector")); + + GuiUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE); + + this.populateElements(panelBuilder, this.elements); + + panelBuilder.item(3, this.createButton(Button.ACCEPT_SELECTED)); + panelBuilder.item(5, this.createButton(Button.CANCEL)); + + 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; + + switch (button) + { + case ACCEPT_SELECTED -> { + if (!this.selectedElements.isEmpty()) + { + description.add(this.user.getTranslation(reference + "title")); + this.selectedElements.forEach(material -> { + description.add(this.user.getTranslation(reference + "element", + "[element]", Utils.prettifyObject(material, this.user))); + }); + } + + icon = new ItemStack(Material.COMMAND_BLOCK); + clickHandler = (panel, user1, clickType, slot) -> + { + this.consumer.accept(true, this.selectedElements); + return true; + }; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-save")); + } + case CANCEL -> { + + icon = new ItemStack(Material.IRON_DOOR); + + clickHandler = (panel, user1, clickType, slot) -> + { + this.consumer.accept(false, null); + return true; + }; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-cancel")); + } + default -> { + icon = new ItemStack(Material.PAPER); + clickHandler = null; + } + } + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + clickHandler(clickHandler). + build(); + } + + + /** + * This method creates button for given entity. + * @param entity entity which button must be created. + * @return new Button for entity. + */ + @Override + protected PanelItem createElementButton(EntityType entity) + { + final String reference = Constants.BUTTON + "entity."; + + List description = new ArrayList<>(); + description.add(this.user.getTranslation(reference + "description", + "[id]", entity.name())); + + if (this.selectedElements.contains(entity)) + { + description.add(this.user.getTranslation(reference + "selected")); + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-deselect")); + } + else + { + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-select")); + } + + return new PanelItemBuilder(). + name(this.user.getTranslation(reference + "name", "[entity]", + Utils.prettifyObject(entity, this.user))). + icon(this.asEgg ? GuiUtils.getEntityEgg(entity) : GuiUtils.getEntityHead(entity)). + description(description). + clickHandler((panel, user1, clickType, slot) -> { + // On right click change which entities are selected for deletion. + if (!this.selectedElements.add(entity)) + { + // Remove entity if it is already selected + this.selectedElements.remove(entity); + } + + this.build(); + return true; + }). + glow(this.selectedElements.contains(entity)). + build(); + } + + + /** + * Functional buttons in current GUI. + */ + private enum Button + { + ACCEPT_SELECTED, + CANCEL + } + + + public enum Mode + { + ALIVE, + ANY + } + + +// --------------------------------------------------------------------- +// Section: Variables +// --------------------------------------------------------------------- + + /** + * List with elements that will be displayed in current GUI. + */ + private final List elements; + + /** + * Set that contains selected materials. + */ + private final Set selectedElements; + + /** + * This variable stores consumer. + */ + private final BiConsumer> consumer; + + /** + * Indicates that entity must be displayed as egg. + */ + private final boolean asEgg; +} diff --git a/src/main/java/world/bentobox/challenges/panel/util/PagedSelector.java b/src/main/java/world/bentobox/challenges/panel/util/PagedSelector.java new file mode 100644 index 0000000..a53437c --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/util/PagedSelector.java @@ -0,0 +1,178 @@ +// +// Created by BONNe +// Copyright - 2021 +// + + +package world.bentobox.challenges.panel.util; + + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import java.util.ArrayList; +import java.util.List; + +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.Constants; + + +/** + * This single abstract class will manage paged selectors similar to CommonPagedPanel. + */ +public abstract class PagedSelector +{ + /** + * Instantiates a new Paged selector. + * + * @param user the user + */ + protected PagedSelector(User user) + { + this.user = user; + } + + + /** + * Build. + */ + protected abstract void build(); + + + /** + * Create element button panel item. + * + * @param object the object + * @return the panel item + */ + protected abstract PanelItem createElementButton(T object); + + + /** + * Populate elements. + * + * @param panelBuilder the panel builder + * @param objectList the object list + */ + protected void populateElements(PanelBuilder panelBuilder, List objectList) + { + 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, this.createElementButton(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; + + /** + * User who opens gui. + */ + protected final User user; +} diff --git a/src/main/java/world/bentobox/challenges/panel/util/SelectBlocksGUI.java b/src/main/java/world/bentobox/challenges/panel/util/SelectBlocksGUI.java deleted file mode 100644 index d3ffdcb..0000000 --- a/src/main/java/world/bentobox/challenges/panel/util/SelectBlocksGUI.java +++ /dev/null @@ -1,276 +0,0 @@ -package world.bentobox.challenges.panel.util; - - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.function.BiConsumer; - -import org.apache.commons.lang.WordUtils; -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.bentobox.api.user.User; -import world.bentobox.challenges.utils.GuiUtils; - - -/** - * This class contains all necessary things that allows to select single block from all ingame blocks. Selected - * block will be returned via BiConsumer. - */ -public class SelectBlocksGUI -{ - public SelectBlocksGUI(User user, BiConsumer> consumer) - { - this(user, false, new HashSet<>(), consumer); - } - - public SelectBlocksGUI(User user, boolean singleSelect, BiConsumer> consumer) - { - this.consumer = consumer; - this.user = user; - this.singleSelect = singleSelect; - - // Current GUI cannot display air blocks. It crashes with null-pointer - Set excludedMaterial = new HashSet<>(); - - excludedMaterial.add(Material.AIR); - excludedMaterial.add(Material.CAVE_AIR); - excludedMaterial.add(Material.VOID_AIR); - - // Piston head and moving piston is not necessary. useless. - excludedMaterial.add(Material.PISTON_HEAD); - excludedMaterial.add(Material.MOVING_PISTON); - - // Barrier cannot be accessible to user. - excludedMaterial.add(Material.BARRIER); - - this.elements = new ArrayList<>(); - this.selectedMaterials = new HashSet<>(); - - for (Material material : Material.values()) - { - if (!material.isLegacy() && !excludedMaterial.contains(material)) - { - this.elements.add(material); - } - } - - this.build(0); - } - - - public SelectBlocksGUI(User user, boolean singleSelect, Set excludedMaterial, BiConsumer> consumer) - { - this.consumer = consumer; - this.user = user; - this.singleSelect = singleSelect; - - // Current GUI cannot display air blocks. It crashes with null-pointer - excludedMaterial.add(Material.AIR); - excludedMaterial.add(Material.CAVE_AIR); - excludedMaterial.add(Material.VOID_AIR); - - // Piston head and moving piston is not necessary. useless. - excludedMaterial.add(Material.PISTON_HEAD); - excludedMaterial.add(Material.MOVING_PISTON); - - // Barrier cannot be accessible to user. - excludedMaterial.add(Material.BARRIER); - - this.elements = new ArrayList<>(); - this.selectedMaterials = new HashSet<>(); - - for (Material material : Material.values()) - { - if (material.isBlock() && !material.isLegacy() && !excludedMaterial.contains(material)) - { - this.elements.add(material); - } - } - - this.build(0); - } - - -// --------------------------------------------------------------------- -// Section: Methods -// --------------------------------------------------------------------- - - - /** - * This method builds all necessary elements in GUI panel. - */ - public void build(int pageIndex) - { - PanelBuilder panelBuilder = new PanelBuilder().user(this.user). - name(this.user.getTranslation("challenges.gui.title.admin.select-block")); - - GuiUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE); - - final int MAX_ELEMENTS = 21; - final int correctPage; - - if (pageIndex < 0) - { - correctPage = this.elements.size() / MAX_ELEMENTS; - } - else if (pageIndex > (this.elements.size() / MAX_ELEMENTS)) - { - correctPage = 0; - } - else - { - correctPage = pageIndex; - } - - int entitiesIndex = MAX_ELEMENTS * correctPage; - - // I want first row to be only for navigation and return button. - int index = 10; - - while (entitiesIndex < ((correctPage + 1) * MAX_ELEMENTS) && - entitiesIndex < this.elements.size()) - { - if (!panelBuilder.slotOccupied(index)) - { - panelBuilder.item(index, this.createMaterialButton(this.elements.get(entitiesIndex++))); - } - - index++; - } - - panelBuilder.item(3, - new PanelItemBuilder(). - icon(Material.RED_STAINED_GLASS_PANE). - name(this.user.getTranslation("challenges.gui.buttons.admin.cancel")). - clickHandler( (panel, user1, clickType, slot) -> { - this.consumer.accept(false, null); - return true; - }).build()); - - - List description = new ArrayList<>(); - if (!this.selectedMaterials.isEmpty()) - { - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.selected") + ":"); - this.selectedMaterials.forEach(material -> description.add(" - " + material.name())); - } - - panelBuilder.item(5, - new PanelItemBuilder(). - icon(Material.GREEN_STAINED_GLASS_PANE). - name(this.user.getTranslation("challenges.gui.buttons.admin.accept")). - description(description). - clickHandler( (panel, user1, clickType, slot) -> { - this.consumer.accept(true, this.selectedMaterials); - return true; - }).build()); - - if (this.elements.size() > MAX_ELEMENTS) - { - // Navigation buttons if necessary - - panelBuilder.item(18, - new PanelItemBuilder(). - icon(Material.OAK_SIGN). - name(this.user.getTranslation("challenges.gui.buttons.previous")). - clickHandler((panel, user1, clickType, slot) -> { - this.build(correctPage - 1); - return true; - }).build()); - - panelBuilder.item(26, - new PanelItemBuilder(). - icon(Material.OAK_SIGN). - name(this.user.getTranslation("challenges.gui.buttons.next")). - clickHandler((panel, user1, clickType, slot) -> { - this.build(correctPage + 1); - return true; - }).build()); - } - - 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, null); - return true; - }).build()); - - panelBuilder.build(); - } - - - /** - * This method creates PanelItem that represents given material. - * Some materials is not displayable in Inventory GUI, so they are replaced with "placeholder" items. - * @param material Material which icon must be created. - * @return PanelItem that represents given material. - */ - private PanelItem createMaterialButton(Material material) - { - ItemStack itemStack = GuiUtils.getMaterialItem(material); - - return new PanelItemBuilder(). - name(WordUtils.capitalize(material.name().toLowerCase().replace("_", " "))). - description(this.selectedMaterials.contains(material) ? - this.user.getTranslation("challenges.gui.descriptions.admin.selected") : ""). - icon(itemStack). - clickHandler((panel, user1, clickType, slot) -> { - if (!this.singleSelect && clickType.isRightClick()) - { - if (!this.selectedMaterials.add(material)) - { - this.selectedMaterials.remove(material); - } - - panel.getInventory().setItem(slot, this.createMaterialButton(material).getItem()); - } - else - { - this.selectedMaterials.add(material); - this.consumer.accept(true, this.selectedMaterials); - } - - return true; - }). - glow(!itemStack.getType().equals(material)). - build(); - } - - -// --------------------------------------------------------------------- -// Section: Variables -// --------------------------------------------------------------------- - - /** - * List with elements that will be displayed in current GUI. - */ - private List elements; - - /** - * Set that contains selected materials. - */ - private Set selectedMaterials; - - /** - * This variable stores consumer. - */ - private BiConsumer> consumer; - - /** - * User who runs GUI. - */ - private User user; - - /** - * This indicate that return set must contain only single item. - */ - private boolean singleSelect; -} diff --git a/src/main/java/world/bentobox/challenges/panel/util/SelectChallengeGUI.java b/src/main/java/world/bentobox/challenges/panel/util/SelectChallengeGUI.java deleted file mode 100644 index 16cc3b7..0000000 --- a/src/main/java/world/bentobox/challenges/panel/util/SelectChallengeGUI.java +++ /dev/null @@ -1,215 +0,0 @@ -package world.bentobox.challenges.panel.util; - - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.BiConsumer; - -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.event.inventory.ClickType; - -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.database.object.Challenge; -import world.bentobox.challenges.utils.GuiUtils; - - -/** - * This class creates new GUI that allows to select single challenge, which is returned via consumer. - */ -public class SelectChallengeGUI -{ - public SelectChallengeGUI(User user, Map> challengesDescriptionMap, int lineLength, BiConsumer> consumer) - { - this.consumer = consumer; - this.user = user; - this.challengesList = new ArrayList<>(challengesDescriptionMap.keySet()); - this.challengesDescriptionMap = challengesDescriptionMap; - this.lineLength = lineLength; - this.selectedChallenges = new HashSet<>(this.challengesList.size()); - - this.build(0); - } - - - /** - * This method builds panel that allows to select single challenge from input challenges. - */ - private void build(int pageIndex) - { - PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(this.user.getTranslation("challenges.gui.title.admin.select-challenge")); - - GuiUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE); - - // Maximal elements in page. - final int MAX_ELEMENTS = 21; - - final int correctPage; - - if (pageIndex < 0) - { - correctPage = this.challengesList.size() / MAX_ELEMENTS; - } - else if (pageIndex > (this.challengesList.size() / MAX_ELEMENTS)) - { - correctPage = 0; - } - else - { - correctPage = pageIndex; - } - - panelBuilder.item(4, - new PanelItemBuilder(). - icon(Material.RED_STAINED_GLASS_PANE). - name(this.user.getTranslation("challenges.gui.buttons.return")). - clickHandler( (panel, user1, clickType, slot) -> { - this.consumer.accept(false, null); - return true; - }).build()); - - if (this.challengesList.size() > MAX_ELEMENTS) - { - // Navigation buttons if necessary - - panelBuilder.item(18, - new PanelItemBuilder(). - icon(Material.OAK_SIGN). - name(this.user.getTranslation("challenges.gui.buttons.previous")). - clickHandler((panel, user1, clickType, slot) -> { - this.build(correctPage - 1); - return true; - }).build()); - - panelBuilder.item(26, - new PanelItemBuilder(). - icon(Material.OAK_SIGN). - name(this.user.getTranslation("challenges.gui.buttons.next")). - clickHandler((panel, user1, clickType, slot) -> { - this.build(correctPage + 1); - return true; - }).build()); - } - - int challengesIndex = MAX_ELEMENTS * correctPage; - - // I want first row to be only for navigation and return button. - int index = 10; - - while (challengesIndex < ((correctPage + 1) * MAX_ELEMENTS) && - challengesIndex < this.challengesList.size() && - index < 36) - { - if (!panelBuilder.slotOccupied(index)) - { - panelBuilder.item(index, - this.createChallengeButton(this.challengesList.get(challengesIndex++))); - } - - index++; - } - - 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, null); - return true; - }).build()); - - panelBuilder.build(); - } - - - /** - * This method builds PanelItem for given challenge. - * @param challenge Challenge which PanelItem must be created. - * @return new PanelItem for given Challenge. - */ - private PanelItem createChallengeButton(Challenge challenge) - { - List description; - - if (this.selectedChallenges.contains(challenge)) - { - description = new ArrayList<>(); - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.selected")); - description.addAll(this.challengesDescriptionMap.get(challenge)); - } - else - { - description = this.challengesDescriptionMap.get(challenge); - } - - - return new PanelItemBuilder(). - name(ChatColor.translateAlternateColorCodes('&', challenge.getFriendlyName())). - description(GuiUtils.stringSplit(description, this.lineLength)). - icon(challenge.getIcon()). - clickHandler((panel, user1, clickType, slot) -> { - if (clickType == ClickType.RIGHT) - { - // If challenge is not selected, then select :) - if (!this.selectedChallenges.remove(challenge)) - { - this.selectedChallenges.add(challenge); - } - - // Reset button. - panel.getInventory().setItem(slot, this.createChallengeButton(challenge).getItem()); - } - else - { - this.selectedChallenges.add(challenge); - this.consumer.accept(true, this.selectedChallenges); - } - - return true; - }). - glow(this.selectedChallenges.contains(challenge)). - build(); - } - - -// --------------------------------------------------------------------- -// Section: Variables -// --------------------------------------------------------------------- - - - /** - * This variable stores consumer. - */ - private BiConsumer> consumer; - - /** - * User who runs GUI. - */ - private User user; - - /** - * Current value. - */ - private List challengesList; - - /** - * Selected challenges that will be returned to consumer. - */ - private Set selectedChallenges; - - /** - * Map that contains all challenge descriptions - */ - private Map> challengesDescriptionMap; - - /** - * 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/SelectEntityGUI.java b/src/main/java/world/bentobox/challenges/panel/util/SelectEntityGUI.java deleted file mode 100644 index 4104f8a..0000000 --- a/src/main/java/world/bentobox/challenges/panel/util/SelectEntityGUI.java +++ /dev/null @@ -1,237 +0,0 @@ -package world.bentobox.challenges.panel.util; - - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.function.BiConsumer; - -import org.apache.commons.lang.WordUtils; -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.bentobox.api.user.User; -import world.bentobox.challenges.utils.GuiUtils; - - -/** - * This GUI allows to select single entity and return it via Consumer. - */ -public class SelectEntityGUI -{ - public SelectEntityGUI(User user, BiConsumer> consumer) - { - this(user, Collections.emptySet(), true, consumer); - } - - - public SelectEntityGUI(User user, Set excludedEntities, boolean asEggs, BiConsumer> consumer) - { - this.consumer = consumer; - this.user = user; - this.asEggs = asEggs; - - this.entities = new ArrayList<>(EntityType.values().length); - this.selectedEntities = new HashSet<>(EntityType.values().length); - - for (EntityType entityType : EntityType.values()) - { - if (entityType.isAlive() && !excludedEntities.contains(entityType)) - { - this.entities.add(entityType); - } - } - - // Sort mobs by their name for easier search. - this.entities.sort(Comparator.comparing(Enum::name)); - - this.build(0); - } - - -// --------------------------------------------------------------------- -// Section: Methods -// --------------------------------------------------------------------- - - - /** - * This method builds - */ - private void build(int pageIndex) - { - PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(this.user.getTranslation("challenges.gui.title.admin.select-entity")); - - GuiUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE); - - // Maximal elements in page. - final int MAX_ELEMENTS = 21; - - final int correctPage; - - if (pageIndex < 0) - { - correctPage = this.entities.size() / MAX_ELEMENTS; - } - else if (pageIndex > (this.entities.size() / MAX_ELEMENTS)) - { - correctPage = 0; - } - else - { - correctPage = pageIndex; - } - - panelBuilder.item(3, - new PanelItemBuilder(). - icon(Material.RED_STAINED_GLASS_PANE). - name(this.user.getTranslation("challenges.gui.buttons.admin.cancel")). - clickHandler( (panel, user1, clickType, slot) -> { - this.consumer.accept(false, null); - return true; - }).build()); - - List description = new ArrayList<>(); - if (!this.selectedEntities.isEmpty()) - { - description.add(this.user.getTranslation("challenges.gui.descriptions.admin.selected") + ":"); - this.selectedEntities.forEach(entity -> description.add(" - " + entity.name())); - } - - panelBuilder.item(5, - new PanelItemBuilder(). - icon(Material.GREEN_STAINED_GLASS_PANE). - name(this.user.getTranslation("challenges.gui.buttons.admin.accept")). - description(description). - clickHandler( (panel, user1, clickType, slot) -> { - this.consumer.accept(true, this.selectedEntities); - return true; - }).build()); - - if (this.entities.size() > MAX_ELEMENTS) - { - // Navigation buttons if necessary - - panelBuilder.item(18, - new PanelItemBuilder(). - icon(Material.OAK_SIGN). - name(this.user.getTranslation("challenges.gui.buttons.previous")). - clickHandler((panel, user1, clickType, slot) -> { - this.build(correctPage - 1); - return true; - }).build()); - - panelBuilder.item(26, - new PanelItemBuilder(). - icon(Material.OAK_SIGN). - name(this.user.getTranslation("challenges.gui.buttons.next")). - clickHandler((panel, user1, clickType, slot) -> { - this.build(correctPage + 1); - return true; - }).build()); - } - - int entitiesIndex = MAX_ELEMENTS * correctPage; - - // I want first row to be only for navigation and return button. - int slot = 10; - - while (entitiesIndex < ((correctPage + 1) * MAX_ELEMENTS) && - entitiesIndex < this.entities.size() && - slot < 36) - { - if (!panelBuilder.slotOccupied(slot)) - { - panelBuilder.item(slot, - this.createEntityButton(this.entities.get(entitiesIndex++))); - } - - slot++; - } - - panelBuilder.item(44, - new PanelItemBuilder(). - icon(Material.OAK_DOOR). - name(this.user.getTranslation("challenges.gui.buttons.return")). - clickHandler( (panel, user1, clickType, i) -> { - this.consumer.accept(false, null); - return true; - }).build()); - - panelBuilder.build(); - } - - - /** - * This method builds PanelItem for given entity. - * @param entity Entity which PanelItem must be created. - * @return new PanelItem for given Entity. - */ - private PanelItem createEntityButton(EntityType entity) - { - ItemStack itemStack = this.asEggs ? GuiUtils.getEntityEgg(entity) : GuiUtils.getEntityHead(entity); - - return new PanelItemBuilder(). - name(WordUtils.capitalize(entity.name().toLowerCase().replace("_", " "))). - icon(itemStack). - description(this.selectedEntities.contains(entity) ? - this.user.getTranslation("challenges.gui.descriptions.admin.selected") : ""). - clickHandler((panel, user1, clickType, slot) -> { - if (clickType.isRightClick()) - { - if (!this.selectedEntities.add(entity)) - { - this.selectedEntities.remove(entity); - } - - panel.getInventory().setItem(slot, this.createEntityButton(entity).getItem()); - } - else - { - this.selectedEntities.add(entity); - this.consumer.accept(true, this.selectedEntities); - } - - return true; - }). - glow(this.selectedEntities.contains(entity)). - build(); - } - - - -// --------------------------------------------------------------------- -// Section: Variables -// --------------------------------------------------------------------- - - /** - * This variable stores consumer. - */ - private BiConsumer> consumer; - - /** - * Set that contains selected entities. - */ - private Set selectedEntities; - - /** - * User who runs GUI. - */ - private User user; - - /** - * This variable stores if mobs must be displayed as Eggs "true" or Heads "false". - */ - private boolean asEggs; - - /** - * Entities that must be in list. - */ - private List entities; -} diff --git a/src/main/java/world/bentobox/challenges/panel/util/SelectEnvironmentGUI.java b/src/main/java/world/bentobox/challenges/panel/util/SelectEnvironmentGUI.java deleted file mode 100644 index 928998a..0000000 --- a/src/main/java/world/bentobox/challenges/panel/util/SelectEnvironmentGUI.java +++ /dev/null @@ -1,148 +0,0 @@ -package world.bentobox.challenges.panel.util; - - -import java.util.Collections; -import java.util.Set; -import java.util.function.BiConsumer; - -import org.bukkit.Material; -import org.bukkit.World; - -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 class creates panel that allows to select and deselect World Environments. On save it runs - * input consumer with true and selected values. - */ -public class SelectEnvironmentGUI -{ - public SelectEnvironmentGUI(User user, Set values, BiConsumer> consumer) - { - this.user = user; - this.values = values; - this.consumer = consumer; - - this.build(); - } - - - /** - * This method builds environment select panel. - */ - private void build() - { - PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(this.user.getTranslation("challenges.gui.title.admin.toggle-environment")); - - GuiUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE); - - panelBuilder.item(3, new PanelItemBuilder(). - name(this.user.getTranslation("challenges.gui.buttons.admin.save")). - icon(Material.GREEN_STAINED_GLASS_PANE). - clickHandler((panel, user1, clickType, index) -> { - this.consumer.accept(true, this.values); - return true; - }). - build()); - - panelBuilder.item(5, new PanelItemBuilder(). - name(this.user.getTranslation("challenges.gui.buttons.admin.cancel")). - icon(Material.RED_STAINED_GLASS_PANE). - clickHandler((panel, user1, clickType, i) -> { - this.consumer.accept(false, Collections.emptySet()); - return true; - }). - build()); - - panelBuilder.item(20, new PanelItemBuilder(). - name(World.Environment.NETHER.name()). - icon(Material.NETHERRACK). - clickHandler((panel, user1, clickType, i) -> { - if (this.values.contains(World.Environment.NETHER)) - { - this.values.remove(World.Environment.NETHER); - } - else - { - this.values.add(World.Environment.NETHER); - } - - this.build(); - return true; - }). - glow(this.values.contains(World.Environment.NETHER)). - build()); - panelBuilder.item(22, new PanelItemBuilder(). - name(World.Environment.NORMAL.name()). - icon(Material.DIRT). - clickHandler((panel, user1, clickType, i) -> { - if (this.values.contains(World.Environment.NORMAL)) - { - this.values.remove(World.Environment.NORMAL); - } - else - { - this.values.add(World.Environment.NORMAL); - } - - this.build(); - return true; - }). - glow(this.values.contains(World.Environment.NORMAL)). - build()); - panelBuilder.item(24, new PanelItemBuilder(). - name(World.Environment.THE_END.name()). - icon(Material.END_STONE). - clickHandler((panel, user1, clickType, i) -> { - if (this.values.contains(World.Environment.THE_END)) - { - this.values.remove(World.Environment.THE_END); - } - else - { - this.values.add(World.Environment.THE_END); - } - - this.build(); - return true; - }). - glow(this.values.contains(World.Environment.THE_END)). - build()); - - - panelBuilder.item(44, new PanelItemBuilder(). - name(this.user.getTranslation("challenges.gui.buttons.return")). - icon(Material.OAK_DOOR). - clickHandler((panel, user1, clickType, i) -> { - this.consumer.accept(false, Collections.emptySet()); - return true; - }). - build()); - - panelBuilder.build(); - } - - -// --------------------------------------------------------------------- -// Section: Variables -// --------------------------------------------------------------------- - - /** - * User who wants to run command. - */ - private User user; - - /** - * List with selected environments. - */ - private Set values; - - /** - * Stores current Consumer - */ - private BiConsumer> consumer; - -} diff --git a/src/main/java/world/bentobox/challenges/panel/util/SelectStatisticGUI.java b/src/main/java/world/bentobox/challenges/panel/util/SelectStatisticGUI.java deleted file mode 100644 index c261855..0000000 --- a/src/main/java/world/bentobox/challenges/panel/util/SelectStatisticGUI.java +++ /dev/null @@ -1,168 +0,0 @@ -package world.bentobox.challenges.panel.util; - - -import org.apache.commons.lang.WordUtils; -import org.bukkit.Material; -import org.bukkit.Statistic; -import org.bukkit.inventory.ItemStack; -import java.util.*; -import java.util.function.BiConsumer; - -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 class contains all necessary things that allows to select single statistic. Selected - * stats will be returned via BiConsumer. - */ -public class SelectStatisticGUI -{ - public SelectStatisticGUI(User user, BiConsumer consumer) - { - this.consumer = consumer; - this.user = user; - - this.elements = new ArrayList<>(); - this.elements.addAll(Arrays.asList(Statistic.values())); - - this.build(0); - } - - -// --------------------------------------------------------------------- -// Section: Methods -// --------------------------------------------------------------------- - - - /** - * This method builds all necessary elements in GUI panel. - */ - public void build(int pageIndex) - { - PanelBuilder panelBuilder = new PanelBuilder().user(this.user). - name(this.user.getTranslation("challenges.gui.title.admin.select-statistic")); - - GuiUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE); - - final int MAX_ELEMENTS = 21; - final int correctPage; - - if (pageIndex < 0) - { - correctPage = this.elements.size() / MAX_ELEMENTS; - } - else if (pageIndex > (this.elements.size() / MAX_ELEMENTS)) - { - correctPage = 0; - } - else - { - correctPage = pageIndex; - } - - int entitiesIndex = MAX_ELEMENTS * correctPage; - - // I want first row to be only for navigation and return button. - int index = 10; - - while (entitiesIndex < ((correctPage + 1) * MAX_ELEMENTS) && - entitiesIndex < this.elements.size()) - { - if (!panelBuilder.slotOccupied(index)) - { - panelBuilder.item(index, this.createStatisticButton(this.elements.get(entitiesIndex++))); - } - - index++; - } - - panelBuilder.item(3, - new PanelItemBuilder(). - icon(Material.RED_STAINED_GLASS_PANE). - name(this.user.getTranslation("challenges.gui.buttons.admin.cancel")). - clickHandler( (panel, user1, clickType, slot) -> { - this.consumer.accept(false, null); - return true; - }).build()); - - if (this.elements.size() > MAX_ELEMENTS) - { - // Navigation buttons if necessary - - panelBuilder.item(18, - new PanelItemBuilder(). - icon(Material.OAK_SIGN). - name(this.user.getTranslation("challenges.gui.buttons.previous")). - clickHandler((panel, user1, clickType, slot) -> { - this.build(correctPage - 1); - return true; - }).build()); - - panelBuilder.item(26, - new PanelItemBuilder(). - icon(Material.OAK_SIGN). - name(this.user.getTranslation("challenges.gui.buttons.next")). - clickHandler((panel, user1, clickType, slot) -> { - this.build(correctPage + 1); - return true; - }).build()); - } - - 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, null); - return true; - }).build()); - - panelBuilder.build(); - } - - - /** - * This method creates PanelItem that represents given statistic. - * Some materials is not displayable in Inventory GUI, so they are replaced with "placeholder" items. - * @param statistic Material which icon must be created. - * @return PanelItem that represents given statistic. - */ - private PanelItem createStatisticButton(Statistic statistic) - { - ItemStack itemStack = new ItemStack(Material.PAPER); - - return new PanelItemBuilder(). - name(WordUtils.capitalize(statistic.name().toLowerCase().replace("_", " "))). - icon(itemStack). - clickHandler((panel, user1, clickType, slot) -> { - this.consumer.accept(true, statistic); - return true; - }). - glow(false). - build(); - } - - -// --------------------------------------------------------------------- -// Section: Variables -// --------------------------------------------------------------------- - - /** - * List with elements that will be displayed in current GUI. - */ - private List elements; - - /** - * This variable stores consumer. - */ - private BiConsumer consumer; - - /** - * User who runs GUI. - */ - private User user; -} diff --git a/src/main/java/world/bentobox/challenges/panel/util/SingleBlockSelector.java b/src/main/java/world/bentobox/challenges/panel/util/SingleBlockSelector.java new file mode 100644 index 0000000..50092ef --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/util/SingleBlockSelector.java @@ -0,0 +1,207 @@ +package world.bentobox.challenges.panel.util; + + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import java.util.*; +import java.util.function.BiConsumer; +import java.util.stream.Collectors; + +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.Constants; +import world.bentobox.challenges.utils.GuiUtils; +import world.bentobox.challenges.utils.Utils; + + +/** + * This class contains all necessary things that allows to select single block from all ingame blocks. Selected + * block will be returned via BiConsumer. + */ +public class SingleBlockSelector extends PagedSelector +{ + private SingleBlockSelector(User user, Mode mode, Set excluded, BiConsumer consumer) + { + super(user); + this.consumer = consumer; + + // Current GUI cannot display air blocks. It crashes with null-pointer + excluded.add(Material.AIR); + excluded.add(Material.CAVE_AIR); + excluded.add(Material.VOID_AIR); + + // Piston head and moving piston is not necessary. useless. + excluded.add(Material.PISTON_HEAD); + excluded.add(Material.MOVING_PISTON); + + // Barrier cannot be accessible to user. + excluded.add(Material.BARRIER); + + this.elements = Arrays.stream(Material.values()). + filter(material -> !excluded.contains(material)). + filter(material -> { + switch (mode) + { + case BLOCKS -> { + return material.isBlock(); + } + case ITEMS -> { + return material.isItem(); + } + default -> { + return true; + } + } + }). + collect(Collectors.toList()); + } + + + /** + * This method opens GUI that allows to select challenge type. + * + * @param user User who opens GUI. + * @param consumer Consumer that allows to get clicked type. + */ + public static void open(User user, Mode mode, Set excluded, BiConsumer consumer) + { + new SingleBlockSelector(user, mode, excluded, consumer).build(); + } + + + /** + * This method opens GUI that allows to select challenge type. + * + * @param user User who opens GUI. + * @param consumer Consumer that allows to get clicked type. + */ + public static void open(User user, BiConsumer consumer) + { + new SingleBlockSelector(user, Mode.ANY, new HashSet<>(), consumer).build(); + } + + + /** + * This method opens GUI that allows to select challenge type. + * + * @param user User who opens GUI. + * @param consumer Consumer that allows to get clicked type. + */ + public static void open(User user, Mode mode, BiConsumer consumer) + { + new SingleBlockSelector(user, mode, new HashSet<>(), consumer).build(); + } + + +// --------------------------------------------------------------------- +// Section: Methods +// --------------------------------------------------------------------- + + + /** + * This method builds all necessary elements in GUI panel. + */ + protected void build() + { + PanelBuilder panelBuilder = new PanelBuilder().user(this.user); + panelBuilder.name(this.user.getTranslation(Constants.TITLE + "block-selector")); + + GuiUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE); + + this.populateElements(panelBuilder, this.elements); + + panelBuilder.item(4, this.createButton()); + + panelBuilder.build(); + } + + + /** + * This method creates PanelItem button of requested type. + * @return new PanelItem with requested functionality. + */ + private PanelItem createButton() + { + final String reference = Constants.BUTTON + "cancel."; + + final String name = this.user.getTranslation(reference + "name"); + final List description = new ArrayList<>(3); + description.add(this.user.getTranslation(reference + "description")); + + ItemStack icon = new ItemStack(Material.IRON_DOOR); + PanelItem.ClickHandler clickHandler = (panel, user1, clickType, slot) -> + { + this.consumer.accept(false, null); + return true; + }; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-cancel")); + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + clickHandler(clickHandler). + build(); + } + + + /** + * This method creates button for given material. + * @param material material which button must be created. + * @return new Button for material. + */ + @Override + protected PanelItem createElementButton(Material material) + { + final String reference = Constants.BUTTON + "material."; + + List description = new ArrayList<>(); + description.add(this.user.getTranslation(reference + "description", + "[id]", material.name())); + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-choose")); + + return new PanelItemBuilder(). + name(this.user.getTranslation(reference + "name", "[material]", + Utils.prettifyObject(material, this.user))). + icon(GuiUtils.getMaterialItem(material)). + description(description). + clickHandler((panel, user1, clickType, slot) -> { + this.consumer.accept(true, material); + return true; + }). + build(); + } + + +// --------------------------------------------------------------------- +// Section: Mode +// --------------------------------------------------------------------- + + + public enum Mode + { + BLOCKS, + ITEMS, + ANY + } + + +// --------------------------------------------------------------------- +// Section: Variables +// --------------------------------------------------------------------- + + /** + * List with elements that will be displayed in current GUI. + */ + private final List elements; + + /** + * This variable stores consumer. + */ + private final BiConsumer consumer; +} diff --git a/src/main/java/world/bentobox/challenges/panel/util/SingleEntitySelector.java b/src/main/java/world/bentobox/challenges/panel/util/SingleEntitySelector.java new file mode 100644 index 0000000..02c12fa --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/util/SingleEntitySelector.java @@ -0,0 +1,207 @@ +package world.bentobox.challenges.panel.util; + + +import java.util.*; +import java.util.function.BiConsumer; +import java.util.stream.Collectors; + +import org.apache.commons.lang.WordUtils; +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.bentobox.api.user.User; +import world.bentobox.challenges.utils.Constants; +import world.bentobox.challenges.utils.GuiUtils; +import world.bentobox.challenges.utils.Utils; + + +/** + * This GUI allows to select single entity and return it via Consumer. + */ +public class SingleEntitySelector extends PagedSelector +{ + /** + * Instantiates a new Single entity selector. + * + * @param user the user + * @param asEggs the boolean + * @param mode the mode + * @param excluded the excluded + * @param consumer the consumer + */ + private SingleEntitySelector(User user, boolean asEggs, Mode mode, Set excluded, BiConsumer consumer) + { + super(user); + this.consumer = consumer; + this.asEggs = asEggs; + this.elements = Arrays.stream(EntityType.values()). + filter(entity -> !excluded.contains(entity)). + filter(entity -> { + if (mode == Mode.ALIVE) + { + return entity.isAlive(); + } + else + { + return true; + } + }). + collect(Collectors.toList()); + } + + + /** + * This method opens GUI that allows to select challenge type. + * + * @param user User who opens GUI. + * @param consumer Consumer that allows to get clicked type. + */ + public static void open(User user, boolean asEggs, Mode mode, Set excluded, BiConsumer consumer) + { + new SingleEntitySelector(user, asEggs, mode, excluded, consumer).build(); + } + + + /** + * This method opens GUI that allows to select challenge type. + * + * @param user User who opens GUI. + * @param consumer Consumer that allows to get clicked type. + */ + public static void open(User user, boolean asEggs, BiConsumer consumer) + { + new SingleEntitySelector(user, asEggs, Mode.ANY, new HashSet<>(), consumer).build(); + } + + + /** + * This method opens GUI that allows to select challenge type. + * + * @param user User who opens GUI. + * @param consumer Consumer that allows to get clicked type. + */ + public static void open(User user, boolean asEggs, Mode mode, BiConsumer consumer) + { + new SingleEntitySelector(user, asEggs, mode, new HashSet<>(), consumer).build(); + } + + +// --------------------------------------------------------------------- +// Section: Methods +// --------------------------------------------------------------------- + + + /** + * This method builds + */ + @Override + protected void build() + { + PanelBuilder panelBuilder = new PanelBuilder().user(this.user); + panelBuilder.name(this.user.getTranslation(Constants.TITLE + "entity-selector")); + + GuiUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE); + + this.populateElements(panelBuilder, this.elements); + + panelBuilder.item(4, this.createButton()); + + panelBuilder.build(); + } + + + /** + * This method builds PanelItem for given entity. + * @param entity Entity which PanelItem must be created. + * @return new PanelItem for given Entity. + */ + @Override + protected PanelItem createElementButton(EntityType entity) + { + final String reference = Constants.BUTTON + "entity."; + + List description = new ArrayList<>(); + description.add(this.user.getTranslation(reference + "description", + "[id]", entity.name())); + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-choose")); + + return new PanelItemBuilder(). + name(this.user.getTranslation(reference + "name", "[entity]", + Utils.prettifyObject(entity, this.user))). + icon(this.asEggs ? GuiUtils.getEntityEgg(entity) : GuiUtils.getEntityHead(entity)). + description(description). + clickHandler((panel, user1, clickType, slot) -> { + this.consumer.accept(true, entity); + return true; + }). + build(); + } + + + /** + * This method creates PanelItem button of requested type. + * @return new PanelItem with requested functionality. + */ + private PanelItem createButton() + { + final String reference = Constants.BUTTON + "cancel."; + + final String name = this.user.getTranslation(reference + "name"); + final List description = new ArrayList<>(3); + description.add(this.user.getTranslation(reference + "description")); + + ItemStack icon = new ItemStack(Material.IRON_DOOR); + PanelItem.ClickHandler clickHandler = (panel, user1, clickType, slot) -> + { + this.consumer.accept(false, null); + return true; + }; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-cancel")); + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + clickHandler(clickHandler). + build(); + } + + +// --------------------------------------------------------------------- +// Section: Mode +// --------------------------------------------------------------------- + + + public enum Mode + { + ALIVE, + ANY + } + + +// --------------------------------------------------------------------- +// Section: Variables +// --------------------------------------------------------------------- + + /** + * List with elements that will be displayed in current GUI. + */ + private final List elements; + + /** + * Indicates if entities are displayed as eggs or heads. + */ + private final boolean asEggs; + + /** + * This variable stores consumer. + */ + private final BiConsumer consumer; +} diff --git a/src/main/java/world/bentobox/challenges/panel/util/StatisticSelector.java b/src/main/java/world/bentobox/challenges/panel/util/StatisticSelector.java new file mode 100644 index 0000000..378427a --- /dev/null +++ b/src/main/java/world/bentobox/challenges/panel/util/StatisticSelector.java @@ -0,0 +1,159 @@ +package world.bentobox.challenges.panel.util; + + +import org.bukkit.Material; +import org.bukkit.Statistic; +import org.bukkit.inventory.ItemStack; +import java.util.*; +import java.util.function.BiConsumer; +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.challenges.utils.Constants; +import world.bentobox.challenges.utils.GuiUtils; +import world.bentobox.challenges.utils.Utils; + + +/** + * This class contains all necessary things that allows to select single statistic. Selected + * stats will be returned via BiConsumer. + */ +public class StatisticSelector extends PagedSelector +{ + /** + * Instantiates a new Statistic selector. + * + * @param user the user + * @param consumer the consumer + */ + private StatisticSelector(User user, BiConsumer consumer) + { + super(user); + + this.consumer = consumer; + this.elements = new ArrayList<>(Arrays.asList(Statistic.values())); + this.elements.sort(Comparator.comparing(Statistic::name)); + } + + + /** + * This method opens GUI that allows to select challenge type. + * + * @param user User who opens GUI. + * @param consumer Consumer that allows to get clicked type. + */ + public static void open(User user, BiConsumer consumer) + { + new StatisticSelector(user, consumer).build(); + } + + +// --------------------------------------------------------------------- +// Section: Methods +// --------------------------------------------------------------------- + + + /** + * This method builds all necessary elements in GUI panel. + */ + @Override + protected void build() + { + PanelBuilder panelBuilder = new PanelBuilder().user(this.user); + panelBuilder.name(this.user.getTranslation(Constants.TITLE + "statistic-selector")); + + GuiUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE); + + this.populateElements(panelBuilder, this.elements); + + panelBuilder.item(4, this.createButton()); + + panelBuilder.build(); + } + + + /** + * This method creates PanelItem that represents given statistic. + * Some materials is not displayable in Inventory GUI, so they are replaced with "placeholder" items. + * @param statistic Material which icon must be created. + * @return PanelItem that represents given statistic. + */ + @Override + protected PanelItem createElementButton(Statistic statistic) + { + final String reference = Constants.BUTTON + "statistic_element."; + + List description = new ArrayList<>(); + + String descriptionText = this.user.getTranslationOrNothing(reference + description, + "[description]", Utils.prettifyDescription(statistic, user)); + + if (!descriptionText.isEmpty()) + { + description.add(descriptionText); + } + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-choose")); + + return new PanelItemBuilder(). + name(this.user.getTranslation(reference + "name", "[statistic]", + Utils.prettifyObject(statistic, this.user))). + icon(Material.PAPER). + description(description). + clickHandler((panel, user1, clickType, slot) -> { + this.consumer.accept(true, statistic); + return true; + }). + build(); + } + + + /** + * This method creates PanelItem button of requested type. + * @return new PanelItem with requested functionality. + */ + private PanelItem createButton() + { + final String reference = Constants.BUTTON + "cancel."; + + final String name = this.user.getTranslation(reference + "name"); + final List description = new ArrayList<>(3); + description.add(this.user.getTranslation(reference + "description")); + + ItemStack icon = new ItemStack(Material.IRON_DOOR); + PanelItem.ClickHandler clickHandler = (panel, user1, clickType, slot) -> + { + this.consumer.accept(false, null); + return true; + }; + + description.add(""); + description.add(this.user.getTranslation(Constants.TIPS + "click-to-cancel")); + + return new PanelItemBuilder(). + icon(icon). + name(name). + description(description). + clickHandler(clickHandler). + build(); + } + + +// --------------------------------------------------------------------- +// Section: Variables +// --------------------------------------------------------------------- + + /** + * List with elements that will be displayed in current GUI. + */ + private final List elements; + + /** + * This variable stores consumer. + */ + private final BiConsumer consumer; +}