Table of Contents
Mod lifecycle
How a mod moves through the engine's boot sequence, and what it may legally do in each phase.
Phases
boot -> import -> discover -> load -> merge -> play -> save
- Boot.
conf.luasets the window; the engine version and mod API number come fromsrc/core/Version.lua, the single home of every compatibility-relevant number (engine semver, mod API major, link protocol, save format, cache generation). - Import.
Game:loadruns the ROM importer's cached data throughData:load(). Mods never participate in extraction; they see the world only after it exists. - Discover. The loader scans the virtual
mods/root (source tree and save directory fused) and validates eachmanifest.json. A bad manifest skips that mod with a logged reason; boot continues. The engine then registers its own vanilla records into the behavioral registries under the ownerengine(src/mods/Builtins.lua) — before any mod runs, so a mod'sregisteron a vanilla id collides and must sayoverride. - Load. Manifest enforcement runs first: engine
game_versionranges, thegameslist against the booted game, hard dependencies (present, enabled, in range, and not scoped to another game), conflict declarations, missingrequired_imports, and dependency cycles, each failing only the mods involved. Entry chunks then run in dependency order (dependencies first, thenpriorityascending, ties by id), each inside its own sandbox (src/mods/Sandbox.lua): a private_G, compat stand-ins for the removed globals, and no reach into the engine's namespace. Each chunk runs under a rollback journal: if it errors, every registration it made and every subscription it took are undone, so a broken mod leaves zero residue. - Merge. Registered content folds over the imported base data, one
registry at a time (
Loader:load, merge loop). A cross-reference pass then resolves id-typed fields against the merged world and reports dangling references. After the merge the content registries freeze:register/override/patch/removeraise from then on, including from inside amods.loadedlistener. Register content at entry-chunk time. Asset transforms run here too, and the merged mod set becomes the asset search path. - Play.
game.readyfires with{ game = Game }once every service is up: readingev.gameis the sanctioned way to reach the liveGameobject. From here the game runs; mods observe it through events and hooks. - Save. Saving and loading pass through the save model: meta stamping, per-mod namespaces, migrations, and the validation/quarantine pass.
Unsealed buses
The event and hook buses are never sealed. A mod may subscribe during its
entry chunk, inside a mods.loaded or game.ready listener, or at any
point later — from inside a battle callback if it wants. Only content
freezes at the merge boundary; behavior stays open for the life of the
process.
Every listener and hook link runs under pcall. A callback that raises is
logged against the mod that subscribed it and skipped; the engine path that
emitted the event or called the hook always completes, and a failing hook
link degrades to "not installed for this call"
(Events and Hooks).
Lifecycle events
| Event | Fires | Payload |
|---|---|---|
mods.loaded |
end of the merge phase | { loader, data } |
game.ready |
after services init, before the first screen | { game } |
Both fire exactly once per boot, with or without mods installed. Under
POKEPORT_DEV=1, a hot reload re-emits game.ready after re-merging
(src/dev/HotReload.lua).
What runs when — quick table
| You want to | Do it |
|---|---|
| Register/override/patch/remove content | entry chunk only |
| Subscribe to events, wrap hooks | any time |
Reach the live Game |
game.ready payload |
Touch the overworld (mod.world) |
after game.ready |
| Read another mod's exports | mod.find(id) — after that mod loaded |
Poll mod.fetch / mod.job handles |
any time; poll never blocks, and handles are released on unload |
Start here
Concepts
Tutorials
- The ladder
- 01 Sprite and Text Tweak
- 02 Balance Patch
- 03 New Species
- 04 New Item and Ball
- 05 New Move
- 06 NPC and Dialogue
- 07 New Map
- 08 Quest
- 09 Custom Music
- 10 New Mechanic
- 11 Custom UI Screen
- 12 Mini Total Conversion
Reference
Guides
- Art Pipeline
- Audio Authoring
- Preparing Your Mod for Gen 2
- Translations
- Total Conversions
- Link Compatibility
- Publishing a Mod
- Custom Carts
- Docs Style Guide
Playing
Engine 1.0.0 · mod API 2 · repository · Discord
This project ships no ROM data. All game content is decoded on the player's machine from their own verified Pokemon Red ROM; mods ship recipes and original assets, never extracted content.