package me.lethunderhawk.tradeplugin.input.player; import me.lethunderhawk.bazaarflux.util.gui.InventoryGUI; import me.lethunderhawk.bazaarflux.util.gui.InventoryManager; import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.plugin.java.JavaPlugin; import java.util.ArrayList; import java.util.List; import java.util.function.BiConsumer; /** * Number input built on top of InventoryGUI. * Open with: InventoryManager.openFor(player, new NumberInputGUI(plugin, player, title, min, max, def, callback)); */ public class NumberInputGUI extends InventoryGUI implements InventoryGUI.AutoCloseHandler { private final JavaPlugin plugin; private final Player player; private final int minValue; private final int maxValue; private final BiConsumer callback; private int currentValue; private static final int PAPER_SLOT = 13, CONFIRM_SLOT = 22, CANCEL_SLOT = 26; public NumberInputGUI(JavaPlugin plugin, Player player, String title, int minValue, int maxValue, int defaultValue, BiConsumer callback) { super(title, 27); this.plugin = plugin; this.player = player; this.minValue = minValue; this.maxValue = maxValue; this.currentValue = Math.max(minValue, Math.min(maxValue, defaultValue)); this.callback = callback; buildContents(); } private void buildContents() { // center display updateDisplay(); // confirm button ItemStack confirm = make(Material.GREEN_DYE, "§a§lBestätigen"); setItemWithClickAction(CONFIRM_SLOT, confirm, (p, t) -> { // Confirm -> close and return value finishAndClose(currentValue); }); // cancel button ItemStack cancel = make(Material.BARRIER, "§c§lAbbrechen"); setItemWithClickAction(CANCEL_SLOT, cancel, (p, t) -> { finishAndClose(0); // original code returned 0 on cancel }); // paper slot: we need to handle left/right and shift. InventoryGUI only provides slot action without click type, // but GUIListener passes raw slot only. To handle click types we use the player's last click state via a small workaround: // we rely on the player sneaking for "shift" and toggle behavior between increment/decrement using right-click sub-GUI is omitted. // We'll implement: left-click (increment 1), sneak+left (increment 10). setItemWithClickAction(PAPER_SLOT, buildPaperWithContents(), (p, type) -> { if(type.isLeftClick()){ currentValue = Math.min(maxValue, currentValue + (type.isShiftClick() ? 10 : 1)); }else if(type.isRightClick()){ currentValue = Math.max(minValue, currentValue - (type.isShiftClick() ? 10 : 1)); } updateDisplay(); // ensure client sees update p.updateInventory(); }); // fill remaining slots with background fillBackground(Material.GRAY_STAINED_GLASS_PANE, " "); player.updateInventory(); } private ItemStack make(Material mat, String name) { ItemStack it = new ItemStack(mat); ItemMeta m = it.getItemMeta(); if (m != null) { m.itemName(Component.text(name)); it.setItemMeta(m); } return it; } private void updateDisplay() { ItemStack valueItem = buildPaperWithContents(); setItem(PAPER_SLOT, valueItem); } private ItemStack buildPaperWithContents() { ItemStack valueItem = new ItemStack(Material.PAPER); ItemMeta meta = valueItem.getItemMeta(); meta.itemName(Component.text("§eAktueller Wert: §6" + currentValue)); List lore = new ArrayList<>(); lore.add(Component.text("§7Min: §f" + minValue)); lore.add(Component.text("§7Max: §f" + maxValue)); lore.add(Component.text("")); lore.add(Component.text("§aLinksklick: §7+1")); lore.add(Component.text("§aRechtsklick: §7-1")); lore.add(Component.text("§aSchleichen + Klick: §7+/-10")); meta.lore(lore); valueItem.setItemMeta(meta); return valueItem; } private void finishAndClose(Integer result) { // ensure main-thread close & callback if (!Bukkit.isPrimaryThread()) { Bukkit.getScheduler().runTask(plugin, () -> finishAndClose(result)); return; } // remove tracking and close handled by InventoryManager on close event; manually remove and close here InventoryManager.close(player.getUniqueId()); player.closeInventory(); callback.accept(player, result); } public void open() { if (minValue >= maxValue) { player.sendMessage("§cDu hast kein Geld zum Ausgeben!"); return; } InventoryManager.openFor(player, this); } @Override public void onClosedByPlayer(Player p) { // accidental close -> null callback (original behaviour) callback.accept(p, null); } }