Log inGet started

Input macro (asset type)

An input macro is a recorded or hand-authored sequence of input simulation events — keystrokes, mouse moves, button clicks, scroll wheel deltas — timestamped and played back via sim.macro. Macros are…

The engine deliberately does NOT ship per-feature input recipes (walk, sprint, drive). Authors record or hand-write the macro they need; the playback primitive is type-agnostic.

When to use one

  • You want to script an input sequence for testing (e.g. "walk forward 3 seconds, jump, look around").
  • You're capturing a demo / repro of a user interaction sequence.
  • You want deterministic input playback across runs.

If you need per-frame programmatic input (more than a fixed sequence allows), drive sim.key / sim.click directly from a script. If you need real input handling, that's the input API (man input).

Where it lives

  • Source: /zero/source/.../<name>.inputMacro/
  • Identity: <name> (the .inputMacro suffix strips).
  • Folder shape:
    • events.json — JSON array of { t, op, arg } event tuples. Required.
    • README.md — instance documentation. Required.

How to create one

Two paths:

-- Record a live sequence:
local rec = sim.recordMacro()
-- ... drive the engine for as long as you want to capture ...
rec:stop("<name>")   -- writes events.json into the macro's asset folder

-- Hand-author an empty macro scaffold and fill events in:
asset.create("inputMacro", "<name>")

The record path is preferred for sequences any human could perform; hand-authoring is for synthetic or precisely-timed sequences.

How it operates

  1. Event format. events.json is a JSON array of triples:
    {
      "t": 0.5,
      "op": "key.down",
      "arg": "W"
    }
    
    • t: seconds since macro start.
    • op: event op — key.down, key.up, mouse.move, mouse.button.down, mouse.button.up, mouse.wheel.
    • arg: op-specific argument (key name, axis delta, button index).
  2. Playback. sim.macro("<name>") schedules every event at its t offset relative to playback start. Events are dispatched in order; earlier events fire before later ones even if their t collides.
  3. Determinism. Macros are deterministic relative to engine state at playback start — same start state + same macro = same end state.
  4. Recording. sim.recordMacro() returns a recorder; calling :stop("<name>") finalises the macro and writes it to disk.

Discovery

  • asset.list("inputMacro") — every registered macro.
  • asset.inspect("<name>") — event count, duration, source, this type README.
  • cat /zero/source/<name>.inputMacro — same summary.

Authoring conventions

  • Start macros from a known state (call layers.load("base") before playback) so determinism holds across runs.
  • Keep macros focused on one user-facing action sequence. Longer macros are harder to compose and debug; chain shorter ones via sim.macro("a"); sim.macro("b").
  • Document the expected start state and end state in the macro's instance README — what scene / mode / focus the playback assumes.

Common pitfalls

  • Non-deterministic start state. Playing a macro from a different starting scene produces different outcomes. Always lead with a scene load.
  • Frame-rate dependence. Times are in seconds; the dispatcher schedules events relative to wall time, not frames. Effects that depend on per-frame logic may diverge across hardware.
  • mouse.move argument. It's an absolute screen-coordinate delta, not a relative one. Check the recorded values match.
  • .tool — for agent-callable input wrappers that may invoke macros as part of larger flows.
  • .scene — macros pair with scenes for deterministic test setups.
  • asset-type
  • reference