Charming Realm is a Minecraft Spigot plugin I built from scratch that provides every player with their own independent private world. The system handles the full lifecycle of realm management through an inventory-based GUI framework, async world generation, MySQL-backed persistence, cross-server synchronization, and a five-tier permission model. I designed the architecture to support Spigot 1.16.5 through 1.20.1, with version-specific NMS implementations for world border rendering and ProtocolLib integration for real-time GUI title updates.
Realm Interface Overview
GUI System
Canvas-Based GUI Framework
I built a custom GUI framework from scratch on top of Spigot’s inventory system. The core abstraction is a Canvas, a personal viewport assigned to each player that manages GUI lifecycle, caching, and state transitions. Every GUI extends CharmGUIBase, which defines a four-phase rendering pipeline: initialization reads button layouts from YAML config, post-initialization injects dynamic data, rendering applies color parsing and placeholder replacement, and display handles the final presentation to the player.
flowchart TD
subgraph Canvas["Canvas (Per-Player Viewport)"]
Cache["GUI Cache"]
State["GUI State"]
end
subgraph Handler["CharmGUIHandler"]
Map["UUID → Canvas Map"]
end
subgraph Lifecycle["GUI Rendering Pipeline"]
A["onCustomGUIInitialize()"] --> B["postCustomGUIInitialize()"]
B --> C["rendCustomGUI()"]
C --> D["onCustomGUIDisplay()"]
end
subgraph Factory["Button Factory"]
BF["BaseButtonFactory"]
WF["WorldCreateButtonFactory"]
end
subgraph Config["YAML Config"]
Matrix["Matrix Layout"]
Buttons["Button Definitions"]
end
Handler --> Canvas
Canvas --> Lifecycle
Config --> A
Factory --> C
The GUI layout is entirely data-driven through YAML configuration files. Each GUI defines a matrix of characters where each character maps to a button definition with its item type, display name, lore, click actions, and sound effects. The BaseButtonFactory and WorldCreateButtonFactory handle button creation with support for multiple button types including LOCKED, UNLOCKED, INVENTORY, MANAGE_MEMBER, and WORLD_CREATE.
I also implemented a CrossRealmContainer that allows players to open and manage other players’ realm settings with proper permission validation. The TitleHandler uses ProtocolLib to send raw packets for dynamic GUI title updates without reopening the inventory.
Biome Presets and Custom World Generation
I implemented a custom ChunkGenerator that works alongside a template-based world creation system. Players select from preconfigured biome presets through the GUI, and the system copies the corresponding world template to generate their realm. The FirstBorderShaped class handles initial border shape generation, creating the visual boundary that defines the playable area of each new realm.
Realm Creation and World Management
Asynchronous World Creation Pipeline
Realm creation runs entirely off the main server thread to prevent lag spikes. I built a RealmGeneratorManager that maintains a thread pool (3 to 5 threads) with a LinkedHashMap task queue for FIFO processing. Each RealmCreateTask handles world file copying, chunk generation, config YAML creation, game rule application, and border initialization. When a task completes, it fires a RealmFinishCreateEvent back on the main thread so other systems can react safely.
flowchart LR
A["Player Request"] --> B["RealmCreateEvent"]
B --> C{"Cancelled?"}
C -->|No| D["Add to Task Queue"]
D --> E["Thread Pool Executor"]
E --> F["Copy World Template"]
F --> G["Generate Chunks"]
G --> H["Apply Game Rules"]
H --> I["Initialize Border"]
I --> J["Write Realm Config"]
J --> K["RealmFinishCreateEvent\n(Main Thread)"]
C -->|Yes| L["Abort"]
World Border and Realm Boundary
I implemented a version-adaptive world border system that uses NMS (Net Minecraft Server) code for direct packet manipulation. The WBControl class detects the server version at runtime and delegates to the appropriate implementation, supporting 1.16.3 and above along with Arclight server forks. Players can upgrade their border level to expand their realm’s playable area, with configurable radius increments and upgrade costs. The system also supports hiding and showing the border effect, warning distance configuration, and border damage settings.
Player Management and Social Features
Permission Management and Player Settings
I designed a five-tier permission hierarchy for realm access control:
| Role | Build | Interact | Invite | Ban | Promote | Full Control |
|---|---|---|---|---|---|---|
| Owner | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Operator | ✓ | ✓ | ✓ | ✓ | to Member | |
| Member | ✓ | ✓ | ||||
| Visitor | ✓ | |||||
| Banned |
Each realm stores its member list, operator list, and banned player list. The GUI provides dedicated panels for member management (RealmGUIContentMember), banned player management (RealmGUIContentBanned), and role assignment (RealmGUIRoleAssign). All permission checks are enforced through an extensive listener system covering block placement, block breaking, entity interaction, item pickup, item dropping, and portal creation.
Cross-Realm Visiting and Social Features
I built a social layer on top of the realm system that includes a public realm browser, a flower-based rating system, popularity tracking, and a gift system. Realm owners can toggle their world’s visibility between public and private. Public realms appear in the visit GUI where other players can browse, rate, and teleport to them. The VisitStatistic class tracks visit metrics, and the rating system uses “flowers” as a like mechanism to rank realms by popularity.
Command System with Auto-Complete
The /realm command serves as the entry point for all realm operations. I implemented a full tab completion system that dynamically suggests subcommands, player names, and realm names based on context. Commands support operations like creating realms, inviting players, managing permissions, visiting other realms, and administrative functions. The command parser handles nested arguments such as /realm invite <player> from <owner> for cross-realm management.
Database and Cross-Server Architecture
I integrated MySQL with HikariCP connection pooling for persistent realm data storage. The database schema uses two main tables: SelfHomeMain_Users for realm data (owner, members, operators, settings, coordinates, ratings) and SelfHomeMain_Servers for server load tracking. All queries use prepared statements to prevent SQL injection.
flowchart TD
subgraph Servers["BungeeCord Network"]
S1["Server 1"]
S2["Server 2"]
S3["Server 3"]
end
subgraph Proxy["BungeeCord Proxy"]
LB["Load Balancer"]
MSG["Plugin Messaging"]
end
subgraph Database["MySQL + HikariCP"]
Users["SelfHomeMain_Users"]
Stats["SelfHomeMain_Servers"]
end
S1 <--> MSG
S2 <--> MSG
S3 <--> MSG
MSG <--> LB
S1 --> Database
S2 --> Database
S3 --> Database
LB --> Stats
For cross-server support, I implemented BungeeCord plugin messaging with three message types: waitDelayToHome for delayed teleportation, waitToCommand for remote command execution, and waitToLoad for cross-server world loading. The system automatically balances realm creation across servers by tracking player counts and TPS (ticks per second) metrics, directing new realm creation to the least loaded server.
Design Philosophy
Data-Driven Configuration — Every aspect of the plugin is configurable through YAML files. GUI layouts use a matrix-based character mapping system. Realm settings, game rules, border parameters, and entity limits are all externalized. This allows server administrators to customize the entire experience without touching Java code.
Event-Driven Decoupling — The plugin uses over 30 specialized event listeners to handle world protection, player interactions, and realm management. Custom events like RealmCreateEvent and RealmFinishCreateEvent enable loose coupling between the creation pipeline and dependent systems. This architecture makes it straightforward to add new features without modifying existing code.
Async-First Performance — All heavy operations run off the main server thread. World generation uses a dedicated thread pool. Database queries go through HikariCP’s connection pool. Time synchronization runs asynchronously. This ensures the server maintains stable TPS even during peak realm creation periods.
Version-Adaptive Compatibility — Rather than targeting a single Minecraft version, I built abstraction layers that detect the runtime environment and delegate to version-specific implementations. The world border system, packet manipulation, and NMS access all adapt automatically across Spigot 1.16.5 to 1.20.1, including support for Arclight server forks.