Skip to content

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_control {"action": "pause_game"}
skywalker call sim_control '{"action": "pause_game"}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "sim_control",
    "arguments": {
      "action": "pause_game"
    }
  }
}

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)
sim_input {"press": ["space"], "hold": ["d"], "release": ["d"]}
skywalker call sim_input '{"press": ["space"], "hold": ["d"], "release": ["d"]}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "sim_input",
    "arguments": {
      "press": [
        "space"
      ],
      "hold": [
        "d"
      ],
      "release": [
        "d"
      ]
    }
  }
}

logs

Runtime logs read-only

Recent Wander log output and runtime/compile errors.

Argument Type Required Description Values
limit integer Max messages (default 30)
logs {"limit": 20}
skywalker call logs '{"limit": 20}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "logs",
    "arguments": {
      "limit": 20
    }
  }
}

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: .[.], vars., name, enabled. By default the scene is restored afterwards if it was in edit mode. display_hz (e.g. 120) simulates a real display instead: real time advances 1/display_hz per frame (fixed 60 Hz ticks accumulate), 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)
sim_trace {"entities": ["Player"], "properties": ["transform.position"], "ticks": 120, "every": 20}
skywalker call sim_trace '{"entities": ["Player"], "properties": ["transform.position"], "ticks": 120, "every": 20}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "sim_trace",
    "arguments": {
      "entities": [
        "Player"
      ],
      "properties": [
        "transform.position"
      ],
      "ticks": 120,
      "every": 20
    }
  }
}

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_play {"clip": "audio/jump.wav"}
skywalker call audio_play '{"clip": "audio/jump.wav"}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "audio_play",
    "arguments": {
      "clip": "audio/jump.wav"
    }
  }
}

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
audio_mix {"buses": {"music": 0.5, "ambience": {"volume": 0.8}}}
skywalker call audio_mix '{"buses": {"music": 0.5, "ambience": {"volume": 0.8}}}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "audio_mix",
    "arguments": {
      "buses": {
        "music": 0.5,
        "ambience": {
          "volume": 0.8
        }
      }
    }
  }
}

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)
input_map {"operation": "set_action", "name": "dash", "type": "button", "bindings": ["key:shift", "pad:east"]}
skywalker call input_map '{"operation": "set_action", "name": "dash", "type": "button", "bindings": ["key:shift", "pad:east"]}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "input_map",
    "arguments": {
      "operation": "set_action",
      "name": "dash",
      "type": "button",
      "bindings": [
        "key:shift",
        "pad:east"
      ]
    }
  }
}

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)
process_info {"entity": "PauseMenu"}
skywalker call process_info '{"entity": "PauseMenu"}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "process_info",
    "arguments": {
      "entity": "PauseMenu"
    }
  }
}

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)
sim_teleport {"entity": "Player", "position": [0, 1, 0]}
skywalker call sim_teleport '{"entity": "Player", "position": [0, 1, 0]}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "sim_teleport",
    "arguments": {
      "entity": "Player",
      "position": [
        0,
        1,
        0
      ]
    }
  }
}

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
save_game {"slot": "checkpoint-1", "meta": {"title": "Before the boss", "chapter": 3}}
skywalker call save_game '{"slot": "checkpoint-1", "meta": {"title": "Before the boss", "chapter": 3}}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "save_game",
    "arguments": {
      "slot": "checkpoint-1",
      "meta": {
        "title": "Before the boss",
        "chapter": 3
      }
    }
  }
}

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)
load_game {"slot": "checkpoint-1"}
skywalker call load_game '{"slot": "checkpoint-1"}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "load_game",
    "arguments": {
      "slot": "checkpoint-1"
    }
  }
}

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_list {}
skywalker call save_list '{}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "save_list",
    "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_inspect {"slot": "autosave", "max_diffs": 50}
skywalker call save_inspect '{"slot": "autosave", "max_diffs": 50}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "save_inspect",
    "arguments": {
      "slot": "autosave",
      "max_diffs": 50
    }
  }
}

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
save_delete {"slot": "slot3"}
skywalker call save_delete '{"slot": "slot3"}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "save_delete",
    "arguments": {
      "slot": "slot3"
    }
  }
}

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)
game_feel {"action": "shake", "trauma": 0.5}
skywalker call game_feel '{"action": "shake", "trauma": 0.5}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "game_feel",
    "arguments": {
      "action": "shake",
      "trauma": 0.5
    }
  }
}