|
7 | 7 | import java.util.Comparator; |
8 | 8 | import java.util.HashSet; |
9 | 9 | import java.util.List; |
| 10 | +import java.util.Objects; |
10 | 11 | import java.util.Set; |
11 | 12 | import java.util.function.Consumer; |
12 | 13 | import java.util.stream.Collectors; |
13 | 14 |
|
14 | 15 | import org.bukkit.Material; |
| 16 | +import org.bukkit.NamespacedKey; |
| 17 | +import org.bukkit.Registry; |
15 | 18 | import org.bukkit.World; |
| 19 | +import org.bukkit.block.Biome; |
16 | 20 | import org.bukkit.event.inventory.InventoryClickEvent; |
17 | 21 | import org.bukkit.event.inventory.InventoryCloseEvent; |
18 | 22 | import org.bukkit.inventory.ItemStack; |
|
35 | 39 | import world.bentobox.challenges.panel.ConversationUtils; |
36 | 40 | import world.bentobox.challenges.panel.util.EnvironmentSelector; |
37 | 41 | import world.bentobox.challenges.panel.util.ItemSelector; |
| 42 | +import world.bentobox.challenges.panel.util.MultiBiomeSelector; |
38 | 43 | import world.bentobox.challenges.panel.util.MultiBlockSelector; |
39 | 44 | import world.bentobox.challenges.utils.Constants; |
40 | 45 | import world.bentobox.challenges.utils.Utils; |
@@ -190,6 +195,7 @@ private void buildIslandRequirementsPanel(PanelBuilder panelBuilder) { |
190 | 195 |
|
191 | 196 |
|
192 | 197 | panelBuilder.item(23, this.createRequirementButton(RequirementButton.SEARCH_RADIUS)); |
| 198 | + panelBuilder.item(24, this.createRequirementButton(RequirementButton.REQUIRED_BIOMES)); |
193 | 199 | panelBuilder.item(25, this.createRequirementButton(RequirementButton.REQUIRED_PERMISSIONS)); |
194 | 200 | } |
195 | 201 |
|
@@ -740,6 +746,11 @@ private PanelItem createRequirementButton(RequirementButton button) { |
740 | 746 | REQUIRED_MATERIALTAGS, REQUIRED_ENTITYTAGS -> { |
741 | 747 | return this.createIslandRequirementButton(button); |
742 | 748 | } |
| 749 | + // Biome requirement is a self-contained island requirement, kept out of the large |
| 750 | + // createIslandRequirementButton switch. |
| 751 | + case REQUIRED_BIOMES -> { |
| 752 | + return this.createBiomeRequirementButton(); |
| 753 | + } |
743 | 754 | // Buttons for Inventory Requirements |
744 | 755 | case REQUIRED_ITEMS, REMOVE_ITEMS, ADD_IGNORED_META, REMOVE_IGNORED_META -> { |
745 | 756 | return this.createInventoryRequirementButton(button); |
@@ -933,6 +944,68 @@ private PanelItem createIslandRequirementButton(RequirementButton button) { |
933 | 944 | .clickHandler(clickHandler).build(); |
934 | 945 | } |
935 | 946 |
|
| 947 | + |
| 948 | + /** |
| 949 | + * Creates the "Required Biomes" button for island challenges. Left-click opens the biome |
| 950 | + * selector (hiding already-chosen biomes); right-click clears the list. |
| 951 | + * |
| 952 | + * @return the PanelItem for the biome requirement button. |
| 953 | + */ |
| 954 | + private PanelItem createBiomeRequirementButton() { |
| 955 | + final String reference = Constants.BUTTON + RequirementButton.REQUIRED_BIOMES.name().toLowerCase() + "."; |
| 956 | + final String name = this.user.getTranslation(reference + "name"); |
| 957 | + final IslandRequirements requirements = this.challenge.getRequirements(); |
| 958 | + final List<String> description = new ArrayList<>(); |
| 959 | + description.add(this.user.getTranslation(reference + Constants.DESCRIPTION_KEY)); |
| 960 | + |
| 961 | + if (requirements.getRequiredBiomes().isEmpty()) { |
| 962 | + description.add(this.user.getTranslation(reference + "none")); |
| 963 | + } else { |
| 964 | + description.add(this.user.getTranslation(reference + Constants.TITLE_KEY)); |
| 965 | + requirements.getRequiredBiomes().forEach(biomeKey -> description.add( |
| 966 | + this.user.getTranslation(reference + "list", "[biome]", Utils.prettifyBiome(biomeKey)))); |
| 967 | + } |
| 968 | + |
| 969 | + description.add(""); |
| 970 | + description.add(this.user.getTranslation(Constants.CLICK_TO_ADD)); |
| 971 | + |
| 972 | + if (!requirements.getRequiredBiomes().isEmpty()) { |
| 973 | + description.add(this.user.getTranslation(Constants.TIPS + "right-click-to-clear")); |
| 974 | + } |
| 975 | + |
| 976 | + return new PanelItemBuilder().icon(new ItemStack(Material.GRASS_BLOCK)).name(name).description(description) |
| 977 | + .glow(false).clickHandler((panel, user, clickType, slot) -> { |
| 978 | + if (clickType.isRightClick()) { |
| 979 | + requirements.getRequiredBiomes().clear(); |
| 980 | + this.build(); |
| 981 | + } else { |
| 982 | + this.openBiomeSelector(requirements); |
| 983 | + } |
| 984 | + return true; |
| 985 | + }).build(); |
| 986 | + } |
| 987 | + |
| 988 | + |
| 989 | + /** |
| 990 | + * Opens the biome selector for the given island requirements, excluding already-chosen |
| 991 | + * biomes, and adds the chosen biomes back to the requirement before rebuilding the panel. |
| 992 | + * |
| 993 | + * @param requirements the island requirements being edited. |
| 994 | + */ |
| 995 | + private void openBiomeSelector(IslandRequirements requirements) { |
| 996 | + Set<Biome> excluded = requirements.getRequiredBiomes().stream() |
| 997 | + .map(key -> Registry.BIOME.get(NamespacedKey.fromString(key))) |
| 998 | + .filter(Objects::nonNull).collect(Collectors.toSet()); |
| 999 | + |
| 1000 | + MultiBiomeSelector.open(this.user, excluded, (status, biomes) -> { |
| 1001 | + if (Boolean.TRUE.equals(status) && biomes != null) { |
| 1002 | + biomes.forEach(biome -> requirements.getRequiredBiomes().add(MultiBiomeSelector.biomeKey(biome))); |
| 1003 | + } |
| 1004 | + |
| 1005 | + this.build(); |
| 1006 | + }); |
| 1007 | + } |
| 1008 | + |
936 | 1009 | /** |
937 | 1010 | * This method creates buttons for inventory requirements menu. |
938 | 1011 | * |
@@ -1090,7 +1163,7 @@ private PanelItem createInventoryRequirementButton(RequirementButton button) { |
1090 | 1163 | glow = false; |
1091 | 1164 |
|
1092 | 1165 | description.add(""); |
1093 | | - description.add(this.user.getTranslation(Constants.TIPS + "click-to-add")); |
| 1166 | + description.add(this.user.getTranslation(Constants.CLICK_TO_ADD)); |
1094 | 1167 | } |
1095 | 1168 | case REMOVE_IGNORED_META -> { |
1096 | 1169 | icon = new ItemStack(Material.RED_SHULKER_BOX); |
@@ -1795,7 +1868,7 @@ private PanelItem createRewardButton(RewardButton button) { |
1795 | 1868 | glow = false; |
1796 | 1869 |
|
1797 | 1870 | description.add(""); |
1798 | | - description.add(this.user.getTranslation(Constants.TIPS + "click-to-add")); |
| 1871 | + description.add(this.user.getTranslation(Constants.CLICK_TO_ADD)); |
1799 | 1872 | } |
1800 | 1873 | case REMOVE_IGNORED_META -> { |
1801 | 1874 | icon = new ItemStack(Material.RED_SHULKER_BOX); |
@@ -1926,7 +1999,7 @@ public enum RequirementButton { |
1926 | 1999 | REQUIRED_LEVEL, REQUIRED_MONEY, REMOVE_MONEY, STATISTIC, STATISTIC_BLOCKS, STATISTIC_ITEMS, |
1927 | 2000 | STATISTIC_ENTITIES, |
1928 | 2001 | STATISTIC_AMOUNT, REMOVE_STATISTIC, REQUIRED_MATERIALTAGS, REQUIRED_ENTITYTAGS, REQUIRED_STATISTICS, |
1929 | | - REMOVE_STATISTICS, REQUIRED_PAPI, REQUIRED_ADVANCEMENTS, |
| 2002 | + REMOVE_STATISTICS, REQUIRED_PAPI, REQUIRED_ADVANCEMENTS, REQUIRED_BIOMES, |
1930 | 2003 | } |
1931 | 2004 |
|
1932 | 2005 | // --------------------------------------------------------------------- |
|
0 commit comments