package com.alttd.easter.gui; import com.alttd.easter.config.Config; import com.alttd.easter.config.Messages; import com.alttd.easter.data.DataManager; import com.alttd.easter.egg.EggType; import com.alttd.easter.util.ItemUtils; import lombok.extern.slf4j.Slf4j; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.JoinConfiguration; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import java.util.*; @Slf4j public class TurnInGuiManager implements Listener { private final DataManager dataManager; private final Map openInventories = new HashMap<>(); public TurnInGuiManager(DataManager dataManager) { this.dataManager = dataManager; } private Component title() { return MiniMessage.miniMessage().deserialize(Messages.RABBIT.GUI_TITLE); } public void open(Player player) { Inventory inv = Bukkit.createInventory(player, 27, title()); openInventories.put(player.getUniqueId(), inv); player.openInventory(inv); } @EventHandler public void onClick(InventoryClickEvent event) { if (!(event.getWhoClicked() instanceof Player player)) { return; } Inventory top = openInventories.get(player.getUniqueId()); if (top == null) { return; } if (!event.getView().getTopInventory().equals(top)) { return; } // If clicking in player inventory with shift-click, prevent moving non-egg items into GUI if (event.isShiftClick() && event.getClickedInventory() != null && event.getClickedInventory().equals(player.getInventory())) { ItemStack stack = event.getCurrentItem(); if (stack != null && !stack.getType().isAir() && !ItemUtils.isEggItem(stack)) { event.setCancelled(true); return; } } // If placing an item into the GUI (cursor over top inventory), only allow egg items boolean inTop = event.getRawSlot() < top.getSize() && event.getRawSlot() >= 0; if (inTop) { ItemStack cursor = event.getCursor(); if (!cursor.getType().isAir() && !ItemUtils.isEggItem(cursor)) { event.setCancelled(true); } } } @EventHandler public void onClose(InventoryCloseEvent event) { Player player = (Player) event.getPlayer(); Inventory top = openInventories.get(player.getUniqueId()); if (top == null) { return; } if (!event.getView().getTopInventory().equals(top)) { return; } openInventories.remove(player.getUniqueId()); // collect egg items for submission and then clear GUI so eggs don't drop Set submitted = new HashSet<>(); for (ItemStack item : top.getContents()) { if (ItemUtils.isEggItem(item)) { EggType type = ItemUtils.getEggType(item); if (type != null) { submitted.add(type); } } } top.clear(); if (submitted.isEmpty()) { player.sendRichMessage(Messages.RABBIT.NO_EGGS); return; } // determine how many new unique egg types were added so we can award correct number of prizes int prevTotal = dataManager.getPlayerEggs(player.getUniqueId()).size(); int newlyAdded = dataManager.addEggs(player.getUniqueId(), submitted); dataManager.save(); // Dialog formatting for submission summary List eggComponents = new ArrayList<>(); for (EggType type : submitted) { eggComponents.add(Component.text(ItemUtils.colorName(type))); } if (eggComponents.size() == 1) { player.sendRichMessage(Messages.RABBIT.ONE_EGG, Placeholder.parsed("player", player.getName()), Placeholder.component("egg1", eggComponents.getFirst()) ); } else { Component eggsJoined; if (eggComponents.size() == 2) { eggsJoined = Component.join( JoinConfiguration.builder() .lastSeparator(Component.text(" and ")) .build(), eggComponents ); } else { eggsJoined = Component.join( JoinConfiguration.builder() .separator(Component.text(", ")) .lastSeparator(Component.text(", and ")) .build(), eggComponents ); } player.sendRichMessage(Messages.RABBIT.MULTI_EGGS, Placeholder.parsed("player", player.getName()), Placeholder.component("eggs", eggsJoined) ); } int newTotal = prevTotal + newlyAdded; int prevMilestones = prevTotal / 4; int newMilestones = newTotal / 4; int prizesToGive = Math.max(0, newMilestones - prevMilestones); List prizeList = Config.PRIZES.LIST; for (int i = 0; i < prizesToGive; i++) { int intendedIndex = prevMilestones + i; if (prizeList.isEmpty()) { log.warn("No prizes configured. Tried to give prize for intended index {}. Staff should configure prizes using /easter setprize.", intendedIndex); } else { int wrappedIndex = intendedIndex % prizeList.size(); if (intendedIndex >= prizeList.size() || intendedIndex < 0) { log.warn("Prize index overflow: intended index {} -> wrapped to {} (prize list size {}).", intendedIndex, wrappedIndex, prizeList.size()); } ItemStack prize = prizeList.get(wrappedIndex).clone(); player.getInventory().addItem(prize); } player.sendRichMessage(Messages.RABBIT.REWARD); } } }