Solved Inventory object changes with openInventory()

Discussion in 'Spigot Plugin Development' started by Nuubles, Nov 25, 2018.

  1. If a player opens a new inventory with the code below, the inventory is always the same when the holding player clicks an item etc. When a player tries to close inventory when it is not allowed to (check "allowClose" and related events) the code will reopen the same inventory as before for the player, denying the possibility of closing the inventory, but when player tries to close the inventory again, the given inventory is not the same as the inventory which player is currently holding (check image). This behavior also breaks all the click events (closeInventory() is not called) because they also will give you a wrong inventory.

    upload_2018-11-25_15-52-58.png

    Most of the unrelated code has been removed

    Code (Java):
    /**
    *
    */

    package net.karanteeni.core.inventory;

    import org.bukkit.Bukkit;
    import org.bukkit.Material;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.inventory.InventoryClickEvent;
    import org.bukkit.event.inventory.InventoryCloseEvent;
    import org.bukkit.event.inventory.InventoryDragEvent;
    import org.bukkit.event.inventory.InventoryType;
    import org.bukkit.event.player.PlayerQuitEvent;
    import org.bukkit.inventory.Inventory;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.ItemMeta;

    import net.karanteeni.core.KaranteeniCore;
    import net.karanteeni.core.KaranteeniPlugin;
    import net.karanteeni.core.information.sounds.Sounds;

    /**
    * @author Nuubles
    *
    */

    public abstract class InventoryMenu implements Listener {

        protected Inventory inventory;
        protected Player player;
        private ItemStack back;
        private ItemStack close;
        private ItemStack empty;
        private boolean allowClose;
        private boolean openingClosed = false;
     
        /**
         * Creates a new translated inventorymenu for player
         * @param player
         */

        public InventoryMenu(KaranteeniPlugin plugin, Player player, InventoryType type, int size, boolean useEmptyItems, boolean allowClose, String title)
        {
            //Can player close this inventory
            this.allowClose = allowClose;
            this.player = player;
            //Creates the inventory
            if(type.equals(InventoryType.CHEST))
                inventory = Bukkit.createInventory(player, size, title);
            else
                inventory = Bukkit.createInventory(player, type, title);
         
            //Create the BACK item
            back = new ItemStack(Material.ARROW, 1);
            ItemMeta meta = back.getItemMeta();
            meta.setDisplayName(KaranteeniPlugin.getTranslator().getTranslation(KaranteeniCore.getPlugin(KaranteeniCore.class), player, "inventory-back"));
            back.setItemMeta(meta);
         
            //Create the CLOSE item
            close = new ItemStack(Material.BARRIER, 1);
            meta = close.getItemMeta();
            meta.setDisplayName(KaranteeniPlugin.getTranslator().getTranslation(KaranteeniCore.getPlugin(KaranteeniCore.class), player, "inventory-close"));
            close.setItemMeta(meta);

            //Create the EMPTY item
            empty = new ItemStack(Material.GRAY_STAINED_GLASS_PANE, 1);
            meta = empty.getItemMeta();
            meta.setDisplayName(KaranteeniPlugin.getTranslator().getTranslation(KaranteeniCore.getPlugin(KaranteeniCore.class), player, "inventory-empty"));
            empty.setItemMeta(meta);
         
            //Fill the inventory with empty items
            if(useEmptyItems)
                for(int i = 0; i < inventory.getSize(); ++i)
                    inventory.setItem(i, empty);
         
            //Register inventory events
            Bukkit.getPluginManager().registerEvents(this, plugin);

            //Allow subclass to fill items
            fillItems();
         
            //Open inventory to player
            openInventory();
        }
     
        /**
         * Player closes this inventory
         * @param event
         */

        @EventHandler
        public void inventoryClose(InventoryCloseEvent event) {
            if(event.getPlayer().getUniqueId().equals(this.player.getUniqueId())) {
                //Can this inventory be closed this way
                if(this.allowClose)
                {
                    this.closeInventory();
                }
                else
                {
                    if(!openingClosed)
                    {
                        openingClosed = true;
                        //Open the inventory back up to player
                        openInventory();
                        closeDenied();
                        openingClosed = false;
                    }
                }
            }
        }
     
        /**
        * Opens this inventory to player
        */

        private void openInventory()
        {
            if(player != null)
            {          
                player.openInventory(inventory);
            }
            else
                this.closeInventory();
        }

        /**
         * Player tries to close this inventory but is not allowed to
         */

        private void closeDenied()
        {
            //Play the deny sound
            KaranteeniPlugin.getSoundHandler().playSound(player, Sounds.NO.get());
        }
     
        /**
         * Closes this inventory which has been opened by the player
         * @param p
         */

        public void closeInventory() {
            InventoryClickEvent.getHandlerList().unregister(this);
            InventoryCloseEvent.getHandlerList().unregister(this);
            InventoryDragEvent.getHandlerList().unregister(this);
            PlayerQuitEvent.getHandlerList().unregister(this);
            this.allowClose = true;
            player.closeInventory();
        }
     
        public static enum MenuClick {
            SUCCESS,
            FAIL,
            NO_PERMISSION,
            CLICK;
        }
    }
     
    #1 Nuubles, Nov 25, 2018
    Last edited: Nov 25, 2018
  2. RandomHashTags

    Supporter

    Where is the openInventory() fuction?
     
    • Informative Informative x 1
  3. Whoops! I accidentally removed it also from the code. I inserted into the code above the closeDenied() method
     
  4. RandomHashTags

    Supporter

    In my experience, using the InventoryCloseEvent to open another inventory the same tick can be buggy. The events won't trigger if it becomes this way.

    I've found that opening it in a delayed BukkitScheduler with 0 or 1 ticks can fix this. This should replace your player.openInventory(inventory); line. And I usually try to close the player's open inventory (before the scheduler) when opening another inventory just to make sure it doesn't bug out.
    Code (Java):

               Bukkit.getScheduler().scheduleSyncDelayedTask(randompackage, new Runnable() {
                    public void run() {
                        player.openInventory(inventory);
                    }
                }, 0);
     
    #4 RandomHashTags, Nov 25, 2018
    Last edited: Nov 25, 2018
    • Like Like x 1
  5. Thank you! That fixed it
     
    • Friendly Friendly x 1