diff --git a/src/main/java/de/fanta/challengesjoinentities/adventure/ui/AdventureMapsUI.java b/src/main/java/de/fanta/challengesjoinentities/adventure/ui/AdventureMapsUI.java index a78dfbc..4627457 100644 --- a/src/main/java/de/fanta/challengesjoinentities/adventure/ui/AdventureMapsUI.java +++ b/src/main/java/de/fanta/challengesjoinentities/adventure/ui/AdventureMapsUI.java @@ -7,6 +7,7 @@ import de.fanta.challengesjoinentities.adventure.Category; import de.fanta.challengesjoinentities.utils.ui.AbstractWindow; import de.fanta.challengesjoinentities.utils.ui.ItemUtil; +import de.iani.cubesideutils.bukkit.items.CustomHeads; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.format.TextColor; @@ -19,6 +20,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.List; @@ -26,51 +28,107 @@ public class AdventureMapsUI extends AbstractWindow { private final ChallengesJoinEntities plugin; - private final Category category; + private static final int NUM_OF_COLUMNS = 9; + private static final int NUM_OF_ITEM_COLUMNS = NUM_OF_COLUMNS - 1; + private static final int NUM_OF_ROWS = 6; + private static final int WINDOW_SIZE = NUM_OF_COLUMNS * NUM_OF_ROWS; + private static final int END_OF_FIRST_ROW_INDEX = NUM_OF_COLUMNS - 1; + private static final int END_OF_LAST_ROW_INDEX = WINDOW_SIZE - 1; - private final Map mapsPerSlot = new HashMap<>(); - - private final int BACK_INDEX = getInventory().getSize() - 9; + private final List maps; + private final int numOfItemRows; + private int scrollAmount; public AdventureMapsUI(ChallengesJoinEntities plugin, Category category, Player player) { - super(player, Bukkit.createInventory(player, 9 * (category.getMaps().size() / 7 + ((category.getMaps().size() % 7 > 0) ? 1 : 0)) + 18, ChatUtil.RED + category.getName() + "Map's ")); + super(player, Bukkit.createInventory(player, WINDOW_SIZE, ChatUtil.RED + category.getName() + " Map's")); this.category = category; this.plugin = plugin; + + List maps = this.category.getMaps().stream().sorted(Comparator.comparing(AdventureMap::getName)).toList(); + this.maps = new ArrayList<>(maps.size()); + this.maps.addAll(maps); + + this.numOfItemRows = (int) (Math.ceil(this.maps.size() / (double) NUM_OF_ITEM_COLUMNS)); + this.scrollAmount = 0; } protected void rebuildInventory() { - List maps = this.category.getMaps().stream().sorted(Comparator.comparing(AdventureMap::getName)).toList(); - int row = 0; - int cat = 0; - for (AdventureMap category : maps) { - int slot = row * 9 + cat + 10; - getInventory().setItem(slot, category.getItem()); - this.mapsPerSlot.put(slot, category); - if (cat < 6) { - cat++; - continue; + ItemStack[] content = new ItemStack[WINDOW_SIZE]; + + // build scroll buttons + ItemStack scrollUpHead = this.scrollAmount <= 0 ? CustomHeads.QUARTZ_BLOCK_BLANK.getHead() : CustomHeads.QUARTZ_ARROW_UP.getHead(); + ItemMeta scrollUpMeta = scrollUpHead.getItemMeta(); + scrollUpMeta.setDisplayName((this.scrollAmount <= 0 ? ChatColor.GRAY : ChatColor.WHITE) + "Nach oben scrollen"); + scrollUpHead.setItemMeta(scrollUpMeta); + content[NUM_OF_COLUMNS - 1] = scrollUpHead; + + ItemStack scrollDownHead = this.scrollAmount >= this.numOfItemRows - NUM_OF_ROWS ? CustomHeads.QUARTZ_BLOCK_BLANK.getHead() : CustomHeads.QUARTZ_ARROW_DOWN.getHead(); + ItemMeta scrollDownMeta = scrollDownHead.getItemMeta(); + scrollDownMeta.setDisplayName((this.scrollAmount >= this.numOfItemRows - NUM_OF_ROWS ? ChatColor.GRAY : ChatColor.WHITE) + "Nach unten scrollen"); + scrollDownHead.setItemMeta(scrollDownMeta); + content[WINDOW_SIZE - 1] = scrollDownHead; + + // build scrollbar + for (int i = 1; i < NUM_OF_ROWS - 1; i++) { + content[(i + 1) * NUM_OF_COLUMNS - 1] = new ItemStack(Material.GRAY_STAINED_GLASS_PANE); + } + int numOfScrollbarRows = NUM_OF_ROWS - 2; + int currentScrollbarRow = + (int) Math.round(this.scrollAmount * numOfScrollbarRows / (double) this.numOfItemRows); + content[(currentScrollbarRow + 2) * NUM_OF_COLUMNS - 1] = new ItemStack(Material.BLACK_STAINED_GLASS_PANE); + + // fill in items + int index = this.scrollAmount * NUM_OF_ITEM_COLUMNS; + for (int row = 0; row < NUM_OF_ROWS && index < this.maps.size(); row++) { + for (int column = 0; column < NUM_OF_ITEM_COLUMNS && index < this.maps.size(); column++) { + AdventureMap adventureMap = this.maps.get(index++); + content[row * NUM_OF_COLUMNS + column] = adventureMap == null ? null : adventureMap.getItem(); } - row++; - cat = 0; } - ItemStack backButtton = new ItemStack(Material.PAPER); - ItemMeta meta = backButtton.getItemMeta(); - meta.setDisplayName("" + ChatColor.GREEN + "Zurück"); - backButtton.setItemMeta(meta); - getInventory().setItem(this.BACK_INDEX, backButtton); - for (int i1 = 0; i1 < getInventory().getSize(); i1++) { - ItemStack item = getInventory().getItem(i1); - if (item == null) - getInventory().setItem(i1, ItemUtil.EMPTY_ICON); - } + + getInventory().setContents(content); } public void onItemClicked(InventoryClickEvent event) { - super.onItemClicked(event); + if (!mayAffectThisInventory(event)) { + return; + } + + event.setCancelled(true); + + if (!getInventory().equals(event.getClickedInventory())) { + return; + } + int slot = event.getSlot(); - AdventureMap map = this.mapsPerSlot.get(slot); + if (slot == END_OF_FIRST_ROW_INDEX) { + attempScrollUp(); + return; + } else if (slot == END_OF_LAST_ROW_INDEX) { + attempScrollDown(); + return; + } + + if ((slot + 1) % NUM_OF_COLUMNS == 0) { + int numOfScrollbarRows = NUM_OF_ROWS - 2; + int selectedScrollBarRow = (slot + 1) / NUM_OF_COLUMNS - 2; + int targetScrollAmount = Math.round(selectedScrollBarRow * this.numOfItemRows / numOfScrollbarRows); + this.scrollAmount = Math.min(targetScrollAmount, this.numOfItemRows - NUM_OF_ROWS); + this.scrollAmount = Math.max(this.scrollAmount, 0); + rebuildInventory(); + return; + } + + int shopItemIndex = (slot - (slot / NUM_OF_COLUMNS)) + + this.scrollAmount * NUM_OF_ITEM_COLUMNS; + if (shopItemIndex >= this.maps.size()) { + return; + } + + AdventureMap map = this.maps.get(shopItemIndex); Player p = getPlayer(); + if (map != null) { if (event.isRightClick()) { getPlayer().sendMessage(ChallengesJoinEntities.PREFIX_COMPONENT.append(Component.text("MapLink: klick mich :)", TextColor.color(Color.YELLOW.asRGB())).clickEvent(ClickEvent.clickEvent(ClickEvent.Action.OPEN_URL, map.getWebLink())))); @@ -82,7 +140,21 @@ } getPlayer().closeInventory(); } - if (slot == this.BACK_INDEX) - (new CategoryUI(this.plugin, this.plugin.getCategoriesConfig(), p)).open(); + } + + private void attempScrollUp() { + if (this.scrollAmount <= 0) { + return; + } + this.scrollAmount--; + rebuildInventory(); + } + + private void attempScrollDown() { + if (this.scrollAmount >= this.numOfItemRows - NUM_OF_ROWS) { + return; + } + this.scrollAmount++; + rebuildInventory(); } }