Script entry point#
Petrichor loads luau mods as classes. Your entry file must return a class from mod(). Petrichor calls new() once, then calls tick each frame and shutdown on exit.
Minimal example#
What the loader does#
For a luau mod, Petrichor:
- Reads
entryinmod.json(defaultmain.luau). - Compiles and runs it once in the shared VM.
- Expects a class table back, not an instance.
- Checks for
tick,shutdown, andnew(mod()inherits the first two fromPetrichor.Mod). - Calls
Class.new()(initruns here if defined). - Each frame: task scheduler tick, then
instance:tick(delta). Courage passesDELTA_TIME / 30.0fasdelta(real frame time in 30 Hz units, not a fixed1.0). - On shutdown:
instance:shutdown(), then pending task work is cleared.
Missing methods or a bad return value fails load with a log error.
mod(name)#
Global from Petrichor.Standard. Luau equivalent of mod():
Use at the top of your entry file and return the class at the bottom:
Match the string to your id in mod.json when you can. It shows up in logs.
Petrichor.Mod base class#
require("Petrichor.Mod") is what mod() extends. Use mod() in game mods.
| Method | Description |
|---|---|
init(self, ...) | Optional. Runs from new(). Register hooks here. |
tick(self, delta) | Optional. Default no-op. Per-frame update. |
shutdown(self) | Optional. Default no-op. Called on host shutdown. |
before(self, sym, fn, priority?) | Before-hook, fn(ctx). priority is ignored; use Augment.Mixin.register to control order. |
after(self, sym, fn, priority?) | After-hook, fn(ctx). priority is ignored; use Augment.Mixin.register to control order. |
replace(self, sym, fn, priority?) | Replace-hook, fn(ctx). priority is ignored; use Augment.Mixin.register to control order. |
field(self, ptr, offset, kind) | Augment.Mixin.read. |
setField(self, ptr, offset, kind, value) | Augment.Mixin.write. |
save(self) | Calls Petrichor.Storage.save() if storage is loaded for this mod. |
fire(self, event, data?) | Fires <mod_id>:<event> on Petrichor.Events. |
on(self, event, mod_id, fn) | Subscribes to <mod_id>:<event>. |
once(self, event, mod_id, fn) | One-shot subscription to <mod_id>:<event>. |
off(self, event, mod_id, fn) | Unsubscribes fn from <mod_id>:<event>. |
Same as calling Augment.Hook directly:
Augment.Hook does not take a priority argument. Use Augment.Mixin.register for ordering (see Hooks reference).
TypeScript notes#
- Compile to
out/main.luauand setentrythere. See TypeScript. - The compiled chunk must
export =the mod class. - Declare global
modin TypeScript. Petrichor injects it at runtime.
Plain newclass() without mod()#
return newclass("MyMod", require("Petrichor.Mod")) works for internal tooling. Game mods should use mod().