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 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.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::name)); this.selectedMaterials = new HashSet<>(); // Init without filters applied. this.filterElements = this.materialList; } /** * Open the Challenges Admin GUI. */ public static void open(CommonPanel parentGUI, Map materialMap) { new ManageBlocksPanel(parentGUI, materialMap).build(); } // --------------------------------------------------------------------- // Section: Methods // --------------------------------------------------------------------- /** * This method is called when filter value is updated. */ @Override protected void updateFilters() { if (this.searchString == null || this.searchString.isBlank()) { this.filterElements = this.materialList; } else { this.filterElements = this.materialList.stream(). filter(element -> { // If element name is set and name contains search field, then do not filter out. return element.name().toLowerCase().contains(this.searchString.toLowerCase()); }). distinct(). collect(Collectors.toList()); } } /** * 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 + "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.filterElements); // 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. */ @Override protected 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; /** * Stores filtered items. */ private List filterElements; }