Hello everyone! So I have been helping lots of new bukkit developers and some not so new recently with creating interactive menus that have submenus or other functionality. So I decided to release some code from a plugin I made a while ago to hope it helps those bukkit members trying to look for a solution/figure out how it works. Keep in mind this is how I decided to go about making an interactive menu and I am sure there is plenty of different solutions to this idea. Sorry for rambling but here is the classes you will need. Menu: https://gist.github.com/anonymous/93cfe1803e2be9adb0ed Menu Item: https://gist.github.com/anonymous/3173707c7ee8135269e6 IMenuItemClickHandler: https://gist.github.com/anonymous/1114ff22fff83ae9c38b GoToSubMenuHandler: https://gist.github.com/anonymous/3d3fab335ff279d358cd MenuListener (This class was modified by adding in TestInteractivePlugin instance so testing could be done through fake command): Code:java import org.bukkit.ChatColor;import org.bukkit.entity.HumanEntity;import org.bukkit.entity.Player;import org.bukkit.event.EventHandler;import org.bukkit.event.Listener;import org.bukkit.event.inventory.InventoryAction;import org.bukkit.event.inventory.InventoryClickEvent;import org.bukkit.event.inventory.InventoryType.SlotType;import org.bukkit.event.player.PlayerCommandPreprocessEvent;import org.bukkit.inventory.Inventory; public class MenuListener implements Listener{ private TestInteractiveMenuPlugin plugin; public MenuListener(TestInteractiveMenuPlugin plugin) { this.plugin = plugin; } @EventHandler public void onInventoryClick(InventoryClickEvent event) { // Get the inventory we are working with Inventory inventory = event.getInventory(); // Get the type of action that occurred InventoryAction actionType = event.getAction(); // Check to make sure its our Menu has the holder of the inventory if (!(inventory.getHolder() instanceof Menu)) return; // Make sure the human does not try and shift click if (actionType.equals(InventoryAction.MOVE_TO_OTHER_INVENTORY)) { event.setCancelled(true); return; } HumanEntity human = event.getWhoClicked(); // Get the menu we are working with from inventory holder through // casting Menu menu = (Menu) inventory.getHolder(); // Check if this menu should be closed when clicking outside inventory // frame if (menu.closeOnClickOutside() && event.getSlotType().equals(SlotType.OUTSIDE)) { menu.close(human); return; } // Now lets check to make sure the player is not clicking outside our // interactive menu by comparing the raw slot to the actual size of the // inventory. if (menu.getSize() <= event.getRawSlot()) return; // We only cancel after the check above to make sure the player clicked // in our inventory event.setCancelled(true); // Lets make sure for the onClick we are working with a player if (!(human instanceof Player)) return; // We are all set to call the onClick method for menu! Player player = (Player) human; menu.onClick(player, actionType, event.getSlot()); } // This event below is for opening the menu for testing purposes. The event // is not actually needed for the menu to work properly. @EventHandler public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { Player player = event.getPlayer(); String message = event.getMessage(); if (message.startsWith("/")) { message = message.replaceFirst("/", ""); if (message.equalsIgnoreCase("testmenu")) { event.setCancelled(true); plugin.getMenu().open(player); player.sendMessage(ChatColor.GREEN + "Opening test menu..."); return; } } }} Now that all of that code is out of the way, we can finally make some menus! Sorry for not typing up a tutorial through the post but I rather tried to do it through comments in this test plugin class file: Code:java import java.util.Arrays;import java.util.List; import org.bukkit.ChatColor;import org.bukkit.Material;import org.bukkit.entity.Player;import org.bukkit.event.HandlerList;import org.bukkit.event.inventory.InventoryAction;import org.bukkit.inventory.ItemStack;import org.bukkit.inventory.meta.ItemMeta;import org.bukkit.plugin.java.JavaPlugin; public class TestInteractiveMenuPlugin extends JavaPlugin{ private Menu menu; public Menu getMenu() { return menu; } @Override public void onDisable() { // We check all the players online to make sure they do not have an open // menu or else after a reload they could steal items for (Player online : getServer().getOnlinePlayers()) { if (online.getOpenInventory().getTopInventory().getHolder() instanceof Menu) { online.closeInventory(); } } menu.cleanUp(); menu = null; HandlerList.unregisterAll(this); } @Override public void onEnable() { getServer().getPluginManager().registerEvents(new MenuListener(this), this); // Initiates our Menu object this.menu = new Menu(ChatColor.GREEN + "Interactive Menu", 2); menu.setCloseOnClickOutside(true); // Creating our menu item to add to the menu we just made. This menu // item will give the players diamonds every time the diamond is // clicked. ItemStack freeDiamondsIcon = createItemStack(Material.DIAMOND, 64, ChatColor.AQUA + "Click 4 Diamonds", Arrays.asList(ChatColor.YELLOW + "Its so....shinny!")); MenuItem freeDiamondsMenuItem = new MenuItem(freeDiamondsIcon); freeDiamondsMenuItem.setCloseOnSelection(true); freeDiamondsMenuItem.setClickHandler(new IMenuItemClickHandler() { @Override public void onClick(MenuItem menuItem, Player player, InventoryAction action) { ItemStack diamonds = new ItemStack(Material.DIAMOND); diamonds.setAmount(64); player.getInventory().addItem(diamonds); player.sendMessage(ChatColor.GREEN + "For being a nice tester here is some diamonds!"); } }); menu.addItem(0, freeDiamondsMenuItem); // Have you ever wondered how to make sub-categories for interactive // menus? // Well, today is your lucky day. We are going to make a sub-menu that // can give us other itemstacks like dirt! There will also be buttons to // get to the sub menu and back. Menu subMenu = new Menu(menu, ChatColor.GREEN + "Sub Menu", 2); subMenu.setCloseOnClickOutside(true); ItemStack subMenuIcon = createItemStack( Material.GOLD_BLOCK, 1, ChatColor.GOLD + "Rares Category", Arrays.asList(ChatColor.LIGHT_PURPLE + "All the best gems in Minecraft!")); MenuItem goToSubMenuItem = new MenuItem(subMenuIcon); goToSubMenuItem.setClickHandler(new GoToSubMenuHandler(subMenu)); // Adding the go to sub menu item to the parent menu menu.addItem(1, goToSubMenuItem); ItemStack backToParentIcon = createItemStack(Material.REDSTONE_BLOCK, 1, ChatColor.RED + "Back to parent", Arrays.asList(ChatColor.DARK_AQUA + "Leaves current menu!")); MenuItem backToParentMenuItem = new MenuItem(backToParentIcon); backToParentMenuItem.setClickHandler(new IMenuItemClickHandler() { @Override public void onClick(MenuItem item, Player player, InventoryAction action) { if (item.getMenu().hasParent()) { player.closeInventory(); item.getMenu().getParent().open(player); } } }); // Adding the menu item to get back to the original menu subMenu.addItem(17, backToParentMenuItem); ItemStack freeDirtIcon = createItemStack(Material.DIRT, 64, ChatColor.GREEN + "Free Dirt", Arrays.asList(ChatColor.GOLD + "My favorite!")); MenuItem freeDirtMenuItem = new MenuItem(freeDirtIcon); freeDirtMenuItem.setCloseOnSelection(true); freeDirtMenuItem.setClickHandler(new IMenuItemClickHandler() { @Override public void onClick(MenuItem item, Player player, InventoryAction action) { ItemStack dirt = new ItemStack(Material.DIRT); dirt.setAmount(64); player.getInventory().addItem(dirt); player.sendMessage(ChatColor.GREEN + "You have recieved from free dirt! Awesome :D"); } }); subMenu.addItem(0, freeDirtMenuItem); } public ItemStack createItemStack(Material material, int amount, String displayName, List<String> lore) { ItemStack itemstack = new ItemStack(material); itemstack.setAmount(amount); ItemMeta itemMeta = itemstack.getItemMeta(); itemMeta.setDisplayName(displayName); itemMeta.setLore(lore); itemstack.setItemMeta(itemMeta); return itemstack; }} I hope this helps you guys and here is some pictures from the menu in this example! (Just tag me and I will be happy to answer questions) Please leave a like!
I have not gone through your code, but are you basically just giving the player a menu, and when he right clicks on an item in the menu, it closes it and opens another one? If so, this can easily be done with IconMenu. Nice work though.
BungeeTheCookie IconMenu is also a way of doing interactive menus. IconMenu basically accomplishes the same thing just a little different. I wanted to be able to show other functionality like closing when clicking outside of the inventory and the simplicity of making a sub-menu (Forgot to mention the unregister all is not needed on disable. I honestly do not know how I accidentally put that code there).
I can see where you are coming from, but IconMenu can do the same thing. I am not trying to put your resource down, but try putting your time into something more unique than this. Great job though
Muhammadazka You make it so on click of a specific item you define you close the player's current inventory and then display another menu. I show how to do sub-menus with my classes above.
MCForger How do I set the position of a item in the menu? EDIT: lol scrolled down and saw where to do it xD Thanks!