[Tutorial] Create a Inventory Menu!

Discussion in 'Resources' started by JPG2000, Sep 8, 2013.

Thread Status:
Not open for further replies.
  1. Offline

    JPG2000

    ABOUT: When I say "Inventory Menu", I mean, a custom inventory, with custom items. Diffirent things happen, when diffirent items are clicked. This tutorial covers creating a inventory, using the inventory click event, and assigning items.

    * This tutorial is for less expierenced developers. This is very easy to do, as long as you've done it once or twice before.
    Part 1: Creating a inventory.
    I am going to create a inventory, name "My custom Inventory", and have it have 9 slots.
    Code:java
    1. public static Inventory myInventory = Bxukkit.createInventory(null, 9, "My custom Inventory!");
    2. // The first parameter, is the inventory owner. I make it null to let everyone use it.
    3. //The second parameter, is the slots in a inventory. Must be a multiple of 9. Can be up to 54.
    4. //The third parameter, is the inventory name. This will accept chat colors.

    NOTE: I made the inventory public and static so that we can access it from diffirent classes.
    With this inventory set up, the inventory will be set up. For the next part, this has to be Static.
    I am going to To assign 3 items to the inventory!
    Code:java
    1. static {
    2. myInventory.setItem(0, new ItemStack(Material.DIRT, 1));
    3. myInventory.setItem(8, new ItemStack(Material.GOLD_BLOCK, 1));
    4. //The first parameter, is the slot that is assigned to. Starts counting at 0
    5. }


    Part 2: Inventory click events.
    Create the event, with a couple of variables:
    Code:java
    1. public void onInventoryClick(InventoryClickEvent event) {
    2. Player player = (Player) event.getWhoClicked(); // The player that clicked the item
    3. ItemStack clicked = event.getCurrentItem(); // The item that was clicked
    4. Inventory inventory = event.getInventory(); // The inventory that was clicked in
    5. }


    Lets now check if the inventory is equal to our custom inventory, so the code only happens if its in our inventory.

    IMPORTANT: You have to check the names

    Code:java
    1.  
    2. @EventHandler
    3. public void onInventoryClick(InventoryClickEvent event) {
    4. Player player = (Player) event.getWhoClicked(); // The player that clicked the item
    5. ItemStack clicked = event.getCurrentItem(); // The item that was clicked
    6. Inventory inventory = event.getInventory(); // The inventory that was clicked in
    7. if (inventory.getName().equals(myInventory.getName())) {
    8.  
    9. }
    10. }



    Finally, lets check if the clicked item is equal to dirt. If so, lets cancel the event, and give the player a piece of dirt!

    Code:java
    1.  
    2. @EventHandler
    3. public void onInventoryClick(InventoryClickEvent event) {
    4. Player player = (Player) event.getWhoClicked(); // The player that clicked the item
    5. ItemStack clicked = event.getCurrentItem(); // The item that was clicked
    6. Inventory inventory = event.getInventory(); // The inventory that was clicked in
    7. if (inventory.getName().equals(myInventory.getName())) { // The inventory is our custom Inventory
    8. if (clicked.getType() == Material.DIRT) { // The item that the player clicked it dirt
    9. event.setCancelled(true); // Make it so the dirt is back in its original spot
    10. player.closeInventory(); // Closes there inventory
    11. player.getInventory().addItem(new ItemStack(Material.DIRT, 1)); // Adds dirt
    12. }
    13. }
    14. }



    OPTIONAL: To quickly make the player open the inventory:
    Code:java
    1. player.openInventory(myInventory);



    To see it all in action an working, I made a little class for this:
    http://pastebin.com/yv1zkfNw

    Thanks!
    - Jake



    EDIT: For assigning custom itemstacks to inventorys, I made a quick method for dis:

    Code:java
    1.  
    2. public static void createDisplay(Material material, Inventory inv, int Slot, string name, string lore) {
    3. ItemStack item = new ItemStack(material);
    4. ItemMeta meta = item.getItemMeta();
    5. meta.setDisplayName(name);
    6. ArrayList<String> Lore = new ArrayList<String>();
    7. Lore.add(lore);
    8. meta.setLore(Lore);
    9. item.setItemMeta(meta);
    10.  
    11. inv.setItem(Slot, item);
    12.  
    13. }
    14.  
     
    Prex, ProGreenLt, megasaad44 and 14 others like this.
  2. Offline

    CaptainBern Retired Staff

  3. Offline

    bloodless2010

    Just a heads up; There's a duplication glitch in bukkit if you open a Inventory Menu twice in the same tick, it allows you to take the items out. Maybe you might wanna fix this? (Perfect way to test is to set it to 2 commands and use essentials powertool with both the commands (i.e /powertool menu and /powertool a:menu2) I tried multiple things to stop this (It's still possible to achieve without powertool - Just powertool is a great way to do the thing) but I still couldn't fix it, any ideas? ;)
     
  4. Offline

    JPG2000

    bloodless2010 Hm. Well, an idea to fix this would be to add a player to an array list, when he closes the invenory remove him, and before he opens it it checks if hes in the array list
     
  5. Offline

    bloodless2010

    JPG2000 I tried that, it didn't work.
     
  6. Offline

    remremrem

    Someone suggested to me to use a cooldown for this issue. Now I use a BukkitRunnable to place players in an array list for 3 seconds.
     
  7. Offline

    JPG2000

    remremrem Yeah.

    I don't know why my arraylist idea would work. Think about the logic, theres no way it can mess up. I'll debug it later.
     
    KingFaris11 likes this.
  8. Offline

    Ultimate_n00b

    Code:java
    1. import java.util.ArrayList;
    2. import java.util.Arrays;
    3. import java.util.List;
    4.  
    5. import org.bukkit.Bukkit;
    6. import org.bukkit.Material;
    7. import org.bukkit.entity.Player;
    8. import org.bukkit.event.EventHandler;
    9. import org.bukkit.event.Listener;
    10. import org.bukkit.event.inventory.InventoryClickEvent;
    11. import org.bukkit.event.inventory.InventoryCloseEvent;
    12. import org.bukkit.event.server.PluginDisableEvent;
    13. import org.bukkit.inventory.Inventory;
    14. import org.bukkit.inventory.ItemStack;
    15. import org.bukkit.inventory.meta.ItemMeta;
    16.  
    17. public class IconMenu implements Listener {
    18.  
    19. private String name;
    20. private int size;
    21. private onClick click;
    22. List<String> viewing = new ArrayList<String>();
    23.  
    24. private ItemStack[] items;
    25.  
    26. public IconMenu(String name, int size, onClick click) {
    27. this.name = name;
    28. this.size = size * 9;
    29. items = new ItemStack[this.size];
    30. this.click = click;
    31. Bukkit.getPluginManager().registerEvents(this, Bukkit.getPluginManager().getPlugins()[0]);
    32. }
    33.  
    34. @EventHandler
    35. public void onPluginDisable(PluginDisableEvent event) {
    36. for (Player p : this.getViewers())
    37. close(p);
    38. }
    39.  
    40. public IconMenu open(Player p) {
    41. p.openInventory(getInventory(p));
    42. viewing.add(p.getName());
    43. return this;
    44. }
    45.  
    46. private Inventory getInventory(Player p) {
    47. Inventory inv = Bukkit.createInventory(p, size, name);
    48. for (int i = 0; i < items.length; i++)
    49. if (items[i] != null)
    50. inv.setItem(i, items[i]);
    51. return inv;
    52. }
    53.  
    54. public IconMenu close(Player p) {
    55. if (p.getOpenInventory().getTitle().equals(name))
    56. p.closeInventory();
    57. return this;
    58. }
    59.  
    60. public List<Player> getViewers() {
    61. List<Player> viewers = new ArrayList<Player>();
    62. for (String s : viewing)
    63. viewers.add(Bukkit.getPlayer(s));
    64. return viewers;
    65. }
    66.  
    67. @EventHandler
    68. public void onInventoryClick(InventoryClickEvent event) {
    69. if (viewing.contains(event.getWhoClicked().getName())) {
    70. event.setCancelled(true);
    71. Player p = (Player) event.getWhoClicked();
    72. Row row = getRowFromSlot(event.getSlot());
    73. if (!click.click(p, this, row, event.getSlot() - row.getRow() * 9, event.getCurrentItem()))
    74. close(p);
    75. }
    76. }
    77.  
    78. @EventHandler
    79. public void onInventoryClose(InventoryCloseEvent event) {
    80. if (viewing.contains(event.getPlayer().getName()))
    81. viewing.remove(event.getPlayer().getName());
    82. }
    83.  
    84. public IconMenu addButton(Row row, int position, ItemStack item, String name, String... lore) {
    85. items[row.getRow() * 9 + position] = getItem(item, name, lore);
    86. return this;
    87. }
    88.  
    89. public Row getRowFromSlot(int slot) {
    90. return new Row(slot / 9, items);
    91. }
    92.  
    93. public Row getRow(int row) {
    94. return new Row(row, items);
    95. }
    96.  
    97. public interface onClick {
    98. public abstract boolean click(Player clicker, IconMenu menu, Row row, int slot, ItemStack item);
    99. }
    100.  
    101. public class Row {
    102. private ItemStack[] rowItems = new ItemStack[9];
    103. int row;
    104.  
    105. public Row(int row, ItemStack[] items) {
    106. this.row = row;
    107. int j = 0;
    108. for (int i = (row * 9); i < (row * 9) + 9; i++) {
    109. rowItems[j] = items[i];
    110. j++;
    111. }
    112. }
    113.  
    114. public ItemStack[] getRowItems() {
    115. return rowItems;
    116. }
    117.  
    118. public ItemStack getRowItem(int item) {
    119. return rowItems[item] == null ? new ItemStack(Material.AIR) : rowItems[item];
    120. }
    121.  
    122. public int getRow() {
    123. return row;
    124. }
    125. }
    126.  
    127. private ItemStack getItem(ItemStack item, String name, String... lore) {
    128. ItemMeta im = item.getItemMeta();
    129. im.setDisplayName(name);
    130. im.setLore(Arrays.asList(lore));
    131. item.setItemMeta(im);
    132. return item;
    133. }
    134.  
    135. }[/i][/i][/i]

    Made this a while ago, and felt like sharing.
    Example Usage:

    Code:java
    1. IconMenu menu = new IconMenu("IconMenu", 2, new onClick() {
    2. @Override
    3. public boolean click(Player p, IconMenu menu, Row row, int slot, ItemStack item) {
    4. if(row.getRow() == 1){
    5. Bukkit.broadcastMessage(row.getRowItem(slot).getType().name());
    6. }
    7. return true;
    8. }
    9. });
    10. menu.addButton(menu.getRow(1), 0, new ItemStack(Material.STONE), "Stone Button ;)");
    11. menu.addButton(menu.getRow(1), 1, new ItemStack(Material.WOOD), "Wood Button ;)");
    12. menu.addButton(menu.getRow(1), 2, new ItemStack(Material.DIAMOND), "Diamond Button ;)");
    13. menu.addButton(menu.getRow(1), 3, new ItemStack(Material.GOLD_BLOCK), "Gold Button ;)");
    14. menu.addButton(menu.getRow(1), 4, new ItemStack(Material.IRON_BLOCK), "Iron Button ;)");
    15. menu.addButton(menu.getRow(1), 5, new ItemStack(Material.OBSIDIAN), "Obby Button ;)");
    16. menu.addButton(menu.getRow(1), 6, new ItemStack(Material.ANVIL), "Anvil Button ;)");
    17. menu.addButton(menu.getRow(1), 7, new ItemStack(Material.STONE_BUTTON), "Button Button ;)");
    18. menu.addButton(menu.getRow(1), 8, new ItemStack(Material.PORTAL), "Portal Button ;)");
    19. menu.open(p.getPlayer());


    A quick note about it, this doesn't do normal slot numbering. Instead it uses rows. Like you would get the row 1, and then item 5 instead of getting item 13.
     
  9. Offline

    viper_monster

    Ultimate_n00b, can we use "Bukkit.dispatchCommand(sender, commandLine)" somehow with your method?
     
  10. Offline

    Ultimate_n00b

    Code:
    IconMenu menu = new IconMenu("My Menu With Commands", 1, new onClick() {
        @Override
        public boolean click(Player p, IconMenu menu, Row row, int slot, ItemStack item) {
            if(item.getType().equals(Material.STONE))
              Bukkit.dispatchCommand(p, "command");
            return true;
        }
    });
    menu.addButton(menu.getRow(0), 0, new ItemStack(Material.STONE), "Stone Button");
    menu.open(player);
     
    spoljo666 likes this.
  11. Offline

    king_tnerb

    Great tutorial! I would like to point out however that the pastebin data is missing two closing parameters.
     
  12. Offline

    JPG2000

  13. Offline

    PieMan456

    JPG2000
    How would I make it so when they click on like a Diamond Block it opens the custom inventory?
     
  14. Offline

    JPG2000

    PieMan456 When you mean click on a diam block do you mean right click with a block in hand, or a block in a inventory?
     
  15. Offline

    PieMan456

    JPG2000
    On like hub servers you know how they have a book and you right click and it opens the inventory how do you do that?
     
  16. Offline

    JPG2000

    PieMan456 Well, you may want to learn a little more bukkit, but use the player interact event, then open up a custom inventory like in the tutorial.
    Code:java
    1. @EventHandler
    2. public void onPlayerInteract(PlayerInteractEvent event) {
    3. Player player = event.getPlayer(); //Player who 'interacted'
    4. if (player.getItemInHand() != null) { //Player is not holding air
    5. ItemStack item = player.getItemInHand(); //The item the players holding
    6. if (item.getType() == Material.BOOK) { //If the type of the item is a book
    7. //To sum up:
    8. //Player right/left clicked something
    9. //Player is holding something other then air
    10. //player is holding book
    11. //Now to open up invenory
    12. player.openInventory(customInventory); //NOTE, IF ITS NOT IN THIS CLASS USE: class_its_used_in.inventory_variable
    13. }
    14. }
    15. }
     
  17. Offline

    PieMan456

  18. Offline

    JPG2000

  19. Offline

    PieMan456

    JPG2000
    I also have another question for you. How would I make it since the items in the inventory are lore, how would i put them in the inventoryclickevent because they are in a different class thing?
     
  20. Offline

    JPG2000

    PieMan456 You mean how to check The lore of item clicked?

    for (ArrayList <String> Lore: event.getClickedItem ().getItemMeta ().getLore ()) {
    //Lore is each line
    }
     
  21. Offline

    PieMan456

    JPG2000
    No I will pm you soon to show you my code and what I am talking about
     
    JPG2000 likes this.
  22. Offline

    michael566

    Thanks amazing tutorial! :)

    JPG2000 How would you change the name of the block?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jan 16, 2016
  23. Offline

    Legocowchaser

    JPG2000 Thanks this was really helpful. I know this is not such a good question but I am not sure what to call it so I did not know how to look it up. Do I need to like register the inventory class in my Main class? How would I do that?

    JPG2000 How would I make an item enchanted?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jan 16, 2016
  24. Offline

    JPG2000

    Legocowchaser likes this.
  25. Offline

    Legocowchaser

    JPG2000 likes this.
  26. Offline

    michael566

    How do you rename the items?
     
  27. Offline

    JPG2000

    michael566 Set the item meta. I have a tutorial and resource in my signature
     
  28. Offline

    michael566

    Never mind figured it out myself.
     
  29. Offline

    TekkitSense

    I used your code and till didn't work, i can open the menu but when i click on the dirt it i can move it into my inv and i don't get one spawned in my inv eather
     
  30. Offline

    JPG2000

    TekkitSense Well, I can't help you unless you send me your code.

    Your obviously doing something wrong. My code works and runs. Im guessing you either need the @EventHandler above your InventoryClickEvent, or you didn't register it.

    Either way, send me your code.
     
Thread Status:
Not open for further replies.

Share This Page