NumberInputGUI.java 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package me.lethunderhawk.tradeplugin.input.player;
  2. import me.lethunderhawk.bazaarflux.util.gui.InventoryGUI;
  3. import me.lethunderhawk.bazaarflux.util.gui.InventoryManager;
  4. import net.kyori.adventure.text.Component;
  5. import org.bukkit.Bukkit;
  6. import org.bukkit.Material;
  7. import org.bukkit.entity.Player;
  8. import org.bukkit.inventory.ItemStack;
  9. import org.bukkit.inventory.meta.ItemMeta;
  10. import org.bukkit.plugin.java.JavaPlugin;
  11. import java.util.ArrayList;
  12. import java.util.List;
  13. import java.util.function.BiConsumer;
  14. /**
  15. * Number input built on top of InventoryGUI.
  16. * Open with: InventoryManager.openFor(player, new NumberInputGUI(plugin, player, title, min, max, def, callback));
  17. */
  18. public class NumberInputGUI extends InventoryGUI implements InventoryGUI.AutoCloseHandler {
  19. private final JavaPlugin plugin;
  20. private final Player player;
  21. private final int minValue;
  22. private final int maxValue;
  23. private final BiConsumer<Player, Integer> callback;
  24. private int currentValue;
  25. private static final int PAPER_SLOT = 13, CONFIRM_SLOT = 22, CANCEL_SLOT = 26;
  26. public NumberInputGUI(JavaPlugin plugin, Player player, String title,
  27. int minValue, int maxValue, int defaultValue,
  28. BiConsumer<Player, Integer> callback) {
  29. super(title, 27);
  30. this.plugin = plugin;
  31. this.player = player;
  32. this.minValue = minValue;
  33. this.maxValue = maxValue;
  34. this.currentValue = Math.max(minValue, Math.min(maxValue, defaultValue));
  35. this.callback = callback;
  36. buildContents();
  37. }
  38. private void buildContents() {
  39. // center display
  40. updateDisplay();
  41. // confirm button
  42. ItemStack confirm = make(Material.GREEN_DYE, "§a§lBestätigen");
  43. setItemWithClickAction(CONFIRM_SLOT, confirm, (p, t) -> {
  44. // Confirm -> close and return value
  45. finishAndClose(currentValue);
  46. });
  47. // cancel button
  48. ItemStack cancel = make(Material.BARRIER, "§c§lAbbrechen");
  49. setItemWithClickAction(CANCEL_SLOT, cancel, (p, t) -> {
  50. finishAndClose(0); // original code returned 0 on cancel
  51. });
  52. // paper slot: we need to handle left/right and shift. InventoryGUI only provides slot action without click type,
  53. // but GUIListener passes raw slot only. To handle click types we use the player's last click state via a small workaround:
  54. // we rely on the player sneaking for "shift" and toggle behavior between increment/decrement using right-click sub-GUI is omitted.
  55. // We'll implement: left-click (increment 1), sneak+left (increment 10).
  56. setItemWithClickAction(PAPER_SLOT, buildPaperWithContents(), (p, type) -> {
  57. if(type.isLeftClick()){
  58. currentValue = Math.min(maxValue, currentValue + (type.isShiftClick() ? 10 : 1));
  59. }else if(type.isRightClick()){
  60. currentValue = Math.max(minValue, currentValue - (type.isShiftClick() ? 10 : 1));
  61. }
  62. updateDisplay();
  63. // ensure client sees update
  64. p.updateInventory();
  65. });
  66. // fill remaining slots with background
  67. fillBackground(Material.GRAY_STAINED_GLASS_PANE, " ");
  68. player.updateInventory();
  69. }
  70. private ItemStack make(Material mat, String name) {
  71. ItemStack it = new ItemStack(mat);
  72. ItemMeta m = it.getItemMeta();
  73. if (m != null) {
  74. m.itemName(Component.text(name));
  75. it.setItemMeta(m);
  76. }
  77. return it;
  78. }
  79. private void updateDisplay() {
  80. ItemStack valueItem = buildPaperWithContents();
  81. setItem(PAPER_SLOT, valueItem);
  82. }
  83. private ItemStack buildPaperWithContents() {
  84. ItemStack valueItem = new ItemStack(Material.PAPER);
  85. ItemMeta meta = valueItem.getItemMeta();
  86. meta.itemName(Component.text("§eAktueller Wert: §6" + currentValue));
  87. List<Component> lore = new ArrayList<>();
  88. lore.add(Component.text("§7Min: §f" + minValue));
  89. lore.add(Component.text("§7Max: §f" + maxValue));
  90. lore.add(Component.text(""));
  91. lore.add(Component.text("§aLinksklick: §7+1"));
  92. lore.add(Component.text("§aRechtsklick: §7-1"));
  93. lore.add(Component.text("§aSchleichen + Klick: §7+/-10"));
  94. meta.lore(lore);
  95. valueItem.setItemMeta(meta);
  96. return valueItem;
  97. }
  98. private void finishAndClose(Integer result) {
  99. // ensure main-thread close & callback
  100. if (!Bukkit.isPrimaryThread()) {
  101. Bukkit.getScheduler().runTask(plugin, () -> finishAndClose(result));
  102. return;
  103. }
  104. // remove tracking and close handled by InventoryManager on close event; manually remove and close here
  105. InventoryManager.close(player.getUniqueId());
  106. player.closeInventory();
  107. callback.accept(player, result);
  108. }
  109. public void open() {
  110. if (minValue >= maxValue) {
  111. player.sendMessage("§cDu hast kein Geld zum Ausgeben!");
  112. return;
  113. }
  114. InventoryManager.openFor(player, this);
  115. }
  116. @Override
  117. public void onClosedByPlayer(Player p) {
  118. // accidental close -> null callback (original behaviour)
  119. callback.accept(p, null);
  120. }
  121. }