diff --git a/pom.xml b/pom.xml index 80a4f23..6da78c1 100644 --- a/pom.xml +++ b/pom.xml @@ -83,6 +83,12 @@ 1.0.0-SNAPSHOT provided + + fr.cleymax + signgui + 1.1.0 + provided + diff --git a/src/main/java/de/fanta/challengesjoinentities/ChallengesJoinEntities.java b/src/main/java/de/fanta/challengesjoinentities/ChallengesJoinEntities.java index f93019e..0d310e9 100644 --- a/src/main/java/de/fanta/challengesjoinentities/ChallengesJoinEntities.java +++ b/src/main/java/de/fanta/challengesjoinentities/ChallengesJoinEntities.java @@ -28,6 +28,7 @@ import de.iani.cubesidestats.api.CubesideStatisticsAPI; import de.iani.cubesideutils.bukkit.commands.CommandRouter; import de.iani.playerUUIDCache.PlayerUUIDCache; +import fr.cleymax.signgui.SignManager; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.format.TextColor; @@ -72,6 +73,7 @@ private CubesideStatisticsAPI cubesideStatistics; private Statistics statistics; + private static SignManager signManager; public ChallengesJoinEntities() { @@ -93,6 +95,9 @@ cubesideStatistics = getServer().getServicesManager().load(CubesideStatisticsAPI.class); statistics = new Statistics(this); + signManager = new SignManager(this); + signManager.init(); + this.globalDataHelper = new ChallengesGlobalDataHelper(this); this.config = new Config(this); loadCategoriesAndMaps(); @@ -376,4 +381,8 @@ public Statistics getStatistics() { return statistics; } + + public SignManager getSignManager() { + return signManager; + } } diff --git a/src/main/java/de/fanta/challengesjoinentities/adventure/ui/AdventureSearchGUI.java b/src/main/java/de/fanta/challengesjoinentities/adventure/ui/AdventureSearchGUI.java new file mode 100644 index 0000000..66a2767 --- /dev/null +++ b/src/main/java/de/fanta/challengesjoinentities/adventure/ui/AdventureSearchGUI.java @@ -0,0 +1,162 @@ +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.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.HashMap; +import java.util.List; +import java.util.UUID; + +public class AdventureSearchGUI extends AbstractWindow { + private final ChallengesJoinEntities plugin; + 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 static final HashMap> mapsByPlayer = new HashMap<>(); + private final int numOfItemRows; + private int scrollAmount; + + public AdventureSearchGUI(ChallengesJoinEntities plugin, HashMap mapList, String seachEntry, Player player) { + super(player, Bukkit.createInventory(player, WINDOW_SIZE, ChatUtil.GREEN + "Suche: " + ChatUtil.BLUE + seachEntry)); + this.plugin = plugin; + + HashMap maps = new HashMap<>(mapList); + mapsByPlayer.put(player.getUniqueId(), maps); + this.numOfItemRows = (int) (Math.ceil(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; + HashMap maps = mapsByPlayer.get(getPlayer().getUniqueId()); + for (int row = 0; row < NUM_OF_ROWS && index < maps.size(); row++) { + for (int column = 0; column < NUM_OF_ITEM_COLUMNS && index < maps.size(); column++) { + AdventureMap adventureMap = new ArrayList<>(maps.keySet()).get(index++); + ItemStack stack = adventureMap.getItem().clone(); + ItemMeta meta = stack.getItemMeta(); + List lore = meta.getLore(); + lore.add(ChatUtil.GREEN + "Kategorie: " + ChatUtil.BLUE + maps.get(adventureMap).getName()); + meta.setLore(lore); + stack.setItemMeta(meta); + content[row * NUM_OF_COLUMNS + column] = adventureMap == null ? null : stack; + } + } + + 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 adventureMapIndex = (slot - (slot / NUM_OF_COLUMNS)) + this.scrollAmount * NUM_OF_ITEM_COLUMNS; + HashMap maps = mapsByPlayer.get(getPlayer().getUniqueId()); + if (adventureMapIndex >= maps.size()) { + return; + } + + AdventureMap map = new ArrayList<>(maps.keySet()).get(adventureMapIndex); + Player p = getPlayer(); + + if (map != null) { + Category category = maps.get(map); + 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(); + } +} diff --git a/src/main/java/de/fanta/challengesjoinentities/adventure/ui/CategoryUI.java b/src/main/java/de/fanta/challengesjoinentities/adventure/ui/CategoryUI.java index d3a9217..b4c0029 100644 --- a/src/main/java/de/fanta/challengesjoinentities/adventure/ui/CategoryUI.java +++ b/src/main/java/de/fanta/challengesjoinentities/adventure/ui/CategoryUI.java @@ -2,20 +2,25 @@ import de.fanta.challengesjoinentities.ChallengesJoinEntities; import de.fanta.challengesjoinentities.ChatUtil; +import de.fanta.challengesjoinentities.adventure.AdventureMap; import de.fanta.challengesjoinentities.adventure.CategoriesConfig; import de.fanta.challengesjoinentities.adventure.Category; import de.fanta.challengesjoinentities.utils.ui.AbstractWindow; import de.fanta.challengesjoinentities.utils.ui.ItemUtil; +import fr.cleymax.signgui.SignGUI; import org.bukkit.Bukkit; +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 org.bukkit.scheduler.BukkitRunnable; +import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; public class CategoryUI extends AbstractWindow { private final ChallengesJoinEntities plugin; @@ -23,6 +28,8 @@ private final CategoriesConfig config; private final Map categoryPerSlot = new HashMap<>(); + + private final int SEARCH_INDEX = 0; public CategoryUI(ChallengesJoinEntities plugin, CategoriesConfig config, Player player) { super(player, Bukkit.createInventory(player, 9 * (config.getCategories().size() / 7 + ((config.getCategories().size() % 7 > 0) ? 1 : 0)) + 18, ChatUtil.BLUE + "Adventure Map Kategorien")); @@ -32,7 +39,7 @@ protected void rebuildInventory() { Map categories = this.config.getCategories(); - List sortedValues = categories.values().stream().sorted(Comparator.comparing(Category::getName)).collect(Collectors.toList()); + List sortedValues = categories.values().stream().sorted(Comparator.comparing(Category::getName)).toList(); int row = 0; int cat = 0; for (Category category : sortedValues) { @@ -46,18 +53,63 @@ row++; cat = 0; } + + ItemStack searchItem = new ItemStack(Material.DARK_OAK_SIGN); + ItemMeta itemMeta = searchItem.getItemMeta(); + itemMeta.setDisplayName(ChatUtil.GREEN + "Suche"); + String[] lore = {ChatUtil.GREEN + "Suche nach Adventure Maps"}; + itemMeta.setLore(Arrays.stream(lore).toList()); + searchItem.setItemMeta(itemMeta); + + getInventory().setItem(SEARCH_INDEX, searchItem); + for (int i1 = 0; i1 < getInventory().getSize(); i1++) { ItemStack item = getInventory().getItem(i1); - if (item == null) - getInventory().setItem(i1, ItemUtil.EMPTY_ICON); + if (item == null) { + getInventory().setItem(i1, ItemUtil.EMPTY_ICON); + } } } public void onItemClicked(InventoryClickEvent event) { super.onItemClicked(event); int slot = event.getSlot(); + + if (slot == SEARCH_INDEX) { + SignGUI gui = new SignGUI(plugin.getSignManager(), signEvent -> new BukkitRunnable() { + @Override + public void run() { + String line1 = signEvent.getLines()[0]; + if (line1 != null && !line1.equals("") && !line1.equals(" ")) { + HashMap maps = new HashMap<>(); + for (Category category : plugin.getCategoriesConfig().getCategories().values()) { + for (AdventureMap adventureMap : category.getMaps()) { + if (adventureMap.getName().toLowerCase().contains(line1.toLowerCase())) { + maps.put(adventureMap, category); + } + } + } + + if (maps.isEmpty()) { + ChatUtil.sendErrorMessage(signEvent.getPlayer(), "Kein Ergebnis mit deinem Suchbegriff."); + } else { + new AdventureSearchGUI(plugin, maps, line1, getPlayer()).open(); + } + + } else { + ChatUtil.sendErrorMessage(signEvent.getPlayer(), "Kein Ergebnis mit deinem Suchbegriff."); + } + } + }.runTaskLater(plugin, 1)); + String[] lines = {"", "^^^^^^^^^^^^^^^", "Suche nach", "Adventure Maps"}; + gui.withLines(lines); + gui.open(getPlayer()); + return; + } + Category category = this.categoryPerSlot.get(slot); - if (category != null) - (new AdventureMapsUI(this.plugin, category, getPlayer())).open(); + if (category != null) { + new AdventureMapsUI(this.plugin, category, getPlayer()).open(); + } } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 21595e8..533be69 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -5,7 +5,7 @@ api-version: 1.13 depend: [GlobalClient, CubesideUtils, GlobalPort, CubesideNMSUtils, CubesideStatistics] -softdepend: [Challenges, CubesideNPCs] +softdepend: [Challenges, CubesideNPCs, SignGUI] commands: piglins: