Util Create scrollable inventories

Discussion in 'Resources' started by The_Spaceman, Dec 11, 2019.

  1. Offline

    The_Spaceman

    Hello,

    I've created a dynamical scrollable inventory methods.
    I'm not saying that this is the best, but it works.
    I've actually not tried changing the 'rows', 'width' and 'skipPerPage', but I'm somewhat sure that it works. If not you can let me know.

    'int page' starts at 0 and its displayed as page 1;
    'String name' is the name of the inventory;
    'List<ItemStack>' are ALL the items;
    'ItemStack backButton' is the back button to go back, when 'null' there won't be any

    This will automatically place an previous item and a next item

    The code:
    Code:java
    1. import org.bukkit.Bukkit;
    2. import org.bukkit.ChatColor;
    3. import org.bukkit.Material;
    4. import org.bukkit.entity.Player;
    5. import org.bukkit.event.EventHandler;
    6. import org.bukkit.event.Listener;
    7. import org.bukkit.event.inventory.InventoryAction;
    8. import org.bukkit.event.inventory.InventoryClickEvent;
    9. import org.bukkit.inventory.Inventory;
    10. import org.bukkit.inventory.ItemStack;
    11. import org.bukkit.inventory.meta.ItemMeta;
    12.  
    13. import javax.annotation.Nullable;
    14. import java.util.ArrayList;
    15. import java.util.List;
    16.  
    17. public class DynamicInventory {
    18.  
    19. public static String NEXT = ChatColor.YELLOW + "Next";
    20. public static String PREVIOUS = ChatColor.YELLOW + "Previous";
    21. public static String BACK = ChatColor.YELLOW + "Back";
    22.  
    23. private static ItemStack createStack(String displayName, Material material) {
    24. ItemStack is = new ItemStack(material);
    25.  
    26. ItemMeta im = is.getItemMeta();
    27. im.setDisplayName(displayName);
    28. is.setItemMeta(im);
    29. return is;
    30. }
    31.  
    32. public static void openDynamicScrollableInventory(Player player, int page, String name, List<ItemStack> items, @Nullable ItemStack backButton) {
    33. player.openInventory(getDynamicScrollableInventory(page, name, items, backButton));
    34. }
    35.  
    36. public static Inventory getDynamicScrollableInventory(int page, String name, List<ItemStack> items, @Nullable ItemStack backButton) {
    37. int size = items.size();
    38.  
    39. int rows = 3; //amount of rows
    40. int width = 7; //amount of items in a row
    41. int skipPerPage = 7; //amount of items skipped per page (width * rows to skip)
    42.  
    43. //add max to GUI page
    44. if (size > rows * width) {
    45. page = Math.min(size / width - rows + (size % width == 0 ? 0 : 1), page);
    46. } else {
    47. page = 0;
    48. }
    49. page = Math.max(0, page); //set min to page
    50.  
    51. size += (width - (size - 1) % width); //calculate square rectangle items
    52. size /= width; //get amount of rows
    53. if (size > rows) {
    54. size -= (size - rows); //set a max on 3 rows
    55. }
    56. size *= 9; //turn rows into slots
    57. size += 18; //add top and bottom row
    58.  
    59. Inventory inv = Bukkit.createInventory(null, size, name + " (" + (page + 1) + ")");
    60.  
    61. int a = page * skipPerPage; //amount to skip
    62.  
    63. int slot = 9 + (9 - width) / 2;
    64. for (int index = a; index < a + width * rows && index < items.size(); index++) {
    65. if ((slot + 1) % 9 == 0) { //end of row, +2 to go to next row
    66. slot += (9 - width);
    67. }
    68. if (slot >= size - 9) { //end of items
    69. break;
    70. }
    71. inv.setItem(slot, items.get(index)); //add item
    72. slot++; //next slot
    73. }
    74.  
    75. if (backButton != null) {
    76. inv.setItem(size / 18 * 9 + 8, backButton);
    77. }
    78.  
    79. if ((page + rows) * width < items.size()) { //if not all items could be displayed, add next 'button'
    80. inv.setItem(size - 1, createStack(NEXT, Material.HOPPER));
    81. }
    82. if (page != 0) { //if not at page 0 (1 as display) add previous 'button'
    83. inv.setItem(8, createStack(PREVIOUS, Material.FERN));
    84. }
    85. return inv;
    86. }
    87.  
    88. public static class ClickEvent implements Listener {//todo register class
    89.  
    90. @EventHandler
    91. public void dynamicInventoryClick(InventoryClickEvent e) {
    92. Player player = (Player) e.getWhoClicked();
    93. Inventory inv = e.getInventory();
    94. String invTitle = e.getView().getTitle();
    95.  
    96. if (e.getRawSlot() > inv.getSize()) {
    97. return;
    98. }
    99.  
    100. ItemStack item = e.getCurrentItem();
    101. if (item == null) {
    102. return;
    103. }
    104.  
    105. ItemMeta meta = item.getItemMeta();
    106. if (meta == null) {
    107. return;
    108. }
    109. if (!meta.hasDisplayName()) {
    110. return;
    111. }
    112.  
    113. if (invTitle.startsWith("Your inventory name ")) {
    114. String pageNumber = invTitle.replace("Your inventory name ", "").replace("(", "").replace(")", "");
    115. if (meta.getDisplayName().equals(NEXT)) {
    116. e.setCancelled(true);
    117. //todo set your inventory
    118. openDynamicScrollableInventory(player, Integer.parseInt(pageNumber), "Your inventory name ", new ArrayList<>()/*your items*/, createStack(BACK, Material.BARRIER));
    119. }
    120.  
    121. if (meta.getDisplayName().equals(PREVIOUS)) {
    122. e.setCancelled(true);
    123. //todo set your inventory
    124. openDynamicScrollableInventory(player, Integer.parseInt(pageNumber) - 2, "Your inventory name ", new ArrayList<>()/*your items*/, createStack(BACK, Material.BARRIER));
    125. }
    126.  
    127. //back button
    128. if (item.getType().equals(Material.BARRIER)) {
    129. if (meta.getDisplayName().equals(BACK)) {
    130. e.setCancelled(true);
    131. if (e.getAction().equals(InventoryAction.PICKUP_HALF)) {//right lick
    132. //todo do something when the player right clicks
    133. } else if (e.getAction().equals(InventoryAction.PICKUP_ALL)) {//left click
    134. //todo do something when the player left clicks
    135. } else if (e.getAction().equals(InventoryAction.CLONE_STACK) || e.getAction().equals(InventoryAction.UNKNOWN)) {//middle click
    136. //todo do something when the player middle clicks (InventoryAction.UNKNOWN added for when the player has remapped his button to something else (like the button 'F'))
    137. }
    138. return;
    139. }
    140. }
    141. }
    142. }
    143.  
    144. }
    145. }
    146.  
    147.  
     
    Last edited: Dec 12, 2019
    MCMastery likes this.
  2. Offline

    KarimAKL

    @The_Spaceman
    You accidentally typed "rivate" instead of "private" as the access modifier for the "createStack" method.

    Some feedback:
    1. I'd probably type all of this in 1 file, with the InventoryClickEvent being in a static class inside the upper class. (And make it so that it won't interfere with another InventoryClickEvent (at least to some extend, as the user can edit it themselves))
    2. I'd also like this better if it included the imports for the file.
    3. This is a minor thing but, a reminder that people still need to register the InventoryClickEvent.
     
  3. Offline

    The_Spaceman

    Thanks for your feedback, I've put it all there
     

Share This Page