Newer
Older
ChallengesJoinEntities / src / main / java / de / fanta / challengesjoinentities / adventure / ui / AdventureMapsUI.java
@fanta fanta on 24 Jul 2022 6 KB Make maps scrollable
package de.fanta.challengesjoinentities.adventure.ui;

import de.fanta.challengesjoinentities.ChallengesJoinEntities;
import de.fanta.challengesjoinentities.ChatUtil;
import de.fanta.challengesjoinentities.Server;
import de.fanta.challengesjoinentities.adventure.AdventureMap;
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;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
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;
import java.util.Map;

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 List<AdventureMap> maps;
    private final int numOfItemRows;
    private int scrollAmount;

    public AdventureMapsUI(ChallengesJoinEntities plugin, Category category, Player player) {
        super(player, Bukkit.createInventory(player, WINDOW_SIZE, ChatUtil.RED + category.getName() + " Map's"));
        this.category = category;
        this.plugin = plugin;

        List<AdventureMap> 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() {
        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();
            }
        }

        getInventory().setContents(content);
    }

    public void onItemClicked(InventoryClickEvent event) {
        if (!mayAffectThisInventory(event)) {
            return;
        }

        event.setCancelled(true);

        if (!getInventory().equals(event.getClickedInventory())) {
            return;
        }

        int slot = event.getSlot();
        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()))));
            } else if (!Server.serverPlayers.containsValue(p.getUniqueId())) {
                getPlayer().closeInventory();
                this.plugin.getPluginConfig().getOnlineAdventureServer().ifPresentOrElse(server -> server.loadNewAdventure(p, category.getName(), map.getName()), () -> ChatUtil.sendErrorMessage(p, "Aktuell ist kein Server Frei!"));
            } else {
                ChatUtil.sendErrorMessage(p, "Du kannst nur einen Server starten!");
            }
            getPlayer().closeInventory();
        }
    }

    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();
    }
}