API Easy Menu Maker API v2.1 (with Interfaces)

Discussion in 'Resources' started by 567legodude, Mar 19, 2015.

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

    567legodude

    I've seen people with tutorials on making an inventory menu, and also some plugins that let you create a menu from a config. But this is an API for developers that makes it easy to create menu's in their plugins.
    Normally you would have to create the inventory along with registering a listener to have the menu, but this API takes care of all that.
    The Menu maker will automatically handle creating the menu, registering the listener and also the event. So you just have to worry about customizing it the way you want it to look. The new version uses interfaces, so you can run any code you want when a player clicks an item.

    Download (New Version): http://pastebin.com/v1xY7T4x
    Changelog (open)
    Code:
    1.0:
    - General Menu Maker
    - (Pretty buggy)
    2.0:
    - Completely remade
    - Uses interfaces now
    2.1:
    - There is a third constructor to create just a menu without registering a listener.
    - Small improvements.
    - Deprecated methods to add ItemAction to slot.
    - - If you want to check a specific slot just use a global action with if (slot == 1)

    Creating a Menu
    Begin creating a menu like this:
    Creating a menu (open)

    Code:java
    1. Menu menu = new Menu(this, "Title", 3);
    2.  
    3. // this = Your main class (extends JavaPlugin)
    4. // "Title" = The title of the inventory
    5. // 3 = Number of rows in the inventory.
    6. // An ItemStack[] can be added as a fourth argument to set the contents of the menu when it is created.


    Adding Items
    Items can be added with the following methods.
    setContents (open)
    Code:java
    1. menu.setContents(ItemStack[] contents)
    2. // Set the inventory to some predefined contents.

    addItem (open)

    Code:java
    1. menu.addItem(ItemStack item)
    2. // adds an item to the next open slot in the inventory.

    setItem (open)

    Code:java
    1. menu.setItem(int slot, ItemStack item)
    2. // First slot is 0

    fill (open)

    Code:java
    1. menu.fill(ItemStack item)
    2. // Sets every item in the inventory to this item.

    fillRange (open)

    Code:java
    1. menu.fillRange(int, int, ItemStack)
    2. // fills the range of slots with the item


    This method was also created to ease the creating of itemstacks.
    createItem (open)

    Code:java
    1. //returns itemstack
    2. menu.createItem(Material m, int amount, String name, String lore, short durability)
    3.  
    4. // name and lore can be set to null if you want to use the default name and no lore.
    5. // lore - use "^$" to separate each line of the lore (Example: line1^$line2)
    6. // just use 0 for the durability unless you actually need it.
    7.  
    8. // for items with data (such as colored wool)
    9. menu.createItem(Material m, int amount, String name, String lore, short durability, byte data)


    Adding Actions
    ItemAction is an interface in the Menu class. With the method
    run(Player, Inventory, ItemStack, Integer)
    You use that to run your own code when something is clicked.
    setAction (open)
    Code:java
    1. menu.setAction(int, ItemAction)
    2. // set an ItemAction to run when a specific slot is clicked
    removeAction (open)
    Code:java
    1. menu.removeAction(int)
    2. // removes an ItemAction from the slot
    setGlobalAction (open)
    Code:java
    1. menu.setGlobalAction(ItemAction)
    2. // set the ItemAction to run when any slot is clicked.
    removeGlobalAction (open)
    Code:java
    1. menu.removeGlobalAction()
    2. // remove the global action
    EXAMPLE (open)
    Code:java
    1. menu.setGlobalAction(new Menu.ItemAction() {
    2. @Override
    3. public void run(Player player, Inventory inv, ItemStack item, int slot) {
    4. // this runs when a slot is clicked
    5. player.sendMessage("Item: " + item.getType().toString());
    6. }
    7. });

    If you don't want any ItemActions to run if the slot clicked is empty (includes clicking outside the inventory) you can do:
    menu.runWhenEmpty(false)

    Showing the Menu
    You can show the menu with this:
    getMenu (open)

    Code:java
    1. //returns Inventory
    2. menu.getMenu()

    showMenu (open)

    Code:java
    1. //opens menu for player
    2. menu.showMenu(Player player)


    Other Methods
    These are some other methods in the API
    nextOpenSlot (open)

    Code:java
    1.  
    2. menu.nextOpenSlot()
    3. // Returns next open slot in the inventory.


    And there are some other useful methods that may help you too.
    If you have any questions on how to use the API, then leave a comment.
     
    Last edited: Jun 13, 2015
  2. Offline

    teej107

    Replace the add/setCommands method to accept an Interface and where you would usually execute the command, have it call a method in that interface. This allows you to do much more than executing a command.
     
    Goblom and TwerkinCraft like this.
  3. Offline

    567legodude

    @teej107 What do you mean by accept an interface?
     
  4. Offline

    teej107

    @567legodude http://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html
    Most of the Bukkit API is made up of Interfaces.

    EDIT: Also you can condense your second constructor to this:
    Show Spoiler

    Code:
     public MenuMaker(JavaPlugin plugin, String title, int rows, ItemStack[] contents) throws IndexOutOfBoundsException {
                    this(plugin, title, rows);
                    setContents(contents)
            }
     
  5. Offline

    567legodude

    @teej107 I can't see a use for an interface in this specific case. (But I also dont know too much about them)
    If you could show a small example and I understand it, then I will implement it.
    I also edited the paste with your idea, thanks for that.

    EDIT: The way I have it set up is so that you could define all the commands and actions on a single string. I only did that to make it simple.
     
    Last edited: Mar 19, 2015
  6. Offline

    teej107

    @567legodude
    Here is an example of an interface to use:
    Code:
    public interface GuiClickListener
    {
        public void onClick(InventoryClickEvent event);
    }

    1. Change the values of your "contents" Map to the GuiClickListener Interface or Collection of the Interfaces.
    2. Change your add/setCommands method parameters to something like this
      Code:
      public addCommand(int i, GuiClickListener listener)
      and have it add the Interface to the Map
    3. Where you would call the runCommand method, have it call the interface's onClick method instead.
    In the Object that implements the Interface, you can do anything that you can do in code, including running commands.
     
    Last edited: Mar 19, 2015
  7. Offline

    567legodude

    @teej107 That seems like a lot more work than what I made, so I'm just gonna stick with what I have.
     
  8. Offline

    Pik0

    @567legodude Your API is kinda useless without the use of interfaces, but nice work anyways.
     
    ferrybig likes this.
  9. Offline

    567legodude

    @Pik0 That's only because you don't need an interface to do what I was trying to do.
    The way @teej107 was saying was to have me store an interface with each item. That's not helpful because the only thing that needs to be stored is the item and any commands that are run with it.

    @teej107 I tried making an interface and using that in the hashmap instead of the arraylist<object> but since I can't store values in the interface, it doesn't really work here. But as another thing, it is already extremely customizable even without an interface, so theres not too much I could add with an interface anyway.
     
    Last edited: Mar 20, 2015
  10. Offline

    nverdier

    @567legodude But what if a developer wants to use this, and do more than just a command when an item is clicked? You can't do that with the system you have setup. You should just use interfaces; It's not that hard to add!
     
  11. Offline

    teej107

    Replace
    with the interface and the method you call from the interface.

    You don't store values in an interface. You define methods in an interface which could return values if you set it up to do so. You can have any object you want implement the interface. Trust what the other users and I are saying. Using interfaces can make this resource a ton times more better.
     
  12. Offline

    567legodude

    @teej107 I tried making an interface and failed. Because I haven't done it before. I looked at a ton of pages explaining it, but since I don't know how to do it, I am unable to implement it.
    I understand how an interface works, that's not the problem; what I don't know is how to add it to my project.
     
  13. I am making a huge API this will definitely go in it!

    Well done @567legodude nice API.
     
  14. Offline

    567legodude

    @bwfcwalshy What kind of API is that, and how is this gonna help?
     
  15. Offline

    RainoBoy97

    @teej107 basically told you how to do it earlier.
     
  16. @567legodude My I makes making plugins very simple! Configs, arenas, menus, itemstacks etc
     
  17. Offline

    567legodude

    @RainoBoy97 In his example he just showed how to create an interface, not how I could add it to my class.
     
  18. Offline

    RainoBoy97

    Just create a new interface in your package?
     
  19. Offline

    567legodude

    @RainoBoy97 Right now I can only see an interface as just another class with the same methods I have now. I don't have any idea of what more I could add.
     
  20. Offline

    teej107

    @567legodude Here, I modified your InventoryClickEvent so it'll be interface friendly.
    GuiClickListener Interface (open)

    Code:
    import org.bukkit.entity.Player;
    import org.bukkit.inventory.Inventory;
    import org.bukkit.inventory.ItemStack;
    
    public interface GuiClickListener
    {
        public void onClick(Player player, Inventory inventory, int slot,
                ItemStack stack);
    }

    Modified onClick method (open)

    Code:
    @EventHandler
                public void onClick(InventoryClickEvent event)
                {
                    Inventory inv = event.getInventory();
                    Player player = (Player) event.getWhoClicked();
                    int slot = event.getRawSlot();
    
                    if (inv.getName().equals(title))
                    {
                        event.setCancelled(true);
    
                        if (slot <= (rows * 9) - 1)
                        {
                            if (closeonclick)
                            {
                                player.closeInventory();
                            }
                            GuiClickListener clickListener = content.get(slot);
                            if (clickListener != null)
                            {
                                clickListener.onClick(player, inv, slot,
                                        event.getCurrentItem());
                            }
                        }
                    }
                }

    With the modifications, you'll need to change the value type of your Map to the GuiClickListener interface as well with a few other modifications. I haven't tested this, but it should work.
     
  21. Offline

    567legodude

    @teej107 Okay, I changed the hashmap to the interface, and changed the listener to use that instead.
    Now here's my questions:
    1. With only player, inventory, slot, and item arguments, how would you get it to run a command when that method is called?
    2. Now that it's set up, how do I actually save info in the hashmap?

    I also found some issues with it. If you create multiple MenuMaker objects, you are also creating multiple listeners, which means when you click an item in an inventory, the method is going to run multiple times. Do you know a fix for that?
     
  22. Offline

    nverdier

    @567legodude It would only run multiple time if the inventory's names are the same. You should probably change that line in the listener to check if the inventories themselves are the same. Then it wouldn't happen.
     
  23. Offline

    teej107

    Here is an example:
    Code:
    menuGui.addInterface(slot, new GuiClickListener(){
        @Override
        public void onClick(Player player, Inventory inventory, int slot,
                ItemStack stack)
        {
            player.performCommand("command");
        }
    });
    What do you mean? Just modify your addCommand() method's parameters to accept the GuiClickListener interface instead of a command.
     
  24. Offline

    nverdier

    @teej107 He's saying if you have multiple MenuGUI's, there will be multiple listeners, so then they will fire multiple times.
     
  25. Offline

    teej107

    @nverdier There is one inventory per MenuGUI right? Why would they fire multiple times?
     
  26. Offline

    nverdier

    @teej107 Because the listener is registered for all of them. If the names of the inventories are the same, both of the listeners would fire.
     
  27. Offline

    teej107

    @nverdier So compare the inventory rather than the name.
     
  28. Offline

    nverdier

    @teej107
    :p
     
    teej107 likes this.
  29. Offline

    MrFrozen


    Maybe a feature to run a function instead of a command only.
     
  30. Offline

    567legodude

    @MrFrozen I made this so that beginners could easily make a menu and automatically register commands to items. It wasn't intended for the advanced people who want more functionality.
     
Thread Status:
Not open for further replies.

Share This Page