Solved Opening chest inventory (as a menu) to player

Discussion in 'Spigot Plugin Development' started by DavidMa, Feb 24, 2020.

  1. Hi.
    I am trying to create a menu that the player can interact with.
    I would like the menu to be in the form of a chest inventory. After the chest inventory opens to the player, the player can click on an ItemStack in the inventory, which would then carry out an action.
    How would I create a chest inventory and force the player to open it (it should be done without actually creating a chest in the world)?
    How do I detect when the player clicks on an item, and perform certain actions?
     
    • Agree Agree x 1
  2. First, you're going to want to create an Inventory.
    Code (Java):
    int inventorySize = 27;
    String inventoryName = "My Epic Inventory";
    Inventory inventory = Bukkit.createInventory(null, inventorySize, inventoryName);
    Note that the second argument, which is the size of the inventory, must be a multiple of 9. That number can be expressed as amountOfRows * 9

    You're probably going to want some items in it, so you can add them like this:
    Code (Java):
    inventory.addItem(new ItemStack(Material.DIRT));
    .. or if you want them in a specific spot:
    Code (Java):
    int locationInInventory = 12;
    inventory.setItem(locationInInventory, new ItemStack(Material.DIAMOND));
    Then, you can have the player open it like so:
    Code (Java):
    player.openInventory(inventory);
    Now, to have actions be carried out when items in the chest are clicked you're going to have to listen to InventoryClickEvent.

    Here's what you need to do:
    • Make sure that it is indeed a player clicking.
    • Make sure that the Inventory isn't null.
    • Make sure that the Inventory's name is equal to the one you created earlier.
    • Make sure that the player is right clicking.
    • Optional: Cancel the event if you don't want the player to be able to take the item out.
    • THEN, you can now do whatever you want to do.
    Here's an example of what that could look like, but I strongly encourage you to find your own approach and code it in yourself rather than copy and pasting, because that's how you'll learn.
    Code (Java):
    @EventHandler
    public void onInventoryClick(InventoryClickEvent event) {
        if (event.getWhoClicked() instanceof Player) {
            Player player = (Player) event.getWhoClicked();
            if (event.getClickedInventory() != null) {
                if (event.getView().getTitle().equals("My Epic Inventory")) {
                    if (event.isRightClick()) {
                        event.setCancelled(true);
                        PianoManager.play(player, event.getCurrentItem(), false);
                    }
                }
            }
        }
    }
     
    #2 TehBrian, Feb 24, 2020
    Last edited: Feb 24, 2020
    • Like Like x 1
    • Informative Informative x 1
  3. Thanks for the informative response.
    In addition, is there a way to create an inventory the size of one large chest (54 slots)? The InventoryType enum does not seem to have a value for that.
     
  4. You just switch the size to it,thats the max amount anyway
     
    • Like Like x 1
  5. Re-read the first block of code I posted. I edited my comment so that it's a bit easier to understand. That should answer your question.
     
    • Like Like x 1
  6. My apologies, I didn't see the overloaded variant of Bukkit::createInventory.
     
    • Like Like x 1
  7. Also for future help(you will most likely need it)
    [​IMG]
     
    • Like Like x 2
  8. By the way, is there an alternative approach in determining whether the inventory is yours rather than title comparison?
    I am seeing that with multiple plugins, the title of the inventories might not be unique (title is a display text, not unique ID after all), and therefore might cause conflicts with other plugins?
     
  9. global defined inventory,then with the usage of if(e.getInventory().equals(object)


    pseudo
    Code (Text):
    private Inventory shopInv = Bukkit.createInventory(null,54,"Title");


    public void event(InventoryClickEvent e){
    if(e.getInventory().equals(shopInv){
    stuff..
    }
    }
     
    • Like Like x 1
  10. You could also do something with the InventoryHolder, but that's technically dEpReCaTeD.

    Currently there's no good solution to this other than text checking because Spigot decided that the only other method was bad and deprecated, but then they gave us no alternatives ._.
     
  11. Theres many reasons why InventoryHolder is deprecated and bad programming practice. Anyway, as mentioned before,
     
    • Like Like x 1
  12. I get that InventoryHolder is bad practice and all, I don't mind that being deprecated. But then Spigot gave us no other alternatives to just checking the Inventory's name, and that's a bad idea because players could edit the inventory name in an anvil, or what if there are colors in the name, among other things.
     
  13. Btw, player cannot rename your coded inventory. That is impossible. About the colors and among other things, if you are a programmer you should consider the user end a total idiot and prepare your code based on every possible error.
     
    • Useful Useful x 1
  14. Never said they could rename your coded inventory, but they can rename a chest or dispenser or any item in an anvil and change the Inventory's name that way, which could result in exploits.
     
  15. Probably the best, non-deprecated way is to store every active inventory in some sort of collection and then check if said collection contains the inventory. Obviously there is the typical memory-leakage-problem, but I believe that this can be avoided by just removing the inventory at the right point (or using a weak HashMap after all)
     
  16. Yeah that's essentially what Stellrow said. I still don't feel like it's the best solution.
     
  17. In vanilla spigot, they certainly cannot use color codes in the anvil
     
  18. I suppose you could add &r to the beginning of all inventory names, but I still don't think that this is an ideal solution.