Simulation tools¶
Play, pause, step and stop; inject input; trace and inspect what runs.
15 tools in the sim category. Badges: read-only tools never change the project; mutating tools are undoable and attributed; open-world tools reach outside the engine and MCP clients ask before running them.
| Tool | Summary |
|---|---|
sim_control |
play / pause / stop the game, or step N fixed ticks (1/60 s each) deterministically and get the resulting logs and errors. |
sim_input |
Inject player input for the next ticks, like a player (or a playtest bot) would: press keys (fires on key), hold/release keys (for key()), press or hold input ACTIONS (jump, fire, ... |
logs |
Recent Wander log output and runtime/compile errors. |
sim_trace |
Run the game for N ticks and sample properties over time — e.g. |
audio_play |
Listen to a clip or an entity's audio component. |
audio_mix |
Read or set the project's mixer (audio.json): per-bus volume and mute for master, music, sfx, ambience, voice and ui, and the default music crossfade. |
input_map |
Read or edit the project's input action map (input.json): named, device-independent actions bound to keyboard, mouse and gamepad. |
process_info |
What runs while the game is paused or slowed, and how smooth real-time frames are. |
sim_teleport |
Move an entity instantly — a respawn, a portal, a checkpoint — without render interpolation smearing it across the screen for a frame (Wander: teleport(entity, position)). |
save_game |
Saves the running game into a slot, exactly as Wander's save_game() would at a tick boundary: every entity with a persist component (whole state or chosen fields, Wander vars, spawned subtrees), tombstones for persisted scene entities that were destroyed, game_var values, the scene, the play time and the exact behavior state. |
load_game |
Restores a slot into the running game: persisted entities return to their saved state (spawned ones are recreated with their ids, ones destroyed before the save are removed again), game vars, the scene (a save from another scene is an immediate scene flow change: carry entities come along) and the exact behavior state (state machines, timers, waiting handlers, random generator), then on loaded runs. |
save_list |
Lists the save slots of this project: slot, metadata (title, chapter...), file size, format and game version, play time, scene, tick and when it was saved. |
save_inspect |
Diffs a save slot against the running game to debug "what didn't restore": per persisted entity, the fields whose current value differs from the saved one (path, saved, current), entities missing from the scene, entities the save destroyed or never had, game var differences, the scene and the tick. |
save_delete |
Deletes a save slot's file. |
game_feel |
Try impact feedback on the running game exactly as Wander does: hit_stop freezes the game clock for seconds (or slows it to scale), shake adds trauma (0..1) to the 2D camera (camera, default the active one), flash flashes an entity's sprite color fading over seconds; info reads the hit-stop left, each camera2d's trauma and offset, and active flashes. |
sim_control¶
Simulation control mutating
play / pause / stop the game, or step N fixed ticks (1/60 s each) deterministically and get the resulting logs and errors. stop restores the scene to its pre-play state. Use step + viewport_capture to test behaviors. Two different pauses: pause is the EDITOR pause (nothing ticks; step still works), pause_game is the GAME's pause, like a pause menu (pause_game() in Wander): pausable entities freeze while UI canvases and process mode always/when_paused entities keep running, and on pause fires. time_scale with scale (0..10) is slow motion / fast forward for the game clock. Game pause and time scale apply from the next tick. interpolation turns render smoothing between ticks on/off (real-time frames only). Example: {"action":"pause_game"} then {"action":"step","ticks":30}.
| Argument | Type | Required | Description | Values |
|---|---|---|---|---|
action |
string | yes | What to do | play pause stop step status pause_game resume_game time_scale |
ticks |
integer | Ticks for step (default 60 = 1 second, max 36000) | ||
scale |
number | time_scale: game clock speed (0..10; 1 = normal, 0.25 = bullet time) | ||
interpolation |
boolean | Render interpolation between ticks for real-time frames (default on) |
sim_input¶
Simulate input mutating
Inject player input for the next ticks, like a player (or a playtest bot) would: press keys (fires on key), hold/release keys (for key()), press or hold input ACTIONS (jump, fire, ... see input_map; fires on action) for N ticks (60 ticks = 1 s), hold an axis at a value (move forward: axes=[{name:"move", x:0, y:1, ticks:120}]), set a simulated gamepad (sticks, triggers, buttons) or mouse (position, movement, buttons), click an entity (fires on click), or emit a named event. Applies on the next tick: follow with sim_control step.
| Argument | Type | Required | Description | Values |
|---|---|---|---|---|
press |
string[] | Keys pressed once, e.g. ["space"] | ||
hold |
string[] | Keys to start holding, e.g. ["w"] | ||
release |
string[] | Keys to release | ||
actions |
any[] | Input actions to hold for ticks, e.g. ["jump"] or [{"name":"fire","ticks":30}] | ||
axes |
object[] | Axis actions to hold: [{name, x, y, ticks}] with y = forward/up | ||
release_actions |
string[] | Actions to stop holding | ||
gamepad |
object | Simulated controller: {index?, leftStick:[x,y], rightStick:[x,y], leftTrigger, rightTrigger, buttons:["south",...]} (buttons = the full held set; persists until changed) | ||
mouse |
object | Simulated mouse: | ||
click |
integer | string | Entity to click | ||
event |
string | Event name to emit | ||
data |
any | Event payload, data in the handler, e.g. |
||
target |
integer | string | Event receiver (default: broadcast) |
logs¶
Runtime logs read-only
Recent Wander log output and runtime/compile errors.
| Argument | Type | Required | Description | Values |
|---|---|---|---|---|
limit |
integer | Max messages (default 30) |
sim_trace¶
Trace simulation mutating
Run the game for N ticks and sample properties over time — e.g. transform.position of the player, vars.score, mesh.color — to verify behaviors numerically (did it jump? does the score increase?). Paths: every counts display frames, and each sample shows the interpolation alpha plus shown = what that frame displays (render interpolation) next to the tick values; the result's smoothness compares how evenly vector properties move per frame with and without interpolation (stepJitter: 0 = perfectly even, about 2 = every other frame repeats a tick) and pacing gives the frame-time jitter.
| Argument | Type | Required | Description | Values |
|---|---|---|---|---|
entities |
integer | string[] | yes | Entities to watch | |
properties |
string[] | yes | Property paths, e.g. ["transform.position", "vars.score"] | |
ticks |
integer | Total ticks to simulate (default 120 = 2 s, max 7200) | ||
every |
integer | Sample every N ticks (default 10) | ||
press |
string[] | Keys pressed at the start | ||
hold |
string[] | Keys held during the trace | ||
restore |
boolean | Restore the edit-mode scene afterwards (default true) | ||
display_hz |
number | Simulate a display at this refresh rate (30..240, e.g. 120 for ProMotion): samples per displayed frame with interpolation alpha and shown values | ||
interpolation |
boolean | With display_hz: render interpolation on (default: the engine setting) |
audio_play¶
Play sound read-only
Listen to a clip or an entity's audio component. While editing it auditions the clip on the audio output (a preview; nothing from the scene plays in edit mode). While the game plays it starts a one-shot (clip) or (re)starts the entity's source. stop=true stops the preview, or the entity's sound. Reports whether a real output device is used: on machines without one (CI, servers) sound is mixed silently, so use audio_info to judge a clip, not your ears. Example: {"clip":"audio/jump.wav"} or {"entity":"Campfire"}.
| Argument | Type | Required | Description | Values |
|---|---|---|---|---|
clip |
string | Project-relative audio file | ||
entity |
integer | string | Play this entity's audio component | ||
volume |
number | Gain 0..4 (default 1) | ||
bus |
string | Mixer bus for a clip (default sfx) | master music sfx ambience voice ui |
|
stop |
boolean | Stop instead of play |
audio_mix¶
Audio mixer mutating
Read or set the project's mixer (audio.json): per-bus volume and mute for master, music, sfx, ambience, voice and ui, and the default music crossfade. Every audio component and Wander sound plays through a bus, so this is how you balance a game (music quieter than effects, mute ambience for a cutscene). With no arguments it returns the mix plus what is playing right now (voices with clip, bus and distance gain), whether a real output device is used, and the measured output peak in silent (null) mode. Wander can change volumes at runtime with set_volume("music", 0.4). Example: {"buses":{"music":0.5,"ambience":{"volume":0.8}}}.
| Argument | Type | Required | Description | Values |
|---|---|---|---|---|
buses |
object | bus -> volume (0..4) or {volume, mute}. Buses: master, music, sfx, ambience, voice, ui | ||
musicFade |
number | Default music crossfade in seconds | ||
reset |
boolean | Restore default levels first |
input_map¶
Input actions mutating
Read or edit the project's input action map (input.json): named, device-independent actions bound to keyboard, mouse and gamepad. Scripts use action("jump"), pressed("jump"), axis("move") and on action "jump" instead of raw keys, so one game works with keyboard+mouse and controllers and players can rebind. Defaults exist: move (WASD/arrows/left stick), look (mouse/right stick), jump, fire, aim, interact, sprint, pause, cursor. operation=get returns the map, the live state of every action and (with catalog=true) every valid binding source; set_action adds or replaces one action; remove_action deletes it; reset restores the defaults; set replaces everything; add_preset preset=drive adds the vehicle actions (throttle W/Up/right trigger, brake S/Down/left trigger, steer A-D/arrows/left stick, handbrake Space/A, shift_up/shift_down E/Q/shoulders) that vehicles with control "player" read. Action types: button (held/pressed/released), axis (-1..1), axis2d (x right, y forward/up). Binding strings: key:space, mouse:left, mouse:delta, pad:south, pad:leftStick, pad:rightTrigger; composites "wasd", "arrows", "dpad", "ad", "qe"; objects {source, scale, invertY, deadzone}. Example: set_action name=dash type=button bindings=["key:shift", "pad:east"]. Test with sim_input.
| Argument | Type | Required | Description | Values |
|---|---|---|---|---|
operation |
string | What to do (default get) | get set_action remove_action reset set add_preset |
|
preset |
string | add_preset: a group of actions (drive = vehicle controls) | drive |
|
name |
string | Action name (set_action, remove_action) | ||
type |
string | Action type (set_action, default button) | button axis axis2d |
|
bindings |
any[] | Bindings (set_action) | ||
deadzone |
number | Radial deadzone for analog gamepad sources, 0..1 (default 0.15) | ||
threshold |
number | Analog value at which a button action counts as held (default 0.5) | ||
description |
string | What the action is for | ||
map |
object | Whole map for operation=set: {actions: {name: {type, bindings}}} | ||
catalog |
boolean | Include the list of valid binding sources (get) |
process_info¶
Pause, time scale and smoothing read-only
What runs while the game is paused or slowed, and how smooth real-time frames are. Reports the game clock (paused?, time scale, game vs real time), every entity with a process component or a UI canvas (UI runs always by default), and with entity that entity's effective settings and WHY (which ancestor decided its mode). Also render interpolation: alpha, entities smoothed last frame, on frame handler runs and frame pacing jitter (jitterMs vs jitterMsWithoutInterpolation). Warnings flag a paused game nothing can resume. Example: {"entity": "PauseMenu"}.
| Argument | Type | Required | Description | Values |
|---|---|---|---|---|
entity |
integer | string | Entity to explain (effective mode, clock, interpolation, whether it runs from the next tick) |
sim_teleport¶
Teleport entity mutating
Move an entity instantly — a respawn, a portal, a checkpoint — without render interpolation smearing it across the screen for a frame (Wander: teleport(entity, position)). position/rotation are local (like transform). Without position/rotation it only resets the smoothing. Undoable.
| Argument | Type | Required | Description | Values |
|---|---|---|---|---|
entity |
integer | string | yes | Entity to move | |
position |
number[3] | New position | ||
rotation |
number[3] | New rotation (Euler degrees) |
save_game¶
Save the game mutating
Saves the running game into a slot, exactly as Wander's save_game() would at a tick boundary: every entity with a persist component (whole state or chosen fields, Wander vars, spawned subtrees), tombstones for persisted scene entities that were destroyed, game_var values, the scene, the play time and the exact behavior state. Use it to make checkpoints while playtesting, then load_game to jump back. Needs play mode (sim_control play). Slots: 1-64 of [a-z0-9_-]; "autosave" and "quicksave" do not count toward game.json saves.maxSlots. Example: {"slot": "checkpoint-1", "meta": {"title": "Before the boss", "chapter": 3}}.
| Argument | Type | Required | Description | Values |
|---|---|---|---|---|
slot |
string | yes | Slot name, e.g. "slot1", "autosave", "checkpoint-2" | |
meta |
object | Shown in save menus: title, chapter, thumbnail (project-relative image path), anything else the game wants |
load_game¶
Load a save mutating
Restores a slot into the running game: persisted entities return to their saved state (spawned ones are recreated with their ids, ones destroyed before the save are removed again), game vars, the scene (a save from another scene is an immediate scene flow change: carry entities come along) and the exact behavior state (state machines, timers, waiting handlers, random generator), then on loaded runs. Older saves are migrated (game.json saves.version / saves.migrate). Stopping play still returns to the edited scene. After loading, save_inspect on the same slot lists anything that did not restore. Example: {"slot": "checkpoint-1"}.
| Argument | Type | Required | Description | Values |
|---|---|---|---|---|
slot |
string | yes | Slot to load (save_list shows them) |
save_list¶
List save slots read-only
Lists the save slots of this project: slot, metadata (title, chapter...), file size, format and game version, play time, scene, tick and when it was saved. Damaged files are listed with an error. Also returns the save folder and game.json saves settings. Works while editing too.
Takes no arguments.
save_inspect¶
Compare a save with the game read-only
Diffs a save slot against the running game to debug "what didn't restore": per persisted entity, the fields whose current value differs from the saved one (path, saved, current), entities missing from the scene, entities the save destroyed or never had, game var differences, the scene and the tick. Right after load_game everything should read same; anything else is what the load could not bring back. Example: {"slot": "autosave", "max_diffs": 50}.
| Argument | Type | Required | Description | Values |
|---|---|---|---|---|
slot |
string | yes | Slot to compare | |
max_diffs |
integer | Most field differences to list (default 200) |
save_delete¶
Delete a save slot mutating destructive
Deletes a save slot's file. Cannot be undone. Example: {"slot": "slot3"}.
| Argument | Type | Required | Description | Values |
|---|---|---|---|---|
slot |
string | yes | Slot to delete |
game_feel¶
Game feel (hit-stop, shake, flash) mutating
Try impact feedback on the running game exactly as Wander does: hit_stop freezes the game clock for seconds (or slows it to scale), shake adds trauma (0..1) to the 2D camera (camera, default the active one), flash flashes an entity's sprite color fading over seconds; info reads the hit-stop left, each camera2d's trauma and offset, and active flashes. Use while playing (sim_control play), then step and capture. Example: {"action": "shake", "trauma": 0.5}
| Argument | Type | Required | Description | Values |
|---|---|---|---|---|
action |
string | yes | What to do | hit_stop shake flash info |
seconds |
number | hit_stop / flash duration (default 0.08 / 0.12) | ||
scale |
number | hit_stop: clock speed during the stop (0 = frozen) | ||
trauma |
number | shake: trauma added (0..1, default 0.4) | ||
camera |
integer | string | shake: camera entity with camera2d | ||
entity |
integer | string | flash: sprite entity | ||
color |
string | flash: color (default #ffffff) |