Aurora GUIs v1.1.0
Modern GUI Library for Spigot/Paper
Java 8+ • Minecraft 1.8.8 - 1.21+ • 7 Major Features
🎯 What is AuroraGuis?
A powerful, performant, and developer-friendly GUI library for Spigot/Paper plugins. Features include advanced animations, packet-level anti-duplication protection, custom resource pack support, config-based GUIs, and extended GUI sizes beyond 54 slots. Built for modern Minecraft servers with enterprise-grade features.
Why Choose AuroraGuis?
Fluent Builder API
Intuitive, chainable GUI construction that feels natural
Packet Anti-Dupe
11 exploit detection types with packet-level validation
Advanced Animations
9 built-in animation types with centralized scheduling
Resource Pack Support
Custom models, pixel-perfect titles, and font characters
Config-Based GUIs
YAML configuration with automatic command registration
Extended GUI Sizes
Virtual GUIs with unlimited rows beyond 54 slots
Quick Start
Get up and running with AuroraGuis in just 5 minutes.
Step 1: Initialize GuiManager
import dev.aurora.Manager.GuiManager;
public class YourPlugin extends JavaPlugin {
private GuiManager guiManager;
@Override
public void onEnable() {
// Initialize the GUI manager
guiManager = new GuiManager(this);
getLogger().info("GuiManager initialized!");
}
public GuiManager getGuiManager() {
return guiManager;
}
}
Step 2: Create Your First GUI
import dev.aurora.GUI.AuroraGui;
import dev.aurora.Utilities.Items.ItemBuilder;
import org.bukkit.Material;
import org.bukkit.entity.Player;
public void createMenuGui() {
AuroraGui menu = new AuroraGui("main-menu")
.title("&6&lMain Menu")
.rows(3);
// Add a clickable item
menu.addItem(13,
new ItemBuilder(Material.DIAMOND)
.name("&b&lClick Me!")
.lore("&7This is a clickable item")
.build(),
event -> {
Player player = (Player) event.getWhoClicked();
player.sendMessage("§aYou clicked the diamond!");
}
);
// Register the GUI
menu.register(guiManager);
}
Step 3: Open the GUI
// Get and open the GUI
AuroraGui menu = guiManager.getGui("main-menu");
if (menu != null) {
menu.open(player);
}
Installation
Maven
<repositories>
<repository>
<id>github</id>
<url>https://maven.pkg.github.com/Unforgoten1/AuroraGuis</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>dev.aurora</groupId>
<artifactId>AuroraGuis</artifactId>
<version>1.1.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
Gradle
repositories {
maven {
url = uri("https://maven.pkg.github.com/Unforgoten1/AuroraGuis")
}
}
dependencies {
implementation 'dev.aurora:AuroraGuis:1.1.0'
}
Requirements
- Java: 8 or higher
- Minecraft: Spigot/Paper 1.8.8 - 1.21+
- Dependencies: None required (PacketEvents optional for PacketGui)
🔧 Shading Required
Don't forget to shade AuroraGuis into your plugin JAR using Maven Shade Plugin or Gradle Shadow plugin. Relocate to your plugin's package to avoid conflicts.
Basic GUIs
Master event-based GUI creation with AuroraGui - the foundation of the library.
Creating a GUI
AuroraGui menu = new AuroraGui("main-menu")
.title("&6&lMain Menu")
.rows(3); // 1-6 rows (9-54 slots)
// Add a border
menu.setBorder(BorderType.FULL,
new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE)
.name("&7")
.build()
);
// Add items to specific slots
menu.addItem(11, homeButton, this::handleHomeClick);
menu.addItem(13, shopButton, this::handleShopClick);
menu.addItem(15, settingsButton, this::handleSettingsClick);
// Register and open
menu.register(guiManager);
menu.open(player);
Configuration Methods
| Method | Description | Example |
|---|---|---|
.title(String) |
Set GUI title (supports color codes) | "&6&lShop" |
.rows(int) |
Set number of rows (1-6) | 3 (27 slots) |
.addItem(slot, item) |
Add non-clickable item | Decoration items |
.addItem(slot, item, handler) |
Add clickable item with handler | Interactive buttons |
.setBorder(type, item) |
Add border decoration | FULL, TOP, BOTTOM, SIDES |
.fill(item) |
Fill all empty slots | Background filler |
.register(manager) |
Register with GuiManager | Required before open() |
.open(player) |
Open GUI for player | Show to player |
Event Handling
// Simple click handler
menu.addItem(13, item, event -> {
Player player = (Player) event.getWhoClicked();
player.sendMessage("§aClicked!");
});
// Advanced click handler
menu.addItem(14, item, event -> {
event.setCancelled(true); // Prevent item pickup
Player player = (Player) event.getWhoClicked();
// Handle different click types
if (event.isLeftClick()) {
// Left click action
} else if (event.isRightClick()) {
// Right click action
} else if (event.isShiftClick()) {
// Shift click action
}
});
Pagination
List<ItemStack> allItems = new ArrayList<>();
// Add 100 items...
// System automatically splits across pages
gui.addPaginatedItems(allItems, event -> {
ItemStack clicked = event.getCurrentItem();
Player player = (Player) event.getWhoClicked();
player.sendMessage("§aClicked: " + clicked.getItemMeta().getDisplayName());
});
// Add navigation buttons
ItemStack prev = new ItemBuilder(Material.ARROW)
.name("&ePrevious Page")
.build();
ItemStack next = new ItemBuilder(Material.ARROW)
.name("&eNext Page")
.build();
gui.addItem(45, prev, e -> gui.prevPage());
gui.addItem(53, next, e -> gui.nextPage());
Packet GUIs (Anti-Dupe)
Enterprise-grade anti-duplication protection through packet-level validation.
🛡️ When to Use PacketGui
Use for: Economy systems, shops, banks, trading, rewards, storage systems
Don't use for: Navigation menus, information displays, cosmetic selectors
Quick Start
// Step 1: Enable packet support (once in onEnable)
guiManager.enablePacketSupport();
// Step 2: Create a PacketGui
PacketGui shop = new PacketGui("secure-shop")
.title("&6Secure Shop")
.rows(6)
.validationLevel(ValidationLevel.PACKET)
.addItem(13, createDiamondItem(), event -> {
Player player = (Player) event.getWhoClicked();
// This transaction is protected from duplication
economy.withdraw(player, 1000);
player.getInventory().addItem(new ItemStack(Material.DIAMOND, 64));
player.sendMessage("§aPurchased 64 diamonds!");
})
.register(guiManager);
shop.open(player);
Validation Levels
No validation
Standard protection
Maximum security
The 11 Exploit Types
| Exploit | Severity | Detection Method |
|---|---|---|
| CLICK_DELAY | 2 | Timing less than 50ms |
| CLICK_SPAM | 3 | Rate over 20/second |
| INVALID_SLOT | 3 | Slot out of bounds |
| CURSOR_DUPLICATION | 4 | Cursor amount increased |
| CURSOR_SWAP | 3 | Cursor type changed |
| CLOSE_DESYNC | 3 | State mismatch on close |
| NBT_INJECTION | 5 | SHA-256 hash mismatch |
| SHIFT_CLICK_LOOP | 4 | Duplicate fingerprint |
| TRANSACTION_MISMATCH | 4 | Expected ≠ actual state |
| NO_CLOSE_PACKET | 5 | Missing close packet |
| STALE_SESSION | 4 | Session timeout |
Configuration Presets
// Lenient - For trusted players
PacketGui gui = new PacketGui("shop")
.config(PacketGuiConfig.lenient())
.register(manager);
// Normal - Recommended default
PacketGui gui = new PacketGui("shop")
.config(PacketGuiConfig.normal())
.register(manager);
// Strict - Maximum security
PacketGui gui = new PacketGui("bank")
.config(PacketGuiConfig.strict())
.register(manager);
Violation Handling
PacketGui shop = new PacketGui("shop")
.validationLevel(ValidationLevel.ADVANCED)
.onViolation((player, exploitType) -> {
// Log violation
plugin.getLogger().warning(
player.getName() + " attempted " + exploitType
);
// Alert admins
Bukkit.getOnlinePlayers().stream()
.filter(p -> p.hasPermission("aurora.admin"))
.forEach(admin -> admin.sendMessage(
"§c" + player.getName() + " attempted " + exploitType
));
// Take action based on severity
int severity = exploitType.getSeverity();
if (severity >= 5) {
player.kickPlayer("§cExploit attempt detected.");
} else if (severity >= 4) {
player.sendMessage("§cWarning: Suspicious activity detected.");
}
})
.register(manager);
Virtual GUIs (Extended Sizes)
Break free from Minecraft's 54-slot limit! Create GUIs with unlimited rows.
Quick Start
import dev.aurora.Builder.VirtualGuiBuilder;
import dev.aurora.GUI.VirtualGui;
VirtualGui storage = new VirtualGuiBuilder(manager)
.name("mega-storage")
.title("&6&lMega Storage")
.virtualRows(15) // 135 total slots!
.build();
// Add items using virtual slot numbers (0-134)
for (int i = 0; i < 100; i++) {
storage.setItem(i, items.get(i), event -> {
// Handle click
});
}
// Open for player
storage.open(player);
⚙️ How It Works
Virtual GUIs automatically split content across multiple physical pages (6 rows each). The bottom row is reserved for navigation buttons. Players seamlessly navigate between pages with Previous/Next buttons.
Slot Calculation
Virtual Rows: 15
Total Virtual Slots: 135 (15 × 9)
Content Slots Per Page: 45 (rows 0-4, bottom row reserved for navigation)
Total Pages: 3 (⌈135 ÷ 45⌉)
Virtual Slot 0-44 → Page 1, Slots 0-44
Virtual Slot 45-89 → Page 2, Slots 0-44
Virtual Slot 90-134 → Page 3, Slots 0-44
Custom Navigation
ItemStack prevButton = new ItemBuilder(Material.ARROW)
.name("&e« Previous")
.build();
ItemStack nextButton = new ItemBuilder(Material.ARROW)
.name("&eNext »")
.build();
ItemStack indicator = new ItemBuilder(Material.PAPER)
.name("&6Page {current}/{total}")
.build();
VirtualGui gui = new VirtualGuiBuilder(manager)
.virtualRows(12)
.navigationButtons(prevButton, nextButton, indicator)
.build();
Navigation Methods
// Open at first page
gui.open(player);
// Navigate to specific page
gui.navigateToPage(player, 2); // Go to page 3 (0-indexed)
// Next/previous page
gui.nextPage(player);
gui.prevPage(player);
// Get current page
int currentPage = gui.getCurrentPage(player);
Animations
Bring your GUIs to life with smooth, performant animations.
Quick Start
AuroraGui menu = new AuroraGui("animated-menu")
.title("&6Animated Menu")
.rows(3);
// Create pulsing animation
Animation pulsing = new PulsingBorder(3, 1);
// Add to slot 13 (center)
menu.addAnimation(13, pulsing);
menu.register(manager);
menu.open(player);
Built-in Animation Types
PulsingBorder
Animated border that pulses around the GUI edges
new PulsingBorder(rows, speed)
RotatingCompass
Compass that rotates through all 16 directions
new RotatingCompass()
LoadingBar
Progress bar that fills horizontally or vertically
new LoadingBar(Direction.HORIZONTAL, speed)
Sparkle
Item sparkles with glowing effect
new Sparkle(item)
ColorCycle
Cycles through different colored glass panes
new ColorCycle(speed)
Multiple Animations
AuroraGui menu = new AuroraGui("multi-animated")
.title("&6Multi-Animated Menu")
.rows(5);
// Border pulse
menu.addAnimation(4, new PulsingBorder(3, 1));
// Rotating compass
menu.addAnimation(13, new RotatingCompass());
// Loading bar
menu.addAnimation(22, new LoadingBar(Direction.HORIZONTAL, 10));
menu.register(manager);
menu.open(player);
⚡ Performance
AuroraGuis uses a centralized AnimationScheduler with O(1) overhead. Unlike traditional approaches that create a BukkitTask per animation, all animations share a single master task, scaling efficiently to thousands of animations.
Resource Pack Support
Create unique, branded GUIs with custom models and pixel-perfect titles.
Model Registry
Central system for managing custom model definitions.
Setup models.yml
models:
ruby:
base-material: EMERALD
custom-model-data: 1001
name: "&cRuby"
lore:
- "&7A rare gemstone"
- "&7Value: $1000"
gold_coin:
base-material: GOLD_NUGGET
custom-model-data: 2001
name: "&6Gold Coin"
diamond_sword_custom:
base-material: DIAMOND_SWORD
custom-model-data: 3001
name: "&b&lLegendary Sword"
lore:
- "&7Damage: +50"
- "&7Durability: Infinite"
Load Models
import dev.aurora.ResourcePack.ModelRegistry;
@Override
public void onEnable() {
// Load models from configuration
File modelsFile = new File(getDataFolder(), "models.yml");
int loaded = ModelRegistry.loadFromConfig(modelsFile);
getLogger().info("Loaded " + loaded + " custom models");
}
Use Custom Models
// Method 1: ItemBuilder.customModel()
ItemStack ruby = new ItemBuilder(Material.EMERALD)
.customModel("ruby") // Looks up from ModelRegistry
.lore("&7Click to sell")
.build();
// Method 2: Direct CustomModelData
ItemStack item = new ItemBuilder(Material.EMERALD)
.customModelData(1001)
.name("&cRuby")
.build();
// Method 3: ModelRegistry.createItem()
ItemStack ruby = ModelRegistry.createItem("ruby");
Title Builder
Create pixel-perfect centered GUI titles.
import dev.aurora.ResourcePack.TitleBuilder;
import dev.aurora.ResourcePack.FontCharacters;
String title = new TitleBuilder()
.icon(FontCharacters.STAR)
.space(4)
.text("&6&lPremium Shop")
.space(4)
.icon(FontCharacters.STAR)
.center()
.build();
AuroraGui gui = new AuroraGui("shop")
.title(title)
.rows(6)
.register(manager);
Available Font Characters
| Character | Symbol | Usage |
|---|---|---|
HEART |
❤ | FontCharacters.HEART |
STAR |
★ | FontCharacters.STAR |
CHECKMARK |
✓ | FontCharacters.CHECKMARK |
CROSS |
✗ | FontCharacters.CROSS |
ARROW_LEFT |
← | FontCharacters.ARROW_LEFT |
ARROW_RIGHT |
→ | FontCharacters.ARROW_RIGHT |
Config-Based GUIs
Create entire GUIs from YAML configuration files with automatic command registration.
Setup
import dev.aurora.Config.GuiConfigManager;
@Override
public void onEnable() {
GuiManager guiManager = new GuiManager(this);
// Initialize config-based GUI system
GuiConfigManager configManager = new GuiConfigManager(this, guiManager);
// Load all GUIs from guis/ folder
int loaded = configManager.loadAllGuis();
getLogger().info("Loaded " + loaded + " GUI(s) from configuration");
// Auto-register commands
int registered = configManager.registerCommands();
getLogger().info("Registered " + registered + " command(s)");
}
Create GUI Configuration
Create: plugins/YourPlugin/guis/shop.yml
gui:
name: "shop"
title: "&6&lItem Shop"
rows: 6
command: "shop"
aliases: ["store", "market"]
permission: "myplugin.shop"
auto-register: true
border:
material: "GRAY_STAINED_GLASS_PANE"
name: " "
items:
- slot: 13
material: "DIAMOND"
name: "&b&lDiamond"
lore:
- "&7Price: $100"
- "&7Click to purchase"
action: "close"
- slot: 20
material: "GOLD_INGOT"
name: "&6&lGold"
lore:
- "&7Price: $50"
actions:
- type: "sound"
sound: "ENTITY_PLAYER_LEVELUP"
volume: 1.0
pitch: 1.5
- type: "message"
message: "&aPurchase successful!"
- type: "close"
Available Actions
| Action | Description | Example |
|---|---|---|
close |
Close the GUI | action: "close" |
message |
Send message to player | action: "message:&aHello!" |
command |
Execute player command | action: "command:/spawn" |
console |
Execute console command | action: "console:give {player} diamond 1" |
sound |
Play sound effect | type: "sound", sound: "ENTITY_PLAYER_LEVELUP" |
open-gui |
Open another GUI | action: "open-gui:other-menu" |
teleport |
Teleport player | action: "teleport:world,0,64,0" |
give-item |
Give item to player | action: "give-item:DIAMOND,64" |
✅ Automatic Commands
When auto-register: true is set, players can use /shop, /store, or /market to open the GUI automatically!
Conditions & Cooldowns
Add requirements and cooldowns to GUI interactions.
Click Conditions
import dev.aurora.Struct.Condition.ClickCondition;
gui.addItem(10, premiumItem, handler,
ClickCondition.requirePermission("shop.premium")
.and(ClickCondition.requireLeftClick())
.and(ClickCondition.custom(p -> p.getLevel() >= 20))
);
// Built-in conditions:
ClickCondition.requirePermission("shop.vip")
ClickCondition.requireLeftClick()
ClickCondition.requireRightClick()
ClickCondition.requireShiftClick()
ClickCondition.requireItem()
ClickCondition.custom(player -> player.getLevel() >= 10)
Cooldowns
import dev.aurora.Struct.Cooldown.ClickCooldown;
ClickCooldown cooldown = new ClickCooldown();
cooldown.setDefaultCooldown(1000); // 1 second
gui.addItem(13, rewardItem, event -> {
Player player = (Player) event.getWhoClicked();
if (cooldown.canClick(player)) {
giveReward(player);
cooldown.recordClick(player);
} else {
long remaining = cooldown.getRemainingCooldown(player);
player.sendMessage("§cCooldown: " + (remaining / 1000) + "s");
}
});
Basic Examples
Navigation Menu
public void open(Player player) {
AuroraGui menu = new AuroraGui("nav-menu")
.title("&6&lNavigation")
.rows(3)
.setBorder(BorderType.FULL, createBorder())
.addItem(11, createButton(Material.GRASS_BLOCK, "&aSpawn", "Teleport to spawn"),
e -> teleportToSpawn((Player) e.getWhoClicked()))
.addItem(13, createButton(Material.CHEST, "&eWarps", "Open warp menu"),
e -> openWarps((Player) e.getWhoClicked()))
.addItem(15, createButton(Material.DIAMOND_SWORD, "&cPvP Arena", "Join PvP"),
e -> joinPvP((Player) e.getWhoClicked()))
.register(manager);
menu.open(player);
}
Confirmation Dialog
public static void confirm(GuiManager manager, Player player,
String message, Runnable onConfirm, Runnable onCancel) {
AuroraGui dialog = new AuroraGui("confirm")
.title("&cConfirm Action")
.rows(3)
// Confirm button (green)
.addItem(11, new ItemBuilder(Material.GREEN_WOOL)
.name("&a&lCONFIRM")
.lore("&7Click to confirm")
.build(), event -> {
player.closeInventory();
onConfirm.run();
})
// Cancel button (red)
.addItem(15, new ItemBuilder(Material.RED_WOOL)
.name("&c&lCANCEL")
.lore("&7Click to cancel")
.build(), event -> {
player.closeInventory();
onCancel.run();
})
.register(manager);
dialog.open(player);
}
Advanced Examples
Secure Economy Shop
public void openShop(Player player) {
PacketGui shop = new PacketGui("secure-shop")
.title("&6&lSecure Shop")
.rows(6)
.validationLevel(ValidationLevel.PACKET)
.config(PacketGuiConfig.normal())
.setBorder(BorderType.FULL, createBorder())
// Diamond section
.addItem(10, createShopItem(Material.DIAMOND, 64, 1000),
event -> handlePurchase(player, Material.DIAMOND, 64, 1000))
// Gold section
.addItem(19, createShopItem(Material.GOLD_INGOT, 64, 500),
event -> handlePurchase(player, Material.GOLD_INGOT, 64, 500))
// Violation handler
.onViolation((p, exploitType) -> {
plugin.getLogger().severe(
p.getName() + " attempted " + exploitType + " in shop!"
);
// Alert admins
Bukkit.getOnlinePlayers().stream()
.filter(admin -> admin.hasPermission("shop.admin"))
.forEach(admin -> admin.sendMessage(
"§c§l[ALERT] " + p.getName() + " attempted " + exploitType
));
})
.register(manager);
shop.open(player);
}
Virtual Storage GUI
public void openStorage(Player player) {
VirtualGui storage = new VirtualGuiBuilder(manager)
.name("player-storage-" + player.getUniqueId())
.title("&6&lMega Storage")
.virtualRows(20) // 180 total slots!
.build();
// Load player's items
List<ItemStack> items = loadPlayerItems(player);
// Add items to virtual slots
for (int i = 0; i < items.size(); i++) {
final int index = i;
storage.setItem(i, items.get(i), event -> {
// Handle item click
ItemStack clicked = event.getCurrentItem();
player.sendMessage("§aClicked: " + clicked.getType());
});
}
// Open first page
storage.open(player);
}
API Reference
Quick reference for the most commonly used APIs.
AuroraGui Methods
| Method | Description | Return Type |
|---|---|---|
.title(String) |
Set GUI title | AuroraGui |
.rows(int) |
Set number of rows (1-6) | AuroraGui |
.addItem(slot, item) |
Add non-clickable item | AuroraGui |
.addItem(slot, item, handler) |
Add clickable item | AuroraGui |
.setBorder(type, item) |
Add border decoration | AuroraGui |
.addAnimation(slot, animation) |
Add animation to slot | AuroraGui |
.register(manager) |
Register with GuiManager | AuroraGui |
.open(player) |
Open GUI for player | void |
.close(player) |
Close GUI for player | void |
PacketGui Methods
| Method | Description | Return Type |
|---|---|---|
.validationLevel(level) |
Set validation level | PacketGui |
.config(config) |
Set configuration | PacketGui |
.onViolation(handler) |
Set violation handler | PacketGui |
VirtualGui Methods
| Method | Description | Return Type |
|---|---|---|
.setItem(slot, item) |
Set item at virtual slot | void |
.navigateToPage(player, page) |
Go to specific page | void |
.nextPage(player) |
Go to next page | void |
.prevPage(player) |
Go to previous page | void |
.getCurrentPage(player) |
Get current page number | int |
.getTotalPages() |
Get total page count | int |
Best Practices
✅ DO:
- Use Unique Names - Avoid conflicts with unique identifiers
- Register Before Opening - Always call register() before open()
- Handle Null Items - Check for null in click handlers
- Close Inventory Appropriately - Close before teleports/commands
- Use PacketGui for Economy - Protect valuable transactions
- Reuse ItemStacks - Create once, use many times
❌ DON'T:
- Don't use same name twice - Causes conflicts
- Don't forget to register - GUI won't work
- Don't assume items exist - Always null check
- Don't use ADVANCED for everything - Unnecessary overhead
- Don't ignore violation logs - You'll miss exploits
🎯 Performance Tips
- Reuse ItemStacks instead of creating new ones
- Limit event listeners to only what you need
- Use batch updates with setItems() for multiple items
- Choose appropriate validation levels for your use case
- GuiManager handles automatic cleanup
Support & Resources
⭐ Contribute
Help improve AuroraGuis
- Submit Pull Requests
- Report Issues
- Improve Documentation
🎯 Perfect For
- ✅ Economy plugins - Shops, banks, trading systems
- ✅ Minigame servers - Kit selection, game lobbies
- ✅ RPG plugins - Character menus, skill trees
- ✅ Admin tools - Configuration interfaces, player management
- ✅ Survival servers - Storage systems, warps
- ✅ Any plugin that needs GUIs!
Performance & Security
🔒 Security Features
- Packet-Level Validation - 11 exploit detection types
- Server-Side Truth Tracking - Authoritative state management
- SHA-256 Item Fingerprinting - Advanced NBT injection detection
- Rate Limiting - Prevent click spam attacks
- Session Monitoring - Detect stale sessions and timeouts
- Automatic Rollback - Auto-fix desyncs on violations