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 новых события щелчка инвентаря регистрируются в прослушивателе.
Чтобы исправить это, я предлагаю вам:
- Сделайте ОДИН класс, который получает
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
, затем получите экземпляр держателя, возможно, с каким-то объектом, который в данный момент редактируется игроком
- Не создавайте экземпляр GUI несколько раз. Для меня это не очень хороший способ, и я думаю, что лучше сделать так:
MainGUI mainGUI = GuiManager.getMainGUID(); // here get the alone main GUI instance
// now use it