├── .github └── FUNDING.yml ├── .gitignore ├── .idea ├── .gitignore ├── misc.xml ├── modules │ └── MenuAPI.main.iml ├── runConfigurations │ ├── Build_MenuAPI.xml │ ├── Clean_MenuAPI.xml │ └── Publish_MenuAPI.xml └── vcs.xml ├── LICENSE.md ├── README.md ├── build.gradle.kts ├── core ├── build.gradle.kts └── src │ └── main │ └── java │ └── net │ └── j4c0b3y │ └── api │ └── menu │ ├── Menu.java │ ├── MenuHandler.java │ ├── MenuSize.java │ ├── annotation │ ├── Async.java │ └── AutoUpdate.java │ ├── button │ ├── Button.java │ └── ButtonClick.java │ ├── layer │ ├── Layer.java │ └── impl │ │ ├── BackgroundLayer.java │ │ └── ForegroundLayer.java │ ├── listener │ └── InventoryListener.java │ ├── pagination │ ├── PaginatedMenu.java │ └── PaginationSlot.java │ ├── task │ └── AutoUpdateTask.java │ ├── template │ └── Template.java │ └── utils │ └── Position.java ├── extras ├── build.gradle.kts └── src │ └── main │ └── java │ └── net │ └── j4c0b3y │ └── api │ └── menu │ └── item │ └── Item.java ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle.kts /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: https://donate.j4c0b3y.net 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | !**/src/main/**/build/ 5 | !**/src/test/**/build/ 6 | gradle.properties 7 | jars/ 8 | 9 | *.iws 10 | *.iml 11 | *.ipr 12 | out/ 13 | !**/src/main/**/out/ 14 | !**/src/test/**/out/ 15 | 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | 3 | !.gitignore 4 | 5 | !vcs.xml 6 | !encodings.xml 7 | !codeStyleSettings.xml 8 | !misc.xml 9 | 10 | !runConfigurations 11 | !runConfigurations/* 12 | 13 | !modules 14 | !modules/* -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.idea/modules/MenuAPI.main.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | SPIGOT 8 | 9 | 1 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/runConfigurations/Build_MenuAPI.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 17 | 19 | true 20 | true 21 | false 22 | false 23 | 24 | 25 | -------------------------------------------------------------------------------- /.idea/runConfigurations/Clean_MenuAPI.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 16 | 18 | true 19 | true 20 | false 21 | false 22 | 23 | 24 | -------------------------------------------------------------------------------- /.idea/runConfigurations/Publish_MenuAPI.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 16 | 18 | true 19 | true 20 | false 21 | false 22 | 23 | 24 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024-Present J4C0B3Y 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MenuAPI 2 | 3 | Simple to use, high performance bukkit menu api. 4 | 5 | ## Features 6 | 7 | - Inbuilt paginated menus 8 | - Asynchronous menu option 9 | - Foreground & background layers 10 | - Reusable layer templates 11 | - Auto update annotation 12 | - Small and lightweight (~22kb) 13 | - Inbuilt item builder utility 14 | - Supports spigot 1.8+ 15 | 16 | ## Support 17 | 18 | If you need any assistance using or installing my MenuAPI, 19 | feel free to contact me by either adding me on discord (@J4C0B3Y) 20 | or by creating an issue and explaining your problem or question. 21 | 22 | ## Installation 23 | 24 | Prebuilt jars can be found in [releases](https://github.com/J4C0B3Y/MenuAPI/releases). 25 | 26 | > **NOTE:**
27 | > It is recommended to relocate the library to prevent 28 | > version mismatches with other plugins that use the api. 29 | 30 | ### Maven & Gradle 31 | 32 | Replace `VERSION` with the latest release version on GitHub. 33 | 34 | ```kts 35 | repositories { 36 | maven("https://repo.j4c0b3y.net/public/") 37 | } 38 | 39 | dependencies { 40 | implementation("net.j4c0b3y:MenuAPI-core:VERSION") 41 | } 42 | ``` 43 | 44 | ```xml 45 | 46 | 47 | j4c0b3y-public 48 | https://repo.j4c0b3y.net/public/ 49 | 50 | 51 | 52 | 53 | 54 | net.j4c0b3y 55 | MenuAPI-core 56 | VERSION 57 | 58 | 59 | ``` 60 | 61 | ### Building 62 | 63 | 1. Clone this repository and enter its directory. 64 | 2. Run the intellij build configuration by clicking the top right icon. 65 | 3. Alternatively you can run `gradle shadowJar`. 66 | 67 | ## Usage 68 | 69 | A MenuHandler instance is required before opening any menus. 70 | 71 | ```java 72 | public class ExamplePlugin extends JavaPlugin { 73 | private MenuHandler menuHandler; 74 | 75 | @Override 76 | public void onEnable() { 77 | this.menuHandler = new MenuHandler(this); 78 | } 79 | } 80 | ``` 81 | 82 | Optionally, you can change default menu behaviour. 83 | 84 | ```java 85 | // Reset the cursor to the center when switching between menus. 86 | menuHandler.setResetCursor(true); 87 | 88 | // Close the menu when Menu#back() is called and there is no previous menu. 89 | menuHandler.setCloseOnBack(true); 90 | ``` 91 | 92 | ### Menus 93 | 94 | To make a menu, all you need to do is extend the `Menu` class. 95 | 96 | ```java 97 | public class ExampleMenu extends Menu { 98 | 99 | public ExampleMenu(Player player) { 100 | // You must specify the title, size and 101 | // player when calling the super constructor. 102 | super("Example Menu", MenuSize.THREE, player); 103 | } 104 | 105 | @Override 106 | public void setup(BackgroundLayer background, ForegroundLayer foreground) { 107 | // Here you can add buttons to the foreground and background layers. 108 | // This method is called the first time the menu is opened. 109 | // See layers & templates further down for more information. 110 | } 111 | } 112 | ``` 113 | 114 | There are some optional methods you can use to listen to certain menu actions. 115 | 116 | ```java 117 | @Override 118 | public void onOpen() { 119 | // Called when the menu is opened. 120 | } 121 | 122 | @Override 123 | public void onClose() { 124 | // Called when the menu is closed. 125 | } 126 | ``` 127 | 128 | To make a menu asynchronous you can annotate the class with `@Async`. 129 | 130 | > **WARNING:**
131 | > Using bukkit api methods in async menus is not recommended, this is 132 | > because the buttons and menu methods are not called on the server thread. 133 | 134 | ```java 135 | @Async // Annotate the class with @Async 136 | public class ExampleMenu extends Menu { 137 | // ... 138 | } 139 | ``` 140 | 141 | To use the `Menu#back()` method, you must set the previous menu in the constructor. 142 | 143 | If the previous menu is not set and the back method is called, by default 144 | nothing will happen unless `menuHandler.setCloseOnBack(true)` is set. 145 | 146 | ```java 147 | public ExampleMenu(Menu previous) { 148 | super("Example Menu", MenuSize.THREE, previous.getPlayer()); 149 | setPreviousMenu(previous); 150 | } 151 | ``` 152 | 153 | Here is how you open the menu for the player. 154 | 155 | ```java 156 | new ExampleMenu(player).open() 157 | ``` 158 | 159 | To close the menu you can do one of two things, both achieve the same thing. 160 | 161 | ```java 162 | menu.close(); 163 | // or 164 | player.closeInventory(); 165 | ``` 166 | 167 | There are two ways to update menus, the first way is to call `Menu#update()`. 168 | 169 | Alternatively, you can make a menu auto update by annotating it with `@AutoUpdate`. 170 | 171 | ```java 172 | // You can specify the update interval in ticks. 173 | // Remember 20 ticks is equal to 1 second. 174 | @AutoUpdate(20) 175 | public class ExampleMenu { } 176 | ``` 177 | 178 | ### Buttons 179 | 180 | You must create an item / icon for the button to display in the menu. 181 | 182 | ```java 183 | public class ExampleButton extends Button { 184 | 185 | @Override 186 | public ItemStack getIcon() { 187 | // If you have an ItemBuilder util, you should use that. 188 | ItemStack icon = new ItemStack(Material.WOOL); 189 | ItemMeta meta = icon.getItemMeta(); 190 | 191 | meta.setDisplayName("Example Button"); 192 | 193 | icon.setItemMeta(meta); 194 | return icon; 195 | } 196 | 197 | @Override 198 | public void onClick(ButtonClick click) { 199 | // This method is called when your button is clicked. 200 | if (!click.getType().equals(ClickType.LEFT)) return; 201 | 202 | // Do something here. 203 | } 204 | } 205 | ``` 206 | 207 | ### Layers 208 | 209 | A menu has two layers to place buttons on, the background and the foreground. 210 | 211 | - The background layer should obviously be used for the menu background, border design, etc. 212 | - The foreground layer should be used for functional buttons, a back button, etc. 213 | 214 | You can use a variety of methods for adding buttons to a layer, 215 | there are javadocs on each method but here is an example. 216 | 217 | ```java 218 | public class ExampleMenu extends Menu { 219 | // ... 220 | 221 | @Override 222 | public void setup(BackgroundLayer background, ForegroundLayer foreground) { 223 | background.border(new PlaceholderButton()); 224 | 225 | foreground.set(1, 1, new TeamButton(Team.RED)); 226 | foreground.set(3, 1, new TeamButton(Team.BLUE)); 227 | foreground.set(5, 1, new TeamButton(Team.GREEN)); 228 | foreground.set(7, 1, new TeamButton(Team.YELLOW)); 229 | } 230 | } 231 | ``` 232 | 233 | If a button returns a null icon, it will not be placed in the menu. 234 | 235 | This makes layers powerful as the background button will be used 236 | if a foreground button in the same slot returns null. 237 | 238 | An example on why this is useful is making a back button that returns the item only if 239 | there is a previous menu otherwise it will be ignored and use the button on the background. 240 | 241 | ### Templates 242 | 243 | Templates can be utilized to make reusable menu designs easily, here is an example. 244 | 245 | ```java 246 | @RequiredArgsConstructor 247 | public class BorderTemplate implements Template { 248 | private final Menu menu; 249 | 250 | @Override 251 | public void apply(BackgroundLayer background, ForegroundLayer foreground) { 252 | background.border(new PlaceholderButton()); 253 | foreground.set(0, new BackButton(menu)); 254 | } 255 | } 256 | ``` 257 | 258 | You can then apply the template in the menu's setup method. 259 | 260 | ```java 261 | public class ExampleMenu extends Menu { 262 | // ... 263 | 264 | @Override 265 | public void setup(BackgroundLayer background, ForegroundLayer foreground) { 266 | apply(new BorderTemplate(this)); 267 | 268 | // You can then add menu specific buttons. 269 | } 270 | } 271 | ``` 272 | 273 | ### Paginated Menus 274 | 275 | To make a paginated menu, extend the `PaginatedMenu` class. 276 | 277 | ```java 278 | public class TagsMenu extends PaginatedMenu { 279 | // ... 280 | 281 | // It is recommended to put all this in a PaginationTemplate 282 | // so this doesn't have to be copied each time you make a menu. 283 | @Override 284 | public void setup(BackgroundLayer background, ForegroundLayer foreground) { 285 | background.border(new PlaceholderButton()); 286 | foreground.set(0, new BackButton(this)); 287 | 288 | // Add the inbuilt pagination slot button where 289 | // you want your paginated buttons / entries to go. 290 | // NOTE: You cannot add pagination slots to the background layer. 291 | foreground.center(new PaginationSlot()); 292 | 293 | // You can also add your own previous page and next page buttons. 294 | foreground.set(0, menu.getRows() - 1, new PreviousPageButton(menu)); 295 | foreground.set(Menu.COLUMNS - 1, menu.getRows() - 1, new NextPageButton(menu)); 296 | } 297 | 298 | // Here you create a list of the buttons that you want 299 | // to be paginated and put in the pagination slots added above. 300 | @Override 301 | public List