-
-
Notifications
You must be signed in to change notification settings - Fork 3
Getting Started
tools/gearbox doctor # what toolchains do you have?
tools/gearbox new my-mod # scaffold a mod
tools/gearbox dev my-mod # compile, verify, pack, and install itdev is the one to remember. It builds, checks the module imports nothing
outside the ABI, packs the .odmod, and copies it into the game's mods folder —
so recompiling never means hunting for a directory and copying files by hand.
Then in the game: Mod Menu → Reload modloader. Mods never load any other way, and never mid-game without a reload.
On Windows use tools\gearbox.ps1 (PowerShell), or the bash script under Git
Bash / WSL. Set GEARBOX_MODS_DIR if your install lives somewhere unusual.
tools/sdk_toolchains.sh install # Zig, TinyGo, wabt, Rust, AssemblyScript
tools/sdk_toolchains.sh clean # remove all of itEverything lands in .toolchains/ inside the repo — not Homebrew, not your home
directory — so clean is an rm -rf that cannot break anything else. C and C++
need only a wasm32-capable clang; Apple's cannot target wasm32, but the one
inside Emscripten can.
#include "gearbox.h"
#define S(lit) lit, (uint32_t)(sizeof(lit) - 1)
static gearbox_panel g_panel;
GEARBOX_EXPORT("mod_load")
int32_t mod_load(void) {
gearbox_env_t env; env.size = sizeof env;
gearbox_env(&env);
if (env.is_headless) return 0; /* training run: no renderer */
g_panel = gearbox_panel_register(S("Hello"), 200, 100);
return 0; /* non-zero refuses the load */
}
GEARBOX_EXPORT("mod_draw_panel")
void mod_draw_panel(gearbox_panel p, uint32_t w, uint32_t h) {
(void)w; (void)h;
gearbox_draw_text(p, 8, 8, 0xFFFFFFFFu, S("Hello, world"));
}build/odmod-check my-mod.odmod # same checks the game runs
build/odmod-check my-mod.odmod --revoke UI # rehearse a user saying noThe second one matters: a user can revoke any capability you asked for, and a mod that traps because of it is a bug in the mod.
-
There is no libc. No
snprintf, no allocator unless you write one. Formatting an integer is nine lines and every mod needs it. -
Strings are
(ptr, len), never null-terminated. -
Two-call sizing.
country_namereturns the full length and writes at mostcap. A return greater thancapmeans truncation, not failure. -
is_headlessis real. Self-play runs thousands of turns with no renderer. -
Fuel is finite on desktop — exceed
limits.fuelPerTurnand you are terminated mid-call. On web it is not enforced, so bound your own loops. -
Your state does not survive a reload.
mod_loadalways runs fresh.