[Tutorial] Multi-Page GUI/Menu

Discussion in 'Plugins' started by tchristofferson, Oct 13, 2017.

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

    tchristofferson Developer Premium

    Messages:
    74
    Reactions:
    +11
    Introduction
    This is a tutorial on how to make multi-paged inventory GUIs if you couldn't tell from the title. This tutorial will also teach you how to cycle through inventories like a boss!

    Steps
    1. We need to create an array list to store our inventories. Note that array lists keep their order so it makes it perfect for a multi-paged menu/GUI.
      Code:
      List<Inventory> inventories = new ArrayList<>();
    2. The next step is to figure out how many slots you want your inventories to have. Note, the size of the inventories must be a multiple of 9 (1 row) and no more than 54. Store the number in a variable called invSize or whatever you wish to name it.
      Code:
      int invSize = 18;
    3. Now that we know what size our inventories need to be, we now need to know how many inventories to create. If the number of items that are going into the menu can change you need to create a flexible amount of inventories, otherwise you may run out of inventory space. Let's say we need to add player heads to the inventories for a bounty plugin and you have an array list of item stacks(player heads). To get the number of inventories create a new variable like so:
      Code:
      int neededInventories = ((int) Math.ceil(heads.size() / invSize));
      This will give you the number of inventories you need. Math.ceil will round your input up. If your neededInventories is 0 set it equal to 1.
    4. Now comes the fun part, creating the inventories! To create the inventories just create a simple loop:
      Code:
      for (int i = 0; i < neededInventories; i++) {
                  
                  Inventory inv = Bukkit.createInventory(null, invSize, "title");
                  inventories.add(inv);
                  
      }
    5. Great! Now we need to add navigation to switch between pages. Yes, you could have done it in the previous step but I am just going to do it in a separate step so the tutorial isn't too clustered. We will loop through each inventory and add 3 buttons(previous page, close menu, and next page).
      Code:
      for (Inventory inv : inventories) {
      
          ItemStack previous = new ItemStack(Material.SKULL_ITEM, 1);
          ItemMeta previousMeta = previous.getItemMeta();
          previousMeta.setDisplayName(ChatColor.GOLD + "<< Previous Page");
          previous.setItemMeta(previousMeta);
      
          ItemStack close = new ItemStack(Material.BARRIER, 1);
          ItemMeta closeMeta = close.getItemMeta();
          closeMeta.setDisplayName(ChatColor.RED + "Close Menu");
          close.setItemMeta(closeMeta);
      
          ItemStack next = new ItemStack(Material.SKULL_ITEM, 1);
          ItemMeta nextMeta = next.getItemMeta();
          nextMeta.setDisplayName(ChatColor.GOLD + "Next Page >>");
          next.setItemMeta(nextMeta);
      
          inv.setItem(9, previous);
          inv.setItem(13, close);
          inv.setItem(17, next);
      
      }
      
      What I did above is for every inventory it will add the 3 buttons. Remember that inventory slots are 0 based, meaning the first slot is 0, the second is 1, the third is 2, and so on.
    6. Now that we have the navigation in our pages we need a way to open the menu. For this, we need to have a player variable. Once we have a player variable all we need to do is call the open inventory method.
      Code:
      player.openInventory(inventories.get(0));
    7. Create a listener to handle an event called InventoryClickEvent. If the item they clicked is the next button call the close inventory method on the player and then call the open inventory and pass in inventories.get(inventories.indexOf(clicked inv) + 1). Do the same thing for the previous button except subtract 1 instead of adding. Also, something very important to keep in mind is that eventually someone may click the next/previous button while they are on the last/first page. This will cause an error. Make sure you the player is not on the last/first page.
    I hope this helped someone out there! When I first started doing this it took me a while to figure out because of how few tutorials there are on multi-paged menus. There are plenty of tutorials out there explaining the event used above, all you need to do is a quick search for it on google.
     
    Last edited: Oct 13, 2017
    • Winner Winner x 2
    • Useful Useful x 2
  2. Tig3ax

    Tig3ax Member

    Minecraft Accounts: Tig3ax Trudged
    Messages:
    218
    Reactions:
    +41
    Awseome tutorial. But using your example. How do i make the player heads continue on the second page where it would have stopped on the first one?
     
  3. OP
    OP
    tchristofferson

    tchristofferson Developer Premium

    Messages:
    74
    Reactions:
    +11
    If for example, your inventories are 54 slots you don't want to fill the bottom row with heads because that is where your navigation buttons will be. That being said just add another for loop inside the loop where I added the buttons. Make it loop 45 times(all rows but the bottom) for each inventory and have a variable that keeps track of the page you are on, so you don't put the same heads on the pages.
     
  4. Tig3ax

    Tig3ax Member

    Minecraft Accounts: Tig3ax Trudged
    Messages:
    218
    Reactions:
    +41
    Alright but then for the second page, how do i tell the loop to start at 46?
     
  5. OP
    OP
    tchristofferson

    tchristofferson Developer Premium

    Messages:
    74
    Reactions:
    +11
    Forget my last reply have a variable outside both loops and increase it every time you loop through the heads. That will give you the index you need for the item stack array list(player heads).
     
  6. felldownstairs

    felldownstairs Gypsy Boy | Java Developer Supreme Premium

    Minecraft Accounts: felldownstairs
    Messages:
    804
    Reactions:
    +142
    Thank you for this a lot. But say I did a for method for online players, how would I continue on then next invs?
     
  7. Ambrosia

    Ambrosia hmmmm Premium

    Messages:
    2,555
    Reactions:
    +1,245
    Can't you use pagedpanes?
     
  8. OP
    OP
    tchristofferson

    tchristofferson Developer Premium

    Messages:
    74
    Reactions:
    +11
    You would just loop through all online players instead of the item stack array list as shown above. Use Bukkit.getOnlinePlayers()
     
  9. LuckyLuckiest

    LuckyLuckiest Member

    Messages:
    1
    Reactions:
    +0
    I have two questions.
    How to switch to the previous page or next page, and How to check that the player is on the last page?
    Switch to previous page example:
    I'm on page 3 and I want to go to page 2.
    Switch to next page example:
    I'm on page 2 and I want to go to page 3.
    How to do those steps?

    Code:
    if (e.getInventory( ).getName( ).equals(invName)) {
                    // if (e.getSlot( ) == 45) switchPages(p, inventories.get());
                }
     
    Last edited: Jan 26, 2018
  10. valaiyar

    valaiyar Top 100 DPS Player - Java Developer Banned Premium

    Messages:
    737
    Reactions:
    +253
    Just use abstract guis.

    Before he passed, shortninja posted this video:

    Really useful and I use it for most of my GUIs, some of the code in the video needs some improvement, but you should be able to find it out yourself.

    You could have another Object for the player's current page, or even store what page they are in the abstract GUI, not that hard.
     
    Banned Forever For: Scamming, (https://www.mc-market.org/threads/407162/)
  11. OP
    OP
    tchristofferson

    tchristofferson Developer Premium

    Messages:
    74
    Reactions:
    +11
    I make an object that holds a list of inventories and put it in a hashmap with the player that is opening the inventory as the key. Then I use the list’s index of method for switching pages. Then remove the player from the hashmap when they close inventory
     
    Last edited: Jan 26, 2018
Thread Status:
Not open for further replies.