Make a mod
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.
Spotted something wrong? Open an issue or ask on Discord.
Not an official Minecraft product. Not approved by or associated with Mojang or Microsoft.