Six pages under a "Make a mod" group of the docs: set up and see a mod in the game (the launcher's Game arguments or cargo horizon-mod run), the manifest and every capability, the hooks and calls with a worked example (Playtime, built and checked), content mods, testing and check, and publishing (minisign signing, the submit form, review, updates). /mods, the submit page, the docs index, Mods and data packs and the Mod API link to it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3.1 KiB
Test a mod
Three kinds of checks catch most mistakes before players see them: unit tests for your own logic, the game's dev mode for how the mod looks and feels, and cargo horizon-mod check, which runs the same checks as the registry.
Unit tests for your logic
Code that doesn't call the game (formatting, maths, parsing a command's arguments) is ordinary Rust. Put it in plain functions and test it with #[test], as the Playtime example does with its format function:
cargo test
The tests run on your computer, with no game and no WebAssembly. Keeping the hooks thin and the logic in functions makes most of a mod testable this way.
In the game, as a dev mod
Start the game with your mod as a dev mod (how) and keep it running. After each edit:
cargo horizon-mod build
The game sees the new file within a second, says "Mods reloaded" in chat and starts the mod over. What it saved with storage stays. Things to try each time:
- Every command, with no arguments, with good ones and with wrong ones. An
Errshould say what to type instead. - Leaving the world and opening another:
game::get_player()isNoneon the title screen. - Quitting and starting again, for a mod that saves.
- Options, Mods...: the mod's row lists what it may do. If it says the mod stopped, the reason is there.
The game log (logs/latest.log in the game folder) has your mod's info and warn lines as [mod <id>], and the reason when the game refused or stopped the mod.
Why a mod stops. A mod that panics, runs past its time budget for one call (an endless loop, for example) or uses more than 64 MiB of memory is switched off. The rest of the game carries on. Fix the cause and build again: a dev mod starts over with the new file.
Check it as the registry does
Before you publish, run what the registry runs on every submission:
cargo horizon-mod check target/horizon-mod/playtime.hmod
playtime 0.1.0 (mod, API 0.1, client)
12424 bytes, SHA-256 6561…ac13, unsigned
may draw text on your screen
may show you chat messages
may save its own settings to disk
trial run: started, 40 ticks, 120 frames, a chat line, /playtime: ok
It reads the manifest, refuses code that uses a capability the manifest doesn't list, then plays the mod in the sandbox, as the game does: 40 ticks with a moving player, 120 frames, a chat line and each of its commands once with no arguments. The mod must start and must never crash or overrun its budget. It fails with the reason when one of those goes wrong.
--jsonprints the report as JSON, for scripts.--key <public key> --signature <file>.minisigalso checks your signature (Publish).- It checks modpacks (
.hpack) and resource packs (.zip) too;--kind mod|modpack|resourcepackwhen the file's extension doesn't say which.
A mod that passes check passes the registry's automatic checks. A person still reviews it (see Publish).
Next: publish it.