
GUIEngine
GUIEngine is a lightweight, flexible API for creating interactive GUI menus in Minecraft Paper servers (1.21.4). Instead of writing repetitive inventory code for each menu in your plugins, GUIEngine provides a clean, reusable system to create rich interactive interfaces.
Purpose
GUIEngine is designed as a dependency for other plugins, providing a standardized way to:
- Create custom inventory menus with interactive buttons
- Handle player clicks and interactions
- Manage menu navigation and state
- Create dynamic, responsive interfaces
It functions similar to other utility plugins like Vault or ProtocolLib, but focused exclusively on GUI management.
Key Features
- Simple API: Create complex menus with minimal code
- Interactive Buttons: Add clickable buttons with custom actions
- Menu Navigation: Easily handle sub-menus and menu linking
- Dynamic Updates: Update menu contents in real-time
- Builder Pattern: Create menus using a clean, fluent API
- Resource Management: Automatic cleanup of resources
- Event Handling: Properly integrates with Bukkit's event system
- Clean Architecture: Well-organized code for easy extension
How It Works
GUIEngine consists of five core components:
1. GUIEngine (Core)
The main plugin class that initializes the system, registers event listeners, and provides access points for other plugins.
2. GUI (Menu)
Represents an inventory menu with slots for buttons. Each GUI handles its own layout and button mapping.
3. GUIButton (Buttons)
Interactive items within menus that can trigger actions when clicked. Buttons can execute code, send messages, open other menus, etc.
4. GUIManager (State Manager)
Keeps track of which menu is open for each player and manages the opening/closing of menus.
5. InventoryListener (Event Handler)
Intercepts inventory events and routes them to the appropriate GUI components.
How to Use
Adding as a Dependency
First, add GUIEngine as a dependency in your plugin.yml:
depend: [GUIEngine]
Then, add it to your Maven/Gradle build file.
For Maven:
<dependencies>
<dependency>
<groupId>com.gui.engine</groupId>
<artifactId>gui-engine</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
Creating a Basic Menu
Here's a simple example showing how to create and display a menu:
// Create a new GUI with 3 rows (27 slots)
GUI myMenu = new GUI("§6§lMy Menu", 3);
// Add a button that sends a message when clicked
GUIButton messageButton = new GUIButton(
Material.PAPER,
"§e§lClick Me",
Arrays.asList("§7Click to receive", "§7a message"),
(player, gui, button, slot) -> {
player.sendMessage("§aYou clicked the button!");
return true;
}
);
// Add a button that closes the menu
GUIButton closeButton = new GUIButton(
Material.BARRIER,
"§c§lClose",
(player, gui, button, slot) -> {
player.closeInventory();
return true;
}
);
// Place buttons in specific slots
myMenu.setButton(13, messageButton);
myMenu.setButton(26, closeButton);
// Open the menu for a player
myMenu.open(player);
Using the Builder Pattern
You can also use the builder pattern for cleaner menu creation:
GUI menu = new GUI.Builder()
.title("§6§lMy Menu")
.rows(3)
.build();
// Then add buttons and open as normal
Dynamic Button Updates
Buttons can update themselves in response to clicks:
GUIButton counterButton = new GUIButton(
Material.EMERALD,
"§a§lClicks: §f0",
(player, gui, button, slot) -> {
// Extract current count from name
String name = ChatColor.stripColor(button.getItem().getItemMeta().getDisplayName());
int count = Integer.parseInt(name.split(": ")[1]) + 1;
// Update button name
button.setName("§a§lClicks: §f" + count);
// Update the inventory display
gui.updateInventory();
return true;
}
);
Sub-Menus and Navigation
You can easily create navigation systems between menus:
// In your main menu creation:
GUIButton settingsButton = new GUIButton(
Material.REDSTONE_TORCH,
"§b§lSettings",
(player, gui, button, slot) -> {
openSettingsMenu(player); // Your method to create/open settings menu
return true;
}
);
// And in your settings menu:
GUIButton backButton = new GUIButton(
Material.ARROW,
"§e§lBack",
(player, gui, button, slot) -> {
openMainMenu(player); // Your method to create/open main menu
return true;
}
);
Advanced Features
Custom Button Actions
You can create different types of button actions:
// Teleport button
GUIButton teleportButton = new GUIButton(
Material.ENDER_PEARL,
"§5§lTeleport to Spawn",
(player, gui, button, slot) -> {
player.closeInventory();
player.teleport(player.getWorld().getSpawnLocation());
player.sendMessage("§aTeleported to spawn!");
return true;
}
);
// Command execution button
GUIButton commandButton = new GUIButton(
Material.COMMAND_BLOCK,
"§c§lExecute Command",
(player, gui, button, slot) -> {
player.closeInventory();
player.performCommand("spawn");
return true;
}
);
Item Builders
Use the GUIButton builder for even cleaner button creation:
GUIButton button = new GUIButton.Builder()
.material(Material.DIAMOND)
.name("§b§lPremium Features")
.lore("§7Click to view premium options")
.lore("§7Cost: $10")
.onClick((player, gui, button, slot) -> {
// Handle click
return true;
})
.build();
Best Practices
- Resource Management: Close GUIs when your plugin disables.
- Error Handling: Check for null values when dealing with inventories.
- Performance: Create menus on-demand rather than pre-creating all possible menus.
- Organization: Create a separate manager class in your plugin for all your GUIs.
- Player Data: Store player-specific data externally, not in the GUI itself.
Complete Example
See the ExampleGUI.java class in the GUIEngine source code for a complete example of creating menus, submenus, and various button types.
License
GUIEngine is licensed under the MIT License. Feel free to use, modify, and distribute as needed.
