AnvilGUI icon indicating copy to clipboard operation
AnvilGUI copied to clipboard

Bug when using onClose() to open another Inventory

Open musicalcomputergeek opened this issue 3 years ago • 2 comments

Anvil GUI version: 1.5.3 Spigot version: 1.18.2-R0.1

Scenario: I'm trying to open the previous inventory when AnvilGUI is closed, as it's less disruptive to "go back" to the previous menu when closed.

Issue: Using builder.onClose() to open another inventory opens target inventory, but that inventory doesn't fire InventoryClickEvent, despite being called by the same method in other locations where it does work.

Steps:

  • Player opens my GUI
  • Clicks a nametag
  • Gets AnvilGUI
  • Hit ESC
  • Returns to first GUI, but the new GUI doesn't respond to player clicks.

My plugin event listener calls openChestManagerGui():

@EventHandler
public void onChestOpen(PlayerInteractEvent e) {
    // conditional checks
    e.setCancelled(true);
    GuiInteract.openChestManagerGui(e.getPlayer(), e.getClickedBlock());
}

AnvilGUI calls the same method onClose():

.onClose((player) -> {
    GuiInteract.openChestManagerGui(player, Utils.getCurrentChest(player));
})

ChestManager GUI opens (all item icons are visible) but has no response to InventoryClickEvent (items can be dragged, clicking does nothing). I tested this with e.getWhoClicked().sendMessage(e.getClickedInventory().toString()); at the beginning of the InventoryClickEvent EventHandler and got no message after closing the AnvilGUI.

Complete AnvilGUI method:

new AnvilGUI.Builder()
    .onClose((player) -> {
        GuiInteract.openChestManagerGui(player, Utils.getCurrentChest(player));
    })
    .onComplete((player,text) -> {
       Block chest = Utils.getCurrentChest(player);
       Player newUser = Utils.getPlayerFromName(text);
       if (newUser == null) {
            player.sendMessage("No online player found by that name.");
            return AnvilGUI.Response.text("Player not found");
        }
        Utils.addChestUser(player, chest, newUser);
        return AnvilGUI.Response.openInventory(ChestManager.inv);
    })
    .text("Username")
    .itemLeft(item)
    .title("Add Chest User")
    .plugin(ChestGuard.getPlugin(ChestGuard.class))
    .open(clicker);
}

musicalcomputergeek avatar Apr 21 '22 14:04 musicalcomputergeek

Try

new BukkitRunnable(() ->
  GuiInteract.openChestManagerGui(player, Utils.getCurrentChest(player))
).runTaskLaster(plugin, 1);

with plugin being a reference to your Plugin instance.

joestr avatar May 19 '22 08:05 joestr

Have same issue. Using BukkitRunable solve problem.

xstmass avatar Sep 07 '22 15:09 xstmass

The best way around this is indeed using a runnable that runs your code a single tick later.

The issue that is occurring is that onClose is called before the InventoryCloseEvent is finished. As a result, your code is running while the anvil is still open, and it makes Bukkit close your inventory. Perhaps a way around this would be to add a Response-like return result for onClose, but this requires some more thought.

WesJD avatar Nov 27 '22 23:11 WesJD

isnt it just better to do Player#closeInventory before opening new one?

minus1ms avatar Jul 11 '23 11:07 minus1ms

If you don't call closeInventory, the users cursor will stay in the same position when the new inventory opens.

WesJD avatar Jul 11 '23 13:07 WesJD

problem is that i want it to go back when i close anvilgui so it opens previous gui, but when player click, i want it to go forward to next gui, when player clicks it first opens next gui and then anvilgui close task is triggered and it opens previous gui

i tried doing delay, so anvilgui will close first (and open prev gui) and then task will run next gui, but now next gui gets ghost items no matter what delay there is

minus1ms avatar Jul 14 '23 11:07 minus1ms

problem is that i want it to go back when i close anvilgui so it opens previous gui, but when player click, i want it to go forward to next gui, when player clicks it first opens next gui and then anvilgui close task is triggered and it opens previous gui

i tried doing delay, so anvilgui will close first (and open prev gui) and then task will run next gui, but now next gui gets ghost items no matter what delay there is

It sounds like a combination of two things: a) You aren't using AnvilGUI.Response.openInventory(Inventory) b) You have another bug in your own code

WesJD avatar Jul 15 '23 16:07 WesJD