[LIB] AmpMenus - Advanced Inventory Menus/GUIs

Discussion in 'Resources' started by ampayne2, Jul 19, 2014.

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

    ampayne2

    AmpMenus Library v1.0:

    An object-oriented approach to handling Inventory Menus/GUIs in Bukkit.

    AmpMenus is intended for advanced use cases such as the following examples:

    [​IMG]

    Attribute Allocation Menu
    • Displays the player's current attribute amounts on the attribute items
    • Increase and decrease the points to add by clicking the wool above/below the attribute items
    • Display the increase points item as green wool if the player has enough attribute points to increase the attribute
    • Display the decrease points item as red wool if the player has actually increased the attribute
    • Confirm or cancel point selection
    [​IMG]

    Capture The Flag Shop
    • Display the next available tier of different classes and perks
    Because the items in these menus behave differently depending on the player and certain data or conditions, they would not be possible with a traditional plugin such as http://dev.bukkit.org/bukkit-plugins/chest-commands/ and would be impractical to create with a simpler utility such as https://forums.bukkit.org/threads/icon-menu.108342/

    Maven

    Add the following repository:
    Show Spoiler

    HTML:
    <repository>
      <id>greatman-repo</id>
      <url>http://repo.greatmancode.com/content/groups/public/</url>
    </repository>


    And the following dependency:
    Show Spoiler

    HTML:
    <dependency>
      <groupId>ninja.amp</groupId>
      <artifactId>ampmenus</artifactId>
      <version>1.4-SNAPSHOT</version> <!-- Use LATEST for latest dev build -->
      <scope>compile</scope>
    </dependency>


    And if you want the code to be shaded into your plugin, add the following build plugin:
    Show Spoiler

    HTML:
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>1.7.1</version>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>shade</goal>
                </goals>
                <configuration>
                    <artifactSet>
                        <includes>
                            <include>ninja.amp:ampmenus</include>
                        </includes>
                    </artifactSet>
                </configuration>
            </execution>
        </executions>
    </plugin>


    For code example, usage and additional information:
    View the README.md on Github
    MenuItems for Minigame Shop Menus

    Helpful Links:
    Source code
    Javadocs
    Jenkins

    Message me (Ampayne2) on IRC at irc.esper.net, i'm always happy to help. If you make something cool, let me know - I'd be glad to feature it as an example :)

    Replies welcome, thanks for reading!

    Change Log
    Update 8/28/2014:
    Bumped version number from 1.3 to 1.4​
    Removed the unnecessary ItemClickEventHandler class in this commit, it was kinda pointless as the only implementation was MenuItem and it wasn't possible to use custom implementations.​
    Update 8/12/2014:
    Bumped version number from 1.2 to 1.3​
    Removed the line in the constructor of an ItemMenu that automatically registers the MenuListener in this commit - make sure you register it in on enable or before players can open menus.​
    Update 8/4/2014:
    Bumped version number from 1.1 to 1.2​
    Removed the Menu interface​
    Added a Size enum for ItemMenus instead of using raw slot amounts​
    Update 8/4/2014:
    Moved separate ItemMenu listeners into a global MenuListener in these commits.​
    The global listener automatically registers itself when any ItemMenu instance is created. When a menu is being opened for a player it first checks to make sure the listener is registered and if not, registers it. It works as expected for plugins that don't reload or unregister their own listeners, or even for plugins that have reload functionality in their plugin and immediately instantiate new ItemMenus. There is one unlikely situation which could cause issues - if a player has a menu open, and the plugin's listeners are unregistered without the menu listener being re-registered immediately.
    You won't run into this issue if your plugin meets any of these requirements:
    • Doesn't have reload functionality or doesn't unregister listeners.
    • Instantiates its ItemMenus on enable, so that even if the menu listener is unregistered in a reload, it is immediately re-registered.
    • Calls MenuListener.getInstance().register(JavaPlugin plugin) on enable or as soon as possible after the plugin's listeners are unregistered. Note: If you meet the previous requirement you don't need this, as it is done automatically.
    I also added a method to close all open menus, MenuListener#closeOpenMenus(). The MenuListener automatically calls this method if a PluginDisableEvent is called for the plugin to help prevent the above issue.

    Update 8/3/2014:
    ItemMenu listeners now use EventPriority.HIGHEST
    Added a StaticMenuItem which should be used for MenuItems whose icons will rarely or never change. Instead of displaying a clone of the base icon with the display name and lore applied, it displays the base icon. The base icon of a MenuItem is returned by getIcon() and can still be modified.

    The gray glass panes which filled empty slots and were removed in this pull request have been added back as an optional feature. Just call ItemMenu#fillEmptySlots() to fill with the gray glass panes or ItemMenu#fillEmptySlots(MenuItem menuItem) to fill with a MenuItem of your choosing.

    Update 7/24/2014:
    Changed group id from me.ampayne2 to ninja.amp
    Bumped version number from 1.0 to 1.1
    To use versions past 1.0 you will have to update your pom.xml and old imports

    Update 7/23/2014:
    Accepted this pull request removing gray glass panes filling empty slots

    Update 7/21/2014:
    Added example MenuItems for a minigame shop menu here

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 9, 2016
  2. Offline

    ArsenArsen

    Can i make app to automaticly make code?
     
  3. Offline

    ampayne2

    Are you asking if it would be possible to make an app or asking permission?
    It would definitely be possible for menus that execute commands or do other things, or just templates for menus and their items but if the menu needs to hook into another plugin or something unique that the app doesn't support then its still going to need code in addition to what the app generates. I think it would be awesome, you don't need to ask permission anyway because it's open source :p

    Let me know if you do make it though :D
     
  4. Offline

    ArsenArsen

    It is possible and preety easy, i am asking for permission and need some templates for code, by you.
     
  5. Offline

    mahlooo

    Would you be willing to share the source for the two examples you provided? Looks great from what I've seen.
     
  6. Offline

    ampayne2

    I'd be willing to post the CTF Shop, the attribute allocation menu is under an NDA heh. I'll update the code and post it later today, it's actually using an older version of AmpMenus. Basically there is a GamePerk which extends MenuItem and a TieredGamePerk which extends GamePerk - a lot of the code is situational depending on how you store perks and coins such as buying the perk or getting the players current tier, I'm just going to leave that out so you'll understand how the menu part works. I'll leave comments where those things should be done though :)
     
  7. Offline

    LordVakar

    Well this is interesting...
    I'm gonna go look at the src
     
    ampayne2 likes this.
  8. Offline

    mahlooo

    That would be great! I'm really interested in how this compares to my current solution.

    Edit: I just saw that whenever you create a MenuItem, it forces the lore to be gray. (See https://github.com/ampayne2/AmpMenu.../me/ampayne2/ampmenus/items/MenuItem.java#L43) May I request to have the loop adding gray removed? I feel as if that should be something added in another level of abstraction.
     
  9. Offline

    ampayne2

    Yeah, forgot to take it out when I was making it a resource :p

    Edit: Removed the part that set the lore to gray here
    Edit 2: Added the example MenuItems you asked for here :)
     
  10. Offline

    ampayne2

    Wasn't sure if you saw my edits mahlooo ;)
     
  11. Offline

    mahlooo


    Looks great, thanks for the help :)
     
    ampayne2 likes this.
  12. Offline

    TigerHix

    This is awesome. I have a near approach on this, but this is obviously better than mine. Thanks for sharing this resource. :)
     
    ampayne2 likes this.
  13. Offline

    ampayne2

    I refactored the package to my new domain amp.ninja :)
    To use versions past 1.0 you will have to update your pom.xml.
    Change group id from me.ampayne2 to ninja.amp
    Change the version number from 1.0 to 1.1
    You will also need to replace all old imports with the new ones (or just replace all "me.ampayne2" with "ninja.amp")
     
  14. Offline

    mahlooo

    Why do you choose to store the display name and lore of the item and then later apply it, instead of applying it and modifying the ItemStack later?
     
  15. Offline

    ampayne2

    It seemed like a good idea at the time, since a lot of the items changed so much depending on the player. Now that I look at it though it doesn't improve the performance of those items and it hurts the performance of items that stay the same - I'll push an update changing that :p
     
  16. Offline

    thomasb454

    I'm either being an idiot or something, but I can't work out how to use the setParent method? Any advice?
     
  17. Offline

    mahlooo

    PHP:
    ItemMenu mainMenu = new ItemMenu("Main Menu"54this);
    // set the mainMenu's items here...
     
    // create the sub menu and use the method to set the parent
    ItemMenu subMenu = new ItemMenu("This is a submenu!"54this);
    subMenu.setParent(mainMenu);
     
    // you can also set the parent of the menu in the constructor if you like
    ItemMenu otherMenu  = new ItemMenu("This is another menu"54thismainMenu);
    Now you can use the BackItem on the subMenu or the SubMenuItem on the mainMenu to navigate between the two.

    You don't have to use the setParent method at all, but if you're going to be doing sub menus, it's an easy way to manage them.
     
  18. Offline

    thomasb454



    I know how to use it in that context, but I'm talking about the advanced usage (as shown on the Gist).

    I've tried, this
    Code:java
    1. @Override
    2. public void setParent(Menu parent) {
    3. super.setParent(parent);
    4. }
    5. }

    I'm pretty good with Java, but I'm not too sure what to do here. :L

    And within the classes constructor

    Code:java
    1. setItem(7, new BackItem());
     
  19. Offline

    mahlooo


    Which advanced usage are you talking about? This in the README?
    PHP:
    // Useful in case you only want the back item to appear if the menu has a parent
    @Override
    public void setParent(Menu parent) {
        
    super.setParent(parent);
        if (
    parent != null) {
            
    setItem(16, new BackItem());
        }
    }
    Your code for setParent shouldn't be creating a new MainMenu every time you call it. This lib is designed to have one instance of a particular menu. Instead of overriding the setParent method the way you have, you can simply call setParent() with your instance of MainMenu.
     
  20. Offline

    thomasb454

    I know that, I was just trying everything.



    Anyway, your explanation makes much more sense, lemme go try it. Thanks :)
    EDIT: Works. Thanks =)
     
  21. Offline

    mahlooo


    Glad to hear it. :)
     
  22. Offline

    AoH_Ruthless

    ampayne2
    I really like this library overall. It makes menu creation a lot simpler. However I do have a few points. They aren't truly a big deal at all so it is up to you if you want to act on them..

    • Why do you even have the Menu interface when there is only one implementation of it?
    • Do not use MONITOR as an event priority. This will override logger plugins and other plugins. This sort of action should use at most, HIGHEST.
    • On Line #158 your if check only checks for ClickType.LEFT. That doesn't deal with all left clicks. You might want to add an option for SHIFT_LEFT, etc...
    If you don't want to do it yourself I could submit a PR if you'd like. If you don't want to change it, that's no big deal, its still a nice resource.
     
    thomasb454 likes this.
  23. Offline

    ampayne2

    I didn't explain it very well in the comment heh, basically if you are lazy and don't want to add a back item to every menu that has a parent menu, you could do that and it would automatically add a back item if you give it a parent menu. Make sure you pay attention to which slot it's putting the item in though.

    Glad you like it :)
    I have the Menu interface because it's possible there could be more implementations in the future (although probably not :p). About the other two, i'll have it changed later today - going on vacation but should have internet.
     
  24. Offline

    AoH_Ruthless

    ampayne2
    It makes sense to have an interface with one implementation if you know that you will be creating more implementations or it is likely you will. If you believe you likely will not create more implementations, it is in my opinion better to remove it entirely.
     
  25. Offline

    Onlineids

    ampayne2 Feel like I've seen that attribute interface, herocraft?
     
  26. Offline

    ampayne2

    Yeah, I recoded their pretty buggy/non user-friendly ChestCommands menu with this lib :p
     
  27. Offline

    AoH_Ruthless

    ampayne2
    You may want to update your shade code to reflect your changelog, which states that you refactored the package of this library.
     
  28. Offline

    ampayne2

    Thanks for pointing that out :)
     
  29. Offline

    lzravanger

    Only thing I would recommend is using a global listener. You register a listener for every Menu which is quite redundant when you can get the Menu from the InventoryHolder and just call methods from there.
     
  30. Offline

    ampayne2

    I went through the suggestions and was able to address most of them:
    https://github.com/ampayne2/AmpMenus/commit/73cccb4a7524fba2c60d898446e486a578920554

    The listener now uses EventPriority.HIGHEST

    I have added a StaticMenuItem which should be used for MenuItems whose icons will rarely or never change. Instead of displaying a clone of the base icon with the display name and lore applied, it displays the base icon. The base icon of a MenuItem is returned by getIcon() and can still be modified.

    The gray glass panes which filled empty slots and were removed in this pull request have been added back as an optional feature. Just call ItemMenu#fillEmptySlots() to fill with the gray glass panes or ItemMenu#fillEmptySlots(MenuItem menuItem) to fill with a MenuItem of your choosing.

    I am aware, it's a temporary measure while I try to find the best way to automatically register the global listener without requiring plugins depending on the library to do anything. My thoughts were to register the listener when an ItemMenu is created, using the plugin instance in the constructor. However it shouldn't be registered more than once so I just need to do some investigation haha :p

    After some investigation, the best solution I could come up with is this.
    The global listener automatically registers itself when any ItemMenu instance is created. When a menu is being opened for a player it first checks to make sure the listener is registered and if not, registers it. It works as expected for plugins that don't reload or unregister their own listeners, or even for plugins that have reload functionality in their plugin and immediately instantiate new ItemMenus. There is one unlikely situation which could cause issues - if a player has a menu open, and the plugin's listeners are unregistered without the menu listener being re-registered immediately.
    You won't run into this issue if your plugin meets any of these requirements:
    • Doesn't have reload functionality or doesn't unregister listeners.
    • Instantiates its ItemMenus on enable, so that even if the menu listener is unregistered in a reload, it is immediately re-registered.
    • Calls MenuListener.getInstance().register(JavaPlugin plugin) on enable or as soon as possible after the plugin's listeners are unregistered. Note: If you meet the previous requirement you don't need this, as it is done automatically.
    I also added a method to close all open menus, MenuListener#closeOpenMenus(). The MenuListener automatically calls this method if a PluginDisableEvent is called for the plugin to help prevent the above issue.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 9, 2016
Thread Status:
Not open for further replies.

Share This Page