hytale-modding
SKILL.md
Hytale Modding
Quick Start
- Setup: Java 25 + IntelliJ IDEA + Maven (see
references/dev-environment.md) - Clone template:
git clone https://github.com/HytaleModding/plugin-template.git MyMod - Add server JAR: Install HytaleServer.jar to local Maven repo
- Build:
mvn packageproduces JAR intarget/ - Test: Copy JAR to
%appdata%/Hytale/UserData/Mods/
Architecture: Entity Component System (ECS)
Hytale uses ECS - understand these core concepts:
| Concept | Purpose | Example |
|---|---|---|
| Entity | Unique identifier (no data) | Player, Minecart, Block |
| Component | Data container (no logic) | TransformComponent, Health |
| System | Logic processor | DamageSystem, MovementSystem |
| Store | Entity manager | EntityStore, ChunkStore |
| Holder | Blueprint before spawning | "Shopping cart" for components |
| Ref | Safe entity reference | NEVER store entity objects directly |
See references/ecs.md for complete ECS guide.
Plugin Structure
MyMod/
├── pom.xml # Maven config
├── manifest.json # Plugin metadata
├── src/main/java/
│ └── com/example/
│ └── MyPlugin.java # Main plugin class
└── resources/
└── Common/UI/Custom/ # UI files (if using custom UI)
Main Plugin Class:
public class MyPlugin extends JavaPlugin {
@Override
public void setup() {
// Register commands, events, systems here
}
}
Common Tasks
Creating Commands
Extend AbstractPlayerCommand:
public class MyCommand extends AbstractPlayerCommand {
public MyCommand() {
super("mycommand", "Description");
}
@Override
public void execute(CommandContext ctx, Store<EntityStore> store,
Ref<EntityStore> ref, PlayerRef player, World world) {
player.sendMessage(Message.raw("Hello!"));
}
}
Register in setup(): getCommandRegistry().register(new MyCommand());
Listening to Events
public static void onPlayerReady(PlayerReadyEvent event) {
Player player = event.getPlayer();
player.sendMessage(Message.raw("Welcome " + player.getDisplayName()));
}
Register: getEventRegistry().registerGlobal(PlayerReadyEvent.class, MyEvents::onPlayerReady);
Spawning Entities
world.execute(() -> {
Holder<EntityStore> holder = EntityStore.REGISTRY.newHolder();
ModelAsset asset = ModelAsset.getAssetMap().getAsset("Minecart");
Model model = Model.createScaledModel(asset, 1.0f);
holder.addComponent(new TransformComponent(position, rotation));
holder.addComponent(new PersistentModel(model));
holder.addComponent(new ModelComponent(model));
// ... add required components
store.addEntity(holder, AddReason.SPAWN);
});
Playing Sounds
int soundIndex = SoundEvent.getAssetMap().getIndex("SFX_Cactus_Large_Hit");
world.execute(() -> {
SoundUtil.playSoundEvent3dToPlayer(playerRef, soundIndex,
SoundCategory.UI, transform.getPosition(), store);
});
Reference Documentation
| Topic | File | Contents |
|---|---|---|
| Dev Environment | references/dev-environment.md |
Java 25, IntelliJ, Maven setup |
| ECS Architecture | references/ecs.md |
Store, Holder, Ref, Components, Systems |
| Server Plugins | references/server-plugins.md |
Commands, events, UI, packets |
| Gameplay Systems | references/gameplay-systems.md |
Entities, inventory, blocks, prefabs |
| World Generation | references/world-generation.md |
Zones, biomes, caves |
| Publishing | references/publishing.md |
Modtale, CurseForge distribution |
Key APIs
Entity Access:
player.getWorld()- Get world from playerworld.getEntityStore().getStore()- Get entity storestore.getComponent(ref, componentType)- Get component from entity
Common Components:
TransformComponent- Position and rotationPlayerRef/Player- Player connection and presenceUUIDComponent- Entity unique IDModelComponent- Visual model
System Types:
EntityTickingSystem- Per-entity each tickTickingSystem- Global each tickDelayedEntitySystem- Per-entity with delayRefChangeSystem- React to component changes
Manifest.json
{
"PluginId": "com.example.myplugin",
"PluginName": "My Plugin",
"PluginVersion": "1.0.0",
"IncludesAssetPack": true
}
Set IncludesAssetPack: true when including custom UI or assets.
Testing Workflow
- Build:
mvn package - Copy JAR to
%appdata%/Hytale/UserData/Mods/ - Launch Hytale → Create World → Settings → Mods
- Enable "Diagnostic Mode" in settings for error details