InventoryClickEvent запускается несколько раз

У меня есть абстрактный родительский класс GUI, обрабатывающий событие щелчка.

      public abstract class GUI implements Listener {

    private final Inventory inventory;

    public GUI(Player player) {
        Bukkit.getPluginManager().registerEvents(this, NPCs.getPlugin());

        ItemStack fillerItem = new ItemStack(getFiller());
        ItemMeta fillerItemMeta = fillerItem.getItemMeta();
        fillerItemMeta.setDisplayName("");
        fillerItem.setItemMeta(fillerItemMeta);

        int inventorySize = (getFunctionalItems().size()>=54) ? 54 : getFunctionalItems().size()+(9-getFunctionalItems().size()%9)*Math.min(1, getFunctionalItems().size()%9);

        inventory = Bukkit.createInventory(player, inventorySize, getName());

        for(int i = 0; i < inventory.getSize(); i++) {
            inventory.setItem(i, fillerItem);
        }
        for(int i = 0; i < getFunctionalItems().size(); i++) {
            inventory.setItem(i, getFunctionalItems().get(i));
        }
    }

    @EventHandler
    public void onClick(InventoryClickEvent event) {
        handle(event);
    }

    public abstract ArrayList<ItemStack> getFunctionalItems();

    public abstract String getName();

    protected abstract void handle(InventoryClickEvent event);

    public Material getFiller() {
        return Material.GRAY_STAINED_GLASS_PANE;
    }

    public Inventory getInventory() {
        return inventory;
    }

    protected final ItemStack createFunctionalItem(String name, Material material) {
        ItemStack itemStack = new ItemStack(material);
        ItemMeta itemMeta = itemStack.getItemMeta();
        itemMeta.setDisplayName(name);
        itemStack.setItemMeta(itemMeta);

        return itemStack;
    }
}

В моем дочернем классе это обрабатывается следующим образом

          @Override
    public void handle(InventoryClickEvent event) {
        ItemStack clicked = event.getCurrentItem();
        Player player = (Player) event.getWhoClicked();

        MainGUI mainGUI = new MainGUI(player);
        NameGUI nameGUI = new NameGUI(player);
        SkinGUI skinGUI = new SkinGUI(player);

        //Main GUI
        if(Arrays.equals(event.getClickedInventory().getContents(), mainGUI.getInventory().getContents())) {
            switch(clicked.getItemMeta().getDisplayName()) {
                case "Set Name" -> player.openInventory(nameGUI.getInventory());
                case "Set Skin" -> player.openInventory(skinGUI.getInventory());
            }
            event.setCancelled(true);
        }
    }

Но если я проверю, он будет вызван 2 раза при первом нажатии, а при следующем так много раз, что это даже приведет к сбою моей игры. Я знаю, что могу просто поставить задержку, но я действительно хочу знать, почему это так.

Спасибо

1 ответ

Он запускается несколько раз, потому что вы добавляете каждый новый графический интерфейс в прослушиватель.

Например, здесь:

      MainGUI mainGUI = new MainGUI(player);
NameGUI nameGUI = new NameGUI(player);
SkinGUI skinGUI = new SkinGUI(player);

Вы создаете 3 графических интерфейса, поэтому 3 новых события щелчка инвентаря регистрируются в прослушивателе.

Чтобы исправить это, я предлагаю вам:

  1. Сделайте ОДИН класс, который получает InventoryClickEventсобытие и вызвать графический интерфейс, который вам будет вызван.

Например, у вас есть список со всеми GUI:

      public static List<GUI> ALL_GUIS = new ArrayList<>();

Затем у вас должен быть способ определить, в каком инвентаре щелкнул игрок, например:

  • Название инвентаря. Не очень хорошее решение, если это можно изменить, но его легче создать и использовать.
  • Держатель инвентаря вот такой:
      public class MainGUIHolder implements InventoryHolder {

    @Override
    public Inventory getInventory() {
        return null;
    }
}

Теперь используйте это так:

      Inventory mainInv = Bukkit.createInventory(new MainGUIHolder(), 9, "My inv");

Вы можете проверить с inventory instanceof MainGUIHolder, затем получите экземпляр держателя, возможно, с каким-то объектом, который в данный момент редактируется игроком

  1. Не создавайте экземпляр GUI несколько раз. Для меня это не очень хороший способ, и я думаю, что лучше сделать так:
      MainGUI mainGUI = GuiManager.getMainGUID(); // here get the alone main GUI instance
// now use it
Другие вопросы по тегам