Horizon Content Mods (.hmod)
Horizon content mods are data and assets only — no code. A .hmod is a zip containing a horizon-mod.toml manifest plus optional assets/ and data/ directories, layered over the game's base resources at startup. WebAssembly (mod.wasm) is dead and rejected. If the user wants executable behavior, that is a native mod — see the horizon-native-mod skill instead.
The working loop
- Scaffold the project folder (manifest +
data//assets/), or runcargo horizon-mod new <path> --name "Name". If you used the scaffold: delete its generated example content (blockstates, items, models, block declarations, loot tables, and anything underdata/minecraft/) before adding yours — it demonstrates the exact silently-failing patterns described inreferences/pitfalls.md. Keep only the manifest and your own files. - Add content under the mod's own namespace:
data/<mod-id>/recipe/...,assets/<mod-id>/lang/.... Never write intodata/minecraft/— put overrides indata/<mod-id>/. - Build:
cargo horizon-mod build→ producestarget/horizon-mod/<id>.hmod. - Check:
cargo horizon-mod check target/horizon-mod/<id>.hmod. - Install: copy the
.hmodinto the game'shorizon-mods/directory. Where that is: inside the Horizon install folder, next tohorizon-client.exeandhorizon-mods.txt(e.g....\horizon-windows-x64\horizon-mods\) — this is where our installs load from. The user-data directory (%APPDATA%\Roaming\horizon) is a different location and held no mods folder. Create the folder if a fresh install lacks it. - Enable: content mods load once at startup — quit the game completely, relaunch, Options → Mods → enable, quit completely again, relaunch, load a world.
After step 3, optionally run horizon-inspect target/horizon-mod/<id>.hmod --json (exit 0 = valid) for a security/manifest report if the tool is installed.
Start from what is proven to work
Data-driven recipes with vanilla item ids are the verified baseline — they work with no textures, models, or item registrations:
{
"type": "minecraft:smelting",
"cookingtime": 200,
"experience": 0.35,
"ingredient": "minecraft:rotten_flesh",
"result": { "id": "minecraft:leather" }
}
(minecraft:blasting for blast furnace; cookingtime in ticks, 200 = ~10 s.)
Add one kind of content at a time and retest after each. Horizon can silently reject content it does not understand, so a big-bang mod is undebuggable.
Hard-won pitfalls (verified on Horizon 0.2.97)
Read references/pitfalls.md before designing anything beyond vanilla-item recipes — the failure modes there are silent and cost hours. Headlines:
- New item/block declarations may not appear in-game; the game can reject them without logging errors.
- Item
componentsare unsupported on this version. - Manifest uses
deny_unknown_fields; mod ids are[a-z0-9_]only.
References — read on demand
references/manifest-reference.md— fullhorizon-mod.tomlfield reference: api lines, capabilities, side, id rules. Read before writing any manifest.references/data-and-assets.md— verified data formats (recipes, lang) and asset layout. Read when adding content beyond one smelting recipe.references/pitfalls.md— the silent-failure catalog and debugging strategy. Read before testing and whenever "the mod doesn't show up".references/validation-and-publishing.md— inspector/checker usage, registry rules (index.json,revoked.toml, MOD-POLICY), deterministic packaging. Read before publishing.
Rules that are not negotiable
- Content mods declare capabilities; never request more than the mod needs — players see these before enabling.
- Java mod jars do not run in Horizon; do not try to port
.jarfiles, port their data instead. - Horizon contains no Mojang assets; never bundle Minecraft assets into a mod. Derive everything or reference vanilla ids.