Aurora GUIs v1.1.0

Modern GUI Library for Spigot/Paper

Java 8+ • Minecraft 1.8.8 - 1.21+ • 7 Major Features

🎨 Fluent Builder API 🛡️ Anti-Dupe Protection ⚡ High Performance

🎯 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);
}
✅ That's it! Your GUI is now registered with automatic event handling, click listeners, and full lifecycle management.

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

BASIC
0ms

No validation

PACKET
1-2ms

Standard protection

ADVANCED
3-5ms

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

💬 Community

Get help from the community

🐛 Bug Reports

Found a bug? Let us know!

⭐ 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

<1ms
GUI Creation
<5MB
Memory Overhead
100%
Thread-Safe
11
Exploit Types Detected

🔒 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