Hytale Modding API: The Complete Server Plugin Development Guide

By HytaleCharts Team Category: guides 7 min read

Everything you need to start building Hytale server plugins. This guide covers the Java 25 setup, plugin lifecycle, the dual event system (EventBus + ECS), command registration, entity components, manifest.json format, and deploying to CurseForge.

Hytale's server plugin system gives developers deep control over every aspect of the game. If you've written Bukkit or Spigot plugins for Minecraft, the transition is straightforward — but Hytale's architecture is fundamentally different in ways that matter. This guide walks you through everything from initial setup to production deployment. Architecture Overview Before writing any code, understand how Hytale's modding works: The client is a renderer. Hytale's C# client handles graphics, input, and audio — but contains no game logic. All simulation runs on the Java server, even in singleplayer. Everything is server-side. When players join a modded server, custom assets and behavior stream automatically. No client mods needed. Four modding categories exist: Data Assets (JSON), Art Assets (Blockbench models), Server Plugins (Java), and Visual Scripting (coming soon). Server plugins are the most powerful category — they give you full Java access to the server runtime, including the Entity Component System, event pipeline, command framework, and world manipulation. Development Environment Setup Prerequisites ToolVersionNotes Java25+Hytale uses modern features including virtual threads (Project Loom) IntelliJ IDEACommunity or UltimateRecommended IDE — free Community Edition works fine Gradle9.2.0+Build system (included in the plugin template) GitAny recent versionFor cloning the official template Clone the Official Template Hypixel Studios provides an official plugin template on GitHub: git clone https://github.com/HytaleModding/plugin-template.git MyFirstPlugin cd MyFirstPlugin Open the project in IntelliJ IDEA and let Gradle sync. The template includes the correct directory structure, build configuration, and server API dependencies. Alternatively, the HytaleIO Project Generator at hytaleio.com/project-generator can create Plugin, Mod, or Full (combo) project scaffolding with a web UI. Plugin Structure Every Hytale plugin follows this directory layout: your-plugin/ ├── src/main/java/com/yourname/yourplugin/ │ └── YourPlugin.java # Main entry point ├── src/main/resources/ │ ├── manifest.json # Plugin metadata (required) │ ├── Common/ # Shared assets (models, textures) │ └── Server/ # Server-side data assets ├── build.gradle.kts ├── settings.gradle.kts └── gradle.properties manifest.json Every plugin requires a manifest.json at the root of the compiled JAR. This is Hytale's equivalent of Bukkit's plugin.yml: { "Group": "com.yourname", "Name": "YourPluginName", "Main": "com.yourname.yourplugin.YourPlugin", "Version": "1.0.0", "Description": "What your plugin does", "Authors": [{"Name": "YourName"}], "ServerVersion": "*", "Dependencies": {}, "OptionalDependencies": {}, "LoadBefore": [], "DisabledByDefault": false, "IncludesAssetPack": false } The plugin identifier is formed as Group:Name (e.g., com.yourname:YourPluginName). The Main field points to your entry class — get this wrong and the plugin won't load. Plugin Lifecycle Your main class extends JavaPlugin and has four lifecycle phases: public class YourPlugin extends JavaPlugin { public YourPlugin(@Nonnull JavaPluginInit init) { super(init); getLogger().info("Plugin constructed!"); } @Override public void setup() { // Phase 2: Register events, commands, ECS systems // This is where most of your registration code goes } @Override public void start() { // Phase 3: Server is ready for players // Start scheduled tasks, open connections } @Override public void shutdown() { // Phase 4: Cleanup before server stops // Save data, close connections, cancel tasks } } PhaseMethodWhat to Do Here 1. ConstructionConstructorBasic initialization, logging 2. Setupsetup()Register events, commands, ECS components and systems 3. Startstart()Start tasks, the server is accepting players 4. Shutdownshutdown()Save data, cleanup resources The Dual Event System This is the most important concept to understand. Hytale has two separate event systems, and using the wrong one is a common mistake. EventBus — Global Server Events The EventBus handles server-wide events like player connections, chat, and world loading. Register handlers through the EventRegistry provided to your plugin: @Override public void setup() { // Synchronous global event getEventRegistry().registerGlobal( PlayerReadyEvent.class, event -> { getLogger().info("Player joined: " + event.getPlayer().getUsername()); } ); // Async event (like PlayerChatEvent) getEventRegistry().registerAsyncGlobal( PlayerChatEvent.class, future -> { future.thenAccept(event -> { if (event.getMessage().contains("spam")) { event.setCancelled(true); } }); } ); } Key EventBus events: PlayerConnectEvent / PlayerDisconnectEvent — connection lifecycle PlayerReadyEvent — player fully loaded and ready PlayerChatEvent — chat messages (async, cancellable) AddPlayerToWorldEvent — player entering a world StartWorldEvent / AddWorldEvent / RemoveWorldEvent — world management Event priorities: Use EventPriority.EARLY to run first and modify events before other handlers see them. Use EventPriority.LATE to see the final state after all other handlers have processed. ECS Events — Entity-Specific Actions Entity-level events like block breaking, block placing, and damage are handled through the Entity Component System, not the EventBus. You create an EntityEventSystem: public class BlockBreakHandler extends EntityEventSystem<EntityStore, BreakBlockEvent> { @Override public Query getQuery() { // Target entities with specific components return Query.builder().build(); } @Override public Class<BreakBlockEvent> getEventType() { return BreakBlockEvent.class; } @Override public void handle(EntityStore store, CommandBuffer buffer, BreakBlockEvent event) { // Process the block break // Cancel in the filter phase, not here } } Critical rule: Only cancel ECS events during the filter phase. Cancellation in the inspect phase has no effect because the action already happened. Entity Component System (ECS) Hytale uses a custom ECS architecture. Understanding this is essential for any non-trivial plugin. Core Concepts Entity — just a unique ID, contains no data itself Component — pure data container attached to an entity System — logic that processes entities with specific component combinations Ref — safe handle to an entity (never store direct entity references) Store — manages entities using Archetypes for efficient memory layout Custom Components public class ScoreData implements Component<EntityStore> { public int score = 0; public String team = ""; public long joinedAt = System.currentTimeMillis(); @Override public ScoreData clone() { ScoreData copy = new ScoreData(); copy.score = this.score; copy.team = this.team; copy.joinedAt = this.joinedAt; return copy; } } Components must implement clone(). Attach them to entities to store custom data — scores, teams, cooldowns, inventories, or any game-specific state. Understanding PlayerRef A "Player" in Hytale isn't a special class — it's an entity composed of components. PlayerRef is actually a component that stores the player's username, UUID, language, and network handler. It stays active as long as the player is connected. Command Registration Commands implement the Command interface: public class SpawnCommand implements Command { @Override public String getName() { return "spawn"; } @Override public void execute(CommandSender sender, String[] args) { if (sender instanceof Player player) { // Teleport player to spawn sender.sendMessage("Teleporting to spawn..."); } } } // Register in setup() commandRegistry.registerCommand(new SpawnCommand()); Both Player and CommandSender support hasPermission() checks. The built-in permissions system supports user-level permissions, group inheritance, and wildcard matching. Build and Deploy Building ./gradlew build The output JAR goes to build/libs/. Deployment Paths PlatformMod Directory Windows (local)%AppData%/Roaming/Hytale/UserData/Mods/ Linux server/opt/hytale/Server/mods/ Hot reloading is partially supported for minor changes — use Ctrl+F9 in IntelliJ to rebuild without a full restart. Major changes require a server restart. The EventRegistry automatically cleans up handlers when a plugin unloads. Publishing to CurseForge CurseForge recognizes three mod types: Packs — asset/content packs (JSON data, models, textures) Plugins — Java JAR files using the server API Early Plugins — bootstrap plugins for low-level class transformations (advanced, use sparingly) Community Resources The modding community has built extensive documentation beyond what Hypixel Studios provides: ResourceFocus HytaleModding.devGuides, docs, tools — 8,000+ Discord members Britakee Studios GitBookComprehensive tested tutorials for Packs and Plugins HytaleDocs.comCommunity wiki and API reference Hytale-Toolkit (GitHub)Decompiled source, javadocs, semantic code search Patcher (GitHub)Browse the server JAR as an IntelliJ project Note: The server JAR is not obfuscated and can be freely decompiled. Hypixel Studios has committed to releasing the full server source code within 1–2 months of EA launch. What's Coming Server source code release — expected by March 2026 Visual Scripting — node-based scripting for non-programmers (similar to Unreal Blueprints) Development bounties — Hypixel Studios plans to offer bounties for community contributions Official documentation expansion — acknowledged as incomplete, being expanded based on community feedback Ready to deploy your plugin? List your modded server on HytaleCharts so players can find your creation. For minigame-specific development patterns, check out our Custom Minigames Guide.