gameable
Classes
BodyIndex
Maps host body ids back onto entities and ingests frame-input.bodies.
The incoming list is a Float32Array in both modes — jco lifts WIT list<f32> into one, and direct mode hands the guest the host's own buffer (see packages/sdk/src/wit/generated/interfaces/gameable-engine-game.d.ts). It is read purely by index and never copied.
Constructors
Constructor
ts
new BodyIndex(maxBodies): BodyIndex;Parameters
| Parameter | Type | Description |
|---|---|---|
maxBodies | number | Body-id ceiling. |
Returns
Properties
bodyToEntity
ts
readonly bodyToEntity: Uint32Array;Body id to entity id. Index 0 is unused: body 0 means "no body".
lastRowCount
ts
lastRowCount: number = 0;Number of rows seen in the most recent ingest.
Methods
bind()
ts
bind(body, entity): void;Associate a body with the entity it drives.
Parameters
| Parameter | Type | Description |
|---|---|---|
body | number | Body id. |
entity | number | Entity id. |
Returns
void
Nothing.
bodyOf()
ts
bodyOf(entity): number;The body id driving an entity, or 0.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
Returns
number
The body id, or 0 when the entity has none.
clear()
ts
clear(): void;Forget every body.
Returns
void
Nothing.
ingest()
ts
ingest(bodies): void;Copy post-step body transforms into Transform and Velocity.
This does not mark the entity moved, and that is the point. The host owns a body-driven entity's transform: the physics module hands the same rows straight to the adapter after it steps, so the object in the scene is already where the body is. Marking here would send all twelve floats back across the boundary in frame-output.transforms for the host to write a second time — the same numbers, one step later.
What the guest gets is still the truth for gameplay: read Transform.x[e] to aim at something, Velocity to decide whether it is running. A system that overwrites those lanes is authoring a move rather than observing one, and has to say so with markMoved — see markMoved.
Parameters
| Parameter | Type | Description |
|---|---|---|
bodies | ArrayLike<number> | The packed rows, stride 15. |
Returns
void
Nothing.
unbind()
ts
unbind(body): void;Forget a body.
Parameters
| Parameter | Type | Description |
|---|---|---|
body | number | Body id. |
Returns
void
Nothing.
CommandBuffer
Builds and owns one frame's commands list.
Constructors
Constructor
ts
new CommandBuffer(): CommandBuffer;Returns
Properties
list
ts
readonly list: Command[] = [];The list handed to the host. Reused every frame; never retain it.
Methods
addBody()
ts
addBody(
body,
entity,
kind,
shape,
hx,
hy,
hz,
px,
py,
pz,
mass,
layer,
mask,
flags
): AddBodyCmd;Create a rigid body or character controller.
Parameters
| Parameter | Type | Description |
|---|---|---|
body | number | Guest-minted body id. |
entity | number | Entity the body drives. |
kind | BodyKind | Body class. |
shape | ShapeKind | Collision shape family. |
hx | number | Half-extent / radius lane 0. |
hy | number | Half-extent / half-height lane 1. |
hz | number | Half-extent lane 2. |
px | number | Position x. |
py | number | Position y. |
pz | number | Position z. |
mass | number | Kilograms; ignored for fixed and kinematic bodies. |
layer | CollisionLayers | What this body is. |
mask | CollisionLayers | What this body collides with. |
flags | BodyFlags | Per-body switches. |
Returns
The payload, so the caller can tune friction and damping. Round anything written onto it with Math.fround.
addJoint()
ts
addJoint(args): void;Queue a joint in boundary units (radians and metres).
Parameters
| Parameter | Type | Description |
|---|---|---|
args | AddJointCmd | Joint command, copied into a pooled slot. |
Returns
void
addVehicle()
ts
addVehicle(
body,
settings,
initialState
): void;Attach handling to an existing dynamic body.
Parameters
| Parameter | Type |
|---|---|
body | number |
settings | VehicleSettings |
initialState | VehicleState |
Returns
void
applyImpulse()
ts
applyImpulse(
body,
x,
y,
z,
atX?,
atY?,
atZ?
): void;Apply a one-shot impulse.
Parameters
| Parameter | Type | Description |
|---|---|---|
body | number | Body id. |
x | number | Impulse x. |
y | number | Impulse y. |
z | number | Impulse z. |
atX? | number | World-space application point x. Omit for the centre of mass. |
atY? | number | Application point y. |
atZ? | number | Application point z. |
Returns
void
Nothing.
cancelCharacterAction()
ts
cancelCharacterAction(entity): void;Take an action's request back.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
Returns
void
Nothing.
conversation()
ts
conversation(
entity,
action,
character?,
text?
): void;Control an optional host conversation module using pooled commands.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Interviewed entity. |
action | | "end" | "start" | "ask" | "interrupt" | "microphone-on" | "microphone-off" | undefined | Lifecycle or text command. |
character | string | '' | Configured character id, never a URL. |
text | string | '' | Typed/transcribed question; empty for lifecycle commands. |
Returns
void
cutscene()
ts
cutscene(
action,
asset,
fadeInMs?,
fadeOutMs?,
skippable?,
pause?
): void;A cutscene: preload a clip, play it over the stage, or skip the one playing.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
action | "play" | "preload" | "skip" | undefined | 'preload', 'play' or 'skip'. |
asset | number | undefined | The video asset handle; 0 for skip. |
fadeInMs | number | 400 | Fade in, milliseconds. |
fadeOutMs | number | 400 | Fade out, milliseconds. |
skippable | boolean | true | A tap or a key ends it early. |
pause | boolean | true | The stage pauses under it and the game's sound is ducked. |
Returns
void
despawn()
ts
despawn(entity): void;Destroy an entity in the host scene.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
Returns
void
Nothing.
doCharacterAction()
ts
doCharacterAction(
entity,
action,
object,
plain
): void;Ask a character to do an action of its motion set.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
action | string | The action's name. |
object | Readonly<ActionObject> | null | The thing it is done at, or null for none. |
plain | boolean | The plain way, for a comparison. |
Returns
void
Nothing.
effect()
ts
effect(
action,
effect,
preset,
px,
py,
pz,
dx,
dy,
dz,
entity,
scale,
intensity,
tint
): void;Queue an effect, copying all vectors into its pooled payload.
Parameters
| Parameter | Type | Description |
|---|---|---|
action | EffectAction | Play, move or stop. |
effect | number | Guest-minted handle; 0 is a one-shot. |
preset | string | Built-in preset name for play. |
px | number | Position x. |
py | number | Position y. |
pz | number | Position z. |
dx | number | Direction x. |
dy | number | Direction y. |
dz | number | Direction z. |
entity | number | undefined | Followed entity, or undefined. |
scale | number | Size multiplier. |
intensity | number | Count and brightness multiplier. |
tint | Vec3 | undefined | Linear RGB override, or undefined. |
Returns
void
Nothing.
faceCharacter()
ts
faceCharacter(
entity,
facing,
quick?
): void;Turn a character on the spot to face a way.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity id. |
facing | number | undefined | Radians about +Y (0 faces +Z). |
quick | boolean | false | The quickest turn the set has, instead of an unhurried one. |
Returns
void
Nothing.
fightCamera()
ts
fightCamera(shot): void;The fight camera, run on the host.
Parameters
| Parameter | Type | Description |
|---|---|---|
shot | FightCameraCmd | The camera's request, every number copied. |
Returns
void
Nothing.
fightFall()
ts
fightFall(
entity,
velocity,
spin,
turn,
kick?
): void;A fighter thrown into the rag-doll.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity id. |
velocity | Vec3 | undefined | Metres a second, world. |
spin | number | undefined | Radians a second about the axis across the blow's line. |
turn | number | undefined | The blow's line's angle on the floor. |
kick | boolean | false | - |
Returns
void
Nothing.
fightGetUp()
ts
fightGetUp(entity, quick): void;A fighter up off the floor.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
quick | boolean | The kip-up, when the body lies on its back. |
Returns
void
Nothing.
fightHit()
ts
fightHit(entity, hit): void;A blow on a fighter.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
hit | Omit<FightHitCmd, "entity"> | The blow, every number copied. |
Returns
void
Nothing.
fightState()
ts
fightState(entity, state): void;The fight kit's script door: what a fighter's body is doing this step.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
state | Omit<FightStateCmd, "entity"> | The body's doing, every number copied (the floats rounded to f32). |
Returns
void
Nothing.
hitCharacter()
ts
hitCharacter(
entity,
at,
direction,
strength
): void;A blow on a character's physics body.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
at | Vec3 | Where the blow lands, world space. |
direction | Vec3 | null | Which way it travels, world space; null for the character's front. |
strength | number | "small" | "big" | "shot" | "big-shot" | 'small', 'big', 'shot', 'big-shot', or a push's newton-seconds. |
Returns
void
Nothing.
loadAsset()
ts
loadAsset(asset, priority): void;Ask the host to start loading an asset.
Parameters
| Parameter | Type | Description |
|---|---|---|
asset | number | Asset handle. |
priority | number | Higher runs first. |
Returns
void
Nothing.
lookAt()
ts
lookAt(
entity,
target,
weight
): void;Aim a character's head and eyes.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
target | Vec3 | null | World-space point, or null to release the look-at. |
weight | number | Blend weight in 0..1. |
Returns
void
Nothing.
moveCharacter()
ts
moveCharacter(
body,
vx,
vy,
vz,
jump,
crouch,
maxSlopeDeg
): void;Drive a character body for one step.
Parameters
| Parameter | Type | Description |
|---|---|---|
body | number | Body id of a character body. |
vx | number | Desired velocity x. |
vy | number | Desired velocity y. |
vz | number | Desired velocity z. |
jump | boolean | Request a jump this step. |
crouch | boolean | Request a crouch this step. |
maxSlopeDeg | number | Maximum walkable slope in degrees. |
Returns
void
Nothing.
pausePop()
ts
pausePop(reason): void;Release only the named pause owner.
Parameters
| Parameter | Type | Description |
|---|---|---|
reason | string | Owner name. |
Returns
void
Example
ts
buffer.pausePop('menu');pausePush()
ts
pausePush(reason): void;Acquire a named pause owner on the host.
Parameters
| Parameter | Type | Description |
|---|---|---|
reason | string | Owner name. |
Returns
void
Example
ts
buffer.pausePush('menu');playMusic()
ts
playMusic(
tracks,
stems,
stemGains,
bpm,
beatsPerBar,
firstBeat,
fadeMs,
start,
looping,
volume
): void;Queue play-music.
Parameters
| Parameter | Type | Description |
|---|---|---|
tracks | readonly number[] | Streamed playlist in order. |
stems | readonly number[] | Sample-locked layers; ignores tracks when non-empty. |
stemGains | readonly number[] | Initial gains; missing entries mean 1. |
bpm | number | Beats per minute; 0 disables the clock. |
beatsPerBar | number | Beats per bar; 0 means 4. |
firstBeat | number | Seconds from file start to beat zero. |
fadeMs | number | Crossfade duration in milliseconds. |
start | BeatQuantize | Start relative to the current grid. |
looping | boolean | Loop tracks or stems. |
volume | number | Linear gain. |
Returns
void
playSound()
ts
playSound(
sound,
asset,
entity,
volume,
pitch,
looping,
bus
): void;Start a sound.
Parameters
| Parameter | Type | Description |
|---|---|---|
sound | number | Guest-minted sound handle. |
asset | number | Audio asset handle. |
entity | number | undefined | Entity to follow, or undefined for a non-positional sound. |
volume | number | Linear gain in 0..1. |
pitch | number | Playback-rate multiplier. |
looping | boolean | Loop the sound. |
bus | AudioBus | Mixer bus. |
Returns
void
Nothing.
playSoundOnBeat()
ts
playSoundOnBeat(
sound,
asset,
quantize,
subdivision,
volume,
bus
): void;Queue play-sound-on-beat.
Parameters
| Parameter | Type | Description |
|---|---|---|
sound | number | Guest-minted sound handle. |
asset | number | Manifest asset handle. |
quantize | BeatQuantize | Grid to schedule on. |
subdivision | number | Grid points per beat; ignored for bars. |
volume | number | Linear gain. |
bus | AudioBus | Mixer bus. |
Returns
void
playtest()
ts
playtest(
kind,
value,
entity,
position,
note
): void;Mark something for a playtest: a death and its cause, a win, the goal. It changes nothing in the game.
Parameters
| Parameter | Type | Description |
|---|---|---|
kind | string | What happened: death, win, checkpoint, damage, reward, goal, player, restart, or the game's own word. |
value | number | How much, or 0. |
entity | number | The entity it concerns, or 0. |
position | Vec3 | null | Where, or null. |
note | string | Why, in a few words, or ''. |
Returns
void
recoverCharacter()
ts
recoverCharacter(entity): void;Back into the animation: a character that is down blends back over about a second.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
Returns
void
Nothing.
removeBody()
ts
removeBody(body): void;Destroy a body.
Parameters
| Parameter | Type | Description |
|---|---|---|
body | number | Body id. |
Returns
void
Nothing.
removeJoint()
ts
removeJoint(joint): void;Queue joint removal.
Parameters
| Parameter | Type | Description |
|---|---|---|
joint | number | Guest-minted joint id. |
Returns
void
removeVehicle()
ts
removeVehicle(body): void;Detach handling, leaving the body alive.
Parameters
| Parameter | Type |
|---|---|
body | number |
Returns
void
reset()
ts
reset(): void;Rewind for a new frame. Keeps every pooled object alive.
Returns
void
Nothing.
resetVehicle()
ts
resetVehicle(
body,
position,
rotation
): void;Reset all handling history and teleport the chassis.
Parameters
| Parameter | Type |
|---|---|
body | number |
position | Vec3 |
rotation | Quat |
Returns
void
say()
ts
say(
entity,
text,
audio?,
visemes?
): void;Speak a line.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
text | string | Subtitle text. |
audio? | number | Voice line asset handle. |
visemes? | string | Viseme track as JSON. |
Returns
void
Nothing.
setAnim()
ts
setAnim(
entity,
clip,
looping,
speed,
fadeMs,
weight
): void;Play or cross-fade a clip.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
clip | string | Clip name inside the entity's asset. |
looping | boolean | Loop the clip. |
speed | number | Playback rate multiplier. |
fadeMs | number | Cross-fade duration in milliseconds. |
weight | number | Target layer weight in 0..1. |
Returns
void
Nothing.
setAsset()
ts
setAsset(entity, asset): void;Attach or detach a renderable.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
asset | number | undefined | Asset handle, or undefined to detach. |
Returns
void
Nothing.
setBodyEnabled()
ts
setBodyEnabled(body, enabled): void;Enable or disable a body in the broad phase.
Parameters
| Parameter | Type | Description |
|---|---|---|
body | number | Body id. |
enabled | boolean | Whether the body participates. |
Returns
void
Nothing.
setBodyTransform()
ts
setBodyTransform(
body,
px,
py,
pz,
qx,
qy,
qz,
qw,
teleport
): void;Move a body directly.
Parameters
| Parameter | Type | Description |
|---|---|---|
body | number | Body id. |
px | number | Position x. |
py | number | Position y. |
pz | number | Position z. |
qx | number | Rotation x. |
qy | number | Rotation y. |
qz | number | Rotation z. |
qw | number | Rotation w. |
teleport | boolean | Clear velocities and skip interpolation. |
Returns
void
Nothing.
setBodyVelocity()
ts
setBodyVelocity(
body,
x,
y,
z,
ax?,
ay?,
az?
): void;Overwrite a body's velocity.
Parameters
| Parameter | Type | Description |
|---|---|---|
body | number | Body id. |
x | number | Linear x. |
y | number | Linear y. |
z | number | Linear z. |
ax? | number | Angular x, radians per second. Omit to leave spin alone. |
ay? | number | Angular y. |
az? | number | Angular z. |
Returns
void
Nothing.
setBusFx()
ts
setBusFx(
bus,
preset,
reverb,
lowpassHz,
highpassHz,
compressor,
fadeMs
): void;Queue set-bus-fx.
Parameters
| Parameter | Type | Description |
|---|---|---|
bus | AudioBus | Mixer bus. |
preset | FxPreset | Base effect preset. |
reverb | number | undefined | Optional wet level. |
lowpassHz | number | undefined | Optional low-pass cutoff in Hz. |
highpassHz | number | undefined | Optional high-pass cutoff in Hz. |
compressor | boolean | undefined | Optional compression switch. |
fadeMs | number | Ramp duration in milliseconds. |
Returns
void
setCharacterMotion()
ts
setCharacterMotion(
entity,
on,
set,
carry,
responsiveness,
naturalness,
stop?
): void;How the movement system moves a character.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
on | boolean | Whether the movement system moves it at all. |
set | string | undefined | 'own', 'shared' or a name the page gave its bridge; undefined keeps the set it has. |
carry | boolean | Whether the take carries the walker. |
responsiveness | number | 0..1; negative keeps what it has. |
naturalness | number | 0..1; negative keeps what it has. |
stop? | StopStyle | Which kind of stop it makes when it runs and is asked to stand: 'gradual' (it slows and stands upright) or 'hard' (it brakes); undefined keeps what it has. |
Returns
void
Nothing.
setCharacterState()
ts
setCharacterState(
entity,
state,
vx,
vy,
vz,
grounded,
facing?
): void;Drive a character's locomotion state machine.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
state | string | State name, for example `'idle' |
vx | number | Velocity x. |
vy | number | Velocity y. |
vz | number | Velocity z. |
grounded | boolean | Whether the character is on the ground. |
facing? | number | Optional held world yaw, radians. |
Returns
void
Nothing.
setClipWeights()
ts
setClipWeights(
entity,
clips,
weights,
timeScale
): void;Set explicit per-clip weights.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
clips | readonly string[] | Clip names. |
weights | readonly number[] | Float32Array<ArrayBufferLike> | Positional weights; must match clips in length. Copied into pooled storage, so the caller may reuse its own array freely. |
timeScale | number | Playback rate for the whole layer. |
Returns
void
Nothing.
setExpression()
ts
setExpression(
entity,
space,
weights
): void;Set facial expression coefficients.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
space | ExpressionSpace | Coordinate space the weights are in. |
weights | readonly number[] | Float32Array<ArrayBufferLike> | Coefficients; length must match the space. Copied into pooled storage, so the caller may reuse its own array freely. |
Returns
void
Nothing.
setJointMotor()
ts
setJointMotor(
joint,
axis,
mode,
target,
maxForce
): void;Queue a motor command in boundary units.
Parameters
| Parameter | Type | Description |
|---|---|---|
joint | number | Joint id. |
axis | number | Axis index. |
mode | MotorMode | Motor mode. |
target | number | Radians or metres, per second for velocity mode. |
maxForce | number | Force or torque limit. |
Returns
void
setListener()
ts
setListener(
px,
py,
pz,
qx,
qy,
qz,
qw
): void;Place the audio listener.
Parameters
| Parameter | Type | Description |
|---|---|---|
px | number | Position x. |
py | number | Position y. |
pz | number | Position z. |
qx | number | Rotation x. |
qy | number | Rotation y. |
qz | number | Rotation z. |
qw | number | Rotation w. |
Returns
void
Nothing.
setMaterialParam()
ts
setMaterialParam(
entity,
name,
value
): void;Set one material uniform.
The value is copied into a pooled holder, rounded to f32: the host never sees the guest's own object, and a colour built inline costs nothing after the first frame. Only a slot that changes variant allocates.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
name | string | Uniform name. |
value | MaterialValue | The value variant. |
Returns
void
Nothing.
setMusicLayer()
ts
setMusicLayer(
layer,
gain,
fadeMs
): void;Queue set-music-layer.
Parameters
| Parameter | Type | Description |
|---|---|---|
layer | number | Stem index. |
gain | number | Linear gain. |
fadeMs | number | Ramp duration in milliseconds. |
Returns
void
setParent()
ts
setParent(
entity,
parent,
keepWorldTransform
): void;Reparent an entity.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
parent | number | undefined | New parent, or undefined for the scene root. |
keepWorldTransform | boolean | Preserve the world transform across the move. |
Returns
void
Nothing.
setPointerLock()
ts
setPointerLock(locked): void;Request or release pointer lock.
Parameters
| Parameter | Type | Description |
|---|---|---|
locked | boolean | Whether the canvas should hold pointer lock. |
Returns
void
Nothing.
setPost()
ts
setPost(settings): void;Queue partial post settings; absent fields leave the host's setting alone.
Parameters
| Parameter | Type | Description |
|---|---|---|
settings | PostSettings | Settings read field by field, never retained. |
Returns
void
Nothing.
setSoundOcclusion()
ts
setSoundOcclusion(
sound,
amount,
fadeMs
): void;Queue set-sound-occlusion.
Parameters
| Parameter | Type | Description |
|---|---|---|
sound | number | Sound handle. |
amount | number | Occlusion from 0 to 1. |
fadeMs | number | Ramp duration in milliseconds. |
Returns
void
setSpotLight()
ts
setSpotLight(settings): void;Queue spotlight settings, copying into a pooled payload.
Parameters
| Parameter | Type |
|---|---|
settings | SpotLightCmd |
Returns
void
Example
ts
buffer.setSpotLight(settings);setTimeScale()
ts
setTimeScale(scale): void;Scale simulated time.
Parameters
| Parameter | Type | Description |
|---|---|---|
scale | number | Multiplier; 1 is real time. |
Returns
void
Nothing.
setVehicleInput()
ts
setVehicleInput(
body,
controls,
gripScale
): void;Queue one step of controls in pooled storage.
Parameters
| Parameter | Type |
|---|---|
body | number |
controls | VehicleInput |
gripScale | number |
Returns
void
spawn()
ts
spawn(
entity,
asset,
px,
py,
pz,
qx,
qy,
qz,
qw,
sx,
sy,
sz,
name?
): void;Create an entity in the host scene.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Guest-minted entity id. |
asset | number | undefined | Renderable asset handle, or undefined for a bare node. |
px | number | Position x. |
py | number | Position y. |
pz | number | Position z. |
qx | number | Rotation x. |
qy | number | Rotation y. |
qz | number | Rotation z. |
qw | number | Rotation w. |
sx | number | Scale x. |
sy | number | Scale y. |
sz | number | Scale z. |
name? | string | Debug label. |
Returns
void
Nothing.
spawnCharacter()
ts
spawnCharacter(
entity,
bundle,
px,
py,
pz,
qx,
qy,
qz,
qw
): void;Instantiate a splat character bundle.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Guest-minted entity id. |
bundle | number | Character bundle asset handle. |
px | number | Position x. |
py | number | Position y. |
pz | number | Position z. |
qx | number | Rotation x. |
qy | number | Rotation y. |
qz | number | Rotation z. |
qw | number | Rotation w. |
Returns
void
Nothing.
stopCharacterWalk()
ts
stopCharacterWalk(entity): void;Give up a walk to a spot.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
Returns
void
Nothing.
stopMusic()
ts
stopMusic(fadeMs): void;Stop music.
Parameters
| Parameter | Type | Description |
|---|---|---|
fadeMs | number | Fade duration. |
Returns
void
stopSound()
ts
stopSound(sound, fadeMs): void;Stop a playing sound.
Parameters
| Parameter | Type | Description |
|---|---|---|
sound | number | Sound handle. |
fadeMs | number | Fade-out in milliseconds. |
Returns
void
Nothing.
take()
ts
protected take<T>(tag, make): T;Take the next pooled slot for a tag, appending it to the frame list.
Type Parameters
| Type Parameter |
|---|
T |
Parameters
| Parameter | Type | Description |
|---|---|---|
tag | | "send" | "set-player-camera" | "set-player-hud" | "save-player-data" | "save-game-data" | "set-player-entity" | "exchange" | "playtest" | "add-vehicle" | "set-vehicle-input" | "reset-vehicle" | "remove-vehicle" | "conversation" | "spawn" | "despawn" | "set-asset" | "set-parent" | "set-anim" | "set-material-param" | "add-body" | "add-joint" | "remove-joint" | "set-joint-motor" | "remove-body" | "set-body-transform" | "set-body-velocity" | "apply-impulse" | "set-body-enabled" | "move-character" | "spawn-character" | "set-character-state" | "set-clip-weights" | "set-expression" | "look-at" | "say" | "hit-character" | "recover-character" | "set-character-motion" | "walk-character-to" | "face-character" | "stop-character-walk" | "do-character-action" | "cancel-character-action" | "play-sound" | "stop-sound" | "play-music" | "stop-music" | "set-music-layer" | "play-sound-on-beat" | "set-bus-fx" | "set-sound-occlusion" | "set-listener" | "load-asset" | "set-pointer-lock" | "set-time-scale" | "pause-push" | "pause-pop" | "cutscene" | "thing" | "effect" | "set-post" | "set-spot-light" | "fight-state" | "fight-hit" | "fight-fall" | "fight-get-up" | "fight-camera" | The command tag. |
make | () => T | Module-const factory for a fully shaped payload, called only when the pool has to grow. |
Returns
T
The payload to mutate. Every field must be written: the slot still holds whatever the last command with this tag left behind.
thing()
ts
thing(
action,
thing,
x?,
y?,
z?
): void;Ask something of a loose thing in a made world: push it, move it, put it back where the package had it, set one of its joints, drive it, or sit a character on it.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
action | | "push" | "joint" | "move" | "reset" | "drive" | "reset-all" | "ride" | "break" | undefined | 'push', 'move', 'reset', 'reset-all', 'joint', 'drive', 'ride' or 'break' (x, y, z: metres a second added to each piece). |
thing | number | undefined | The thing's place in the world's list. |
x | number | 0 | push: impulse x, newton-seconds. move: where, x. joint: which joint. drive: steering to the right. ride: the character's entity, 0 for getting off. |
y | number | 0 | The same, y. joint: its value. drive: the brakes. |
z | number | 0 | The same, z. drive: the throttle. |
Returns
void
walkCharacterTo()
ts
walkCharacterTo(
entity,
target,
facing,
pace,
quick?,
stop?,
start?
): void;Walk a character to a spot.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity id. |
target | Vec3 | undefined | The spot, world space. |
facing | number | undefined | undefined | The facing to arrive with, radians about +Y; undefined: as it arrives. |
pace | number | undefined | Metres a second; 0 is the set's own walk. |
quick | boolean | false | The shortest stops and turns the set has, instead of unhurried ones. |
stop? | StopStyle | undefined | Which kind of stop this one walk ends with: 'gradual' (it slows and stands upright) or 'hard' (it brakes); undefined: the character's own. |
start? | "moving" | undefined | How it is begun: 'moving', the game says the body is under way already; undefined: as the character's takes have the body. |
Returns
void
Nothing.
GameAddressError
An unsafe game address and the reason it was refused.
Example
ts
import { GameAddressError, resolveGameAddress } from 'gameable/assets';
try { resolveGameAddress('javascript:alert(1)'); }
catch (error) { if (error instanceof GameAddressError) console.log(error.reason); }Extends
Error
Constructors
Constructor
ts
new GameAddressError(address, reason): GameAddressError;Parameters
| Parameter | Type |
|---|---|
address | string |
reason | string |
Returns
Overrides
ts
Error.constructorProperties
address
ts
readonly address: string;The refused address.
reason
ts
readonly reason: string;Why the address is unsafe.
LevelEditError
An edit that cannot be applied: the actor it names is gone (stale), a name is taken, a class is unknown, or an attachment would dangle.
Example
ts
try { applyLevelEdits(level, edits); } catch (e) { if (e instanceof LevelEditError) console.log(e.stale); }Extends
Error
Constructors
Constructor
ts
new LevelEditError(message, stale?): LevelEditError;Parameters
| Parameter | Type | Description |
|---|---|---|
message | string | What went wrong, with the edit's index. |
stale? | string | The missing actor's name, if any. |
Returns
Overrides
ts
Error.constructorProperties
stale?
ts
readonly optional stale?: string;The actor name the edit looked for and did not find, when that is the problem.
MessageDef
One game message: what defineMessage returns. Pass it to ctx.net.messages and ctx.net.send.
Example
ts
const Ready = defineMessage('ready', (p): p is true => p === true);
console.log(Ready.name, Ready.maxBytes); // 'ready' 2048Type Parameters
| Type Parameter |
|---|
T |
Constructors
Constructor
ts
new MessageDef<T>(
name,
check,
maxBytes
): MessageDef<T>;Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | The message name on the wire. |
check | MessageCheck<T> | The payload's type guard. |
maxBytes | number | The payload cap in UTF-8 bytes of JSON. |
Returns
MessageDef<T>
Properties
check
ts
readonly check: MessageCheck<T>;The payload's type guard.
maxBytes
ts
readonly maxBytes: number;The payload cap in UTF-8 bytes of JSON.
name
ts
readonly name: string;The message name on the wire.
TransformPacker
Packs entity transforms into frame-output.transforms.
One row is written per entity whose dirty flags are non-zero, in ascending entity order — deterministic, and cheaper than a bitecs query for the densely packed id space the SDK mints.
Constructors
Constructor
ts
new TransformPacker(maxEntities): TransformPacker;Parameters
| Parameter | Type | Description |
|---|---|---|
maxEntities | number | Entity ceiling; the buffer holds this many rows. |
Returns
Properties
dirty
ts
readonly dirty: Uint8Array;Per-entity transform-flags accumulated since the last pack.
highWater
ts
highWater: number = 0;Highest entity id pack scans to.
It rises when a higher id is marked and falls back to the last dirty id every pack, so a level that spawned 4,000 entities and despawned all but ten does not keep scanning 4,000 slots a frame.
Methods
clear()
ts
clear(): void;Forget every pending flag, for example after restore.
Returns
void
Nothing.
mark()
ts
mark(entity, flags): void;Accumulate dirty flags for one entity.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
flags | number | Any combination of TRANSFORM_FLAGS. |
Returns
void
Nothing.
pack()
ts
pack(): Float32Array;Write every dirty entity into the packed buffer and clear the flags.
Returns
Float32Array
A memoised subarray of the internal buffer. The same row count always returns the same object, which is what makes a steady-state tick allocation-free; never retain it across frames.
Interfaces
Abilities
Rechargeable abilities indexed by owner (0..owners-1, not entity ids). Every ability starts full. Call step once per fixed tick; one charge returns per cooldown. onReady runs synchronously for every returned charge, in ascending owner then ability order, with ctx first. Refill, reset and restore emit no events.
Example
ts
import { createAbilities, type Abilities } from 'gameable';
const skills: Abilities = createAbilities({ owners: 1, abilities: [{ id: 'dash', cooldown: 1 }] });
console.log(skills.ready(0, 'dash')); // trueExtends
Methods
ability()
ts
ability(id): number;Resolve an id; unknown ids throw with the known ids.
Parameters
| Parameter | Type |
|---|---|
id | string |
Returns
number
abilityId()
ts
abilityId(index): string;Resolve an index to its id.
Parameters
| Parameter | Type |
|---|---|
index | number |
Returns
string
charges()
ts
charges(owner, ability): number;Available charge count.
Parameters
| Parameter | Type |
|---|---|
owner | number |
ability | string | number |
Returns
number
progress()
ts
progress(owner, ability): number;Current recharge fraction in 0..1; 1 when full.
Parameters
| Parameter | Type |
|---|---|
owner | number |
ability | string | number |
Returns
number
ready()
ts
ready(owner, ability): boolean;Whether at least one charge is available.
Parameters
| Parameter | Type |
|---|---|
owner | number |
ability | string | number |
Returns
boolean
refill()
ts
refill(owner, ability?): void;Fill one ability, or all abilities for this owner, and stop their clocks.
Parameters
| Parameter | Type |
|---|---|
owner | number |
ability? | string | number |
Returns
void
remaining()
ts
remaining(owner, ability): number;Seconds until the next charge, using the timestep captured by use.
Parameters
| Parameter | Type |
|---|---|
owner | number |
ability | string | number |
Returns
number
reset()
ts
reset(): void;Back to the state right after creation. Call from init.
Returns
void
Inherited from
restore()
ts
restore(state, options?): void;Read back what snapshot returned. Throws on a malformed state.
Parameters
| Parameter | Type |
|---|---|
state | unknown |
options? | { crossBuild?: boolean; } |
options.crossBuild? | boolean |
Returns
void
Inherited from
setCooldown()
ts
setCooldown(ability, seconds): void;Change an ability's cooldown for every owner, for example from ctx.rules. It applies from the next recharge clock that starts; a running clock keeps its duration. reset() goes back to the cooldown given at creation.
Parameters
| Parameter | Type |
|---|---|
ability | string | number |
seconds | number |
Returns
void
snapshot()
ts
snapshot(): unknown;Plain JSON-safe data for defineGame({ snapshot }).
Returns
unknown
Inherited from
step()
ts
step(ctx): void;Advance active clocks by one integer step.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
use()
ts
use(
ctx,
owner,
ability
): boolean;Spend one charge; start an idle recharge clock using ctx.dt.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
owner | number |
ability | string | number |
Returns
boolean
AbilitiesOptions
Attribute declarations, fixed storage limits and synchronous borrowed event payloads.
Example
ts
const options: AbilitiesOptions = { attributes: { health: { base: 100, min: 0, max: 100 } } };Properties
attributes
ts
attributes: Record<string, {
base: number;
max?: number;
min?: number;
}>;maxAbilities?
ts
optional maxAbilities?: number;maxEffects?
ts
optional maxEffects?: number;maxTags?
ts
optional maxTags?: number;Methods
onAbilityActivated()?
ts
optional onAbilityActivated(
self,
event,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle |
event | Readonly<AbilityEvent> |
ctx | GameContext |
Returns
void
onAbilityEnded()?
ts
optional onAbilityEnded(
self,
event,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle |
event | Readonly<AbilityEvent> |
ctx | GameContext |
Returns
void
onAbilityFailed()?
ts
optional onAbilityFailed(
self,
event,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle |
event | Readonly<FailedEvent> |
ctx | GameContext |
Returns
void
onAttributeChanged()?
ts
optional onAttributeChanged(
self,
event,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle |
event | Readonly<AttributeEvent> |
ctx | GameContext |
Returns
void
onEffectApplied()?
ts
optional onEffectApplied(
self,
event,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle |
event | Readonly<EffectEvent> |
ctx | GameContext |
Returns
void
onEffectExpired()?
ts
optional onEffectExpired(
self,
event,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle |
event | Readonly<EffectEvent> |
ctx | GameContext |
Returns
void
AbilityDefinition
Ability definition registered at module scope or in init; cooldown starts on activation.
Example
ts
defineAbility({ id: 'dash', cooldown: 1, cost: { attribute: 'stamina', amount: 5 } });Extends
Gate
Properties
blockedByTags?
ts
optional blockedByTags?: readonly string[];Inherited from
ts
Gate.blockedByTagscooldown
ts
cooldown: number;cost
ts
cost: object;amount
ts
amount: number;attribute
ts
attribute: string;duration?
ts
optional duration?: number;grantsTagsWhileActive?
ts
optional grantsTagsWhileActive?: readonly string[];id
ts
id: string;requiresTags?
ts
optional requiresTags?: readonly string[];Inherited from
ts
Gate.requiresTagsActionObject
The thing an action is done at, as the game has it.
Properties
depth
ts
depth: number;height
ts
height: number;Its top over that floor, and its size across and along the way, metres.
id
ts
id: number;The game's own number for it, said back in events.
position
ts
position: Vec3;Its middle, on the floor it stands on, world space.
width
ts
width: number;yaw
ts
yaw: number;The way across it, radians about +Y (0 is +Z).
ActionState
A pooled button reading; read immediately, do not retain across calls.
Example
ts
import type { ActionState } from 'gameable';
const idle: ActionState = { down: false, pressed: false, released: false };Properties
down
ts
down: boolean;pressed
ts
pressed: boolean;released
ts
released: boolean;ActorCatalog
Versioned actor descriptions in class registration order.
Example
ts
const catalog: ActorCatalog = actorCatalog();Properties
catalogVersion
ts
catalogVersion: 1;classes
ts
classes: ActorCatalogEntry[];ActorCatalogEntry
One registered actor's authoring surface.
Example
ts
const entry: ActorCatalogEntry = actorCatalog().classes[0];Properties
category?
ts
optional category?: string;components
ts
components: object[];kind
ts
kind: "mesh" | "character" | "box" | "sphere" | "capsule" | "scene";name
ts
name: string;description?
ts
optional description?: string;events
ts
events: readonly object[];name
ts
name: string;premade
ts
premade: boolean;props
ts
props: Record<string, CatalogProp>;ActorClass
A registered, validated actor definition.
Example
ts
const cls = defineActor('Marker', { components: { root: scene() } });Type Parameters
| Type Parameter | Default type |
|---|---|
P extends object | object |
Properties
name
ts
readonly name: string;Unique registry name.
order
ts
readonly order: readonly string[];Component names sorted parent before child.
prefabs
ts
readonly prefabs: Readonly<Record<string, PrefabDef & PlaceholderSpec>>;Resolved prefab declarations, in component order.
spec
ts
readonly spec: ActorSpec<P>;Declaration and hooks.
ActorComponent
Declarative scene or primitive component.
Example
ts
const component: ActorComponent = scene();Extends
Extended by
Properties
asset?
ts
optional asset?: string;Manifest asset id for a mesh.
attach?
ts
optional attach?: string;Parent component name; defaults to root for non-root components.
Inherited from
body?
ts
optional body?: "static" | "dynamic" | "kinematic";Blocking body motion; defaults to static.
Inherited from
ccd?
ts
optional ccd?: boolean;Continuous collision detection for fast dynamic bodies.
Inherited from
collision?
ts
optional collision?:
| "none"
| "block"
| "Spectator"
| "overlap"
| CollisionSetup
| "NoCollision"
| "BlockAll"
| "OverlapAll"
| "BlockAllDynamic"
| "OverlapAllDynamic"
| "IgnoreOnlyPawn"
| "OverlapOnlyPawn"
| "Pawn"
| "CharacterMesh"
| "PhysicsActor"
| "Destructible"
| "InvisibleWall"
| "InvisibleWallDynamic"
| "Trigger"
| "Ragdoll"
| "Vehicle"
| "UI";Collision response; defaults to block.
Inherited from
dimensions?
ts
optional dimensions?: readonly string[];Spawn-time prop names supplying dimensions: ['halfExtents'] or ['radius', 'halfHeight'].
Inherited from
dims?
ts
optional dims?: readonly number[];Primitive dimensions in metres.
fit?
ts
optional fit?: "mesh" | "box" | "convex-hull";mesh() only: give the mesh a body fitted to its own model, built by the page from the model's geometry and scale once it loads: 'box' its bounds, 'convex-hull' its hull, 'mesh' its triangles (static only).
Inherited from
kind
ts
kind: "mesh" | "character" | "box" | "sphere" | "capsule" | "scene";Component family.
layer?
ts
optional layer?: CollisionLayers;Physics collision layer.
Inherited from
mask?
ts
optional mask?: CollisionLayers;Raw physics mask; cannot accompany a named/custom collision policy.
Inherited from
mass?
ts
optional mass?: number;Dynamic mass in kilograms.
Inherited from
offset?
ts
optional offset?: readonly [number, number, number];Translation in the parent's space.
Inherited from
reportHits?
ts
optional reportHits?: boolean;Request blocking contact callbacks.
Inherited from
rotation?
ts
optional rotation?: Quat;Local quaternion, default identity.
Inherited from
scale?
ts
optional scale?: readonly [number, number, number];Local per-axis scale, default one.
Inherited from
Methods
create()?
ts
optional create(
self,
ctx,
name
): void;Initialize JSON-safe component state during authority spawn.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle |
ctx | GameContext |
name | string |
Returns
void
destroy()?
ts
optional destroy(
self,
ctx,
name
): void;Release component bookkeeping on authority destruction, before entities are despawned.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle |
ctx | GameContext |
name | string |
Returns
void
step()?
ts
optional step(
self,
ctx,
name
): void;Advance on each authority fixed step, before the actor tick.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle |
ctx | GameContext |
name | string |
Returns
void
ActorHandle
A live actor backed by ECS entities.
Example
ts
const actor: ActorHandle = spawnActor(ctx, cls, { position: { x: 0, y: 0, z: 0 } });Type Parameters
| Type Parameter | Default type |
|---|---|
P extends object | object |
Properties
alive
ts
readonly alive: boolean;False once destruction completes.
class
ts
readonly class: ActorClass<P>;Actor class.
entity
ts
readonly entity: number;Root ECS entity.
instigator?
ts
readonly optional instigator?: ActorHandle<object>;Actor responsible for this spawn, if any.
name
ts
readonly name: string;Optional instance name.
owner?
ts
readonly optional owner?: ActorHandle<object>;Owning actor, if any.
persist
ts
readonly persist: "level" | "session";Travel lifetime; session actors join the keep-list.
position
ts
readonly position: Readonly<Vec3>;Borrowed current world position; do not mutate.
props
ts
readonly props: P;Mutable instance properties.
quarantined
ts
readonly quarantined: boolean;True after eight consecutive failing actor steps; rendering and collision continue.
rotation
ts
readonly rotation: Readonly<Quat>;Borrowed current world quaternion; do not mutate.
source?
ts
readonly optional source?: ActorSource;The level entry that placed this actor, when one did: an editor may write it back.
state
ts
readonly state: Record<string, unknown>;JSON-safe instance state, included in actor snapshots. Allocate scratch separately.
Methods
addTag()
ts
addTag(tag): void;Add an instance tag once.
Parameters
| Parameter | Type |
|---|---|
tag | string |
Returns
void
component()
ts
component(name): number;Find a component entity; throws on unknown names.
Parameters
| Parameter | Type |
|---|---|
name | string |
Returns
number
hasTag()
ts
hasTag(tag): boolean;Test an instance tag.
Parameters
| Parameter | Type |
|---|---|
tag | string |
Returns
boolean
removeTag()
ts
removeTag(tag): void;Remove an instance tag.
Parameters
| Parameter | Type |
|---|---|
tag | string |
Returns
void
setPosition()
ts
setPosition(ctx, value): void;Set world position and teleport any body.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
value | Vec3 |
Returns
void
setRotation()
ts
setRotation(ctx, value): void;Set world quaternion and teleport any body.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
value | Quat |
Returns
void
ActorRow
One actor as the snapshot header carries it. The page's editor reads these rows (peekSnapshotHeader) to list actors with their names, classes, props and sources.
Example
ts
const row: ActorRow = { id: 1, entity: 2, class: 'Door', name: 'gate', props: {}, tags: [], components: { root: 2 }, begun: true, remaining: 0, pending: null };Properties
begun
ts
begun: boolean;class
ts
class: string;components
ts
components: Record<string, number>;entity
ts
entity: number;id
ts
id: number;instigator?
ts
optional instigator?: number;name
ts
name: string;owner?
ts
optional owner?: number;pending
ts
pending: EndPlayReason | null;persist?
ts
optional persist?: "level" | "session";props
ts
props: object;remaining
ts
remaining: number;shapes?
ts
optional shapes?: Record<string, readonly number[]>;source?
ts
optional source?: ActorSource;Present when a level file placed the actor.
state?
ts
optional state?: Record<string, unknown>;tags
ts
tags: string[];ActorSource
Where a level file placed an actor: the level's name and the entry's index in its actors. An actor with a source is one an editor may edit and write back; an actor spawned from code has none.
Example
ts
const source: ActorSource = { level: 'main', entry: 3 };Properties
entry
ts
entry: number;The entry's index in the level file's actors.
level
ts
level: string;The level's name: the key in defineGame({ levels }), 'main' for a bare level.
ActorSpawnOptions
Instance overrides used by spawnActor.
Example
ts
const options: ActorSpawnOptions = { position: { x: 0, y: 0, z: 0 }, yaw: 90 };Type Parameters
| Type Parameter | Default type |
|---|---|
P extends object | Record<string, unknown> |
Properties
instigator?
ts
optional instigator?: ActorHandle<object>;Actor responsible for this spawn.
name?
ts
optional name?: string;Instance lookup name.
owner?
ts
optional owner?: ActorHandle<object>;Owning actor.
persist?
ts
optional persist?: "level" | "session";Defaults to level: destroyed on travel.
position
ts
position: Vec3;World root position.
props?
ts
optional props?: Partial<P>;Override default properties.
rotation?
ts
optional rotation?: Quat;World quaternion; takes precedence over yaw.
scale?
ts
optional scale?: readonly [number, number, number];Root scale [x, y, z]. Attached components inherit it; a body does not (a body has no scale), so a box or capsule keeps its authored dims.
source?
ts
optional source?: ActorSource;The level entry this actor came from, when a level file placed it.
tags?
ts
optional tags?: readonly string[];Additional instance tags.
yaw?
ts
optional yaw?: number;Degrees about +Y, zero faces +Z.
ActorSpec
Default components, plain props and authority lifecycle hooks.
Example
ts
const spec: ActorSpec = { components: { root: scene() } };Type Parameters
| Type Parameter | Default type |
|---|---|
P extends object | Record<string, unknown> |
Properties
category?
ts
optional category?: string & object | "Markers" | "Volumes" | "Gameplay" | "Scene";Place Actors group; user classes may supply any string.
components
ts
components: Record<string, ActorComponent>;Exactly one component named root.
description?
ts
optional description?: string;One-sentence purpose for authoring tools.
events?
ts
optional events?: readonly object[];Callbacks or events exposed to game code.
health?
ts
optional health?: number;Initial root hit points.
lifeSpan?
ts
optional lifeSpan?: number;Seconds until destruction; zero means forever.
overlaps?
ts
optional overlaps?: boolean;Generate overlap events on volumes.
props?
ts
optional props?: P;Plain JSON-safe default properties.
propsMeta?
ts
optional propsMeta?: Record<string, PropMeta>;Descriptions and constraints for declared default props.
tags?
ts
optional tags?: readonly string[];Initial tags.
Methods
beginPlay()?
ts
optional beginPlay(self, ctx): void;Runs at the beginning of the next actor step.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
ctx | GameContext |
Returns
void
clientTick()?
ts
optional clientTick(self, ctx): void;Client cosmetic fixed-step update.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
ctx | GameContext |
Returns
void
configureComponents()?
ts
optional configureComponents(props): Readonly<Record<string, Pick<PrefabSpec, "asset" | "character" | "body" | "scale"> & PlaceholderSpec>>;Initial prefab overrides by component name, evaluated from instance props before spawn. Keeps the declared component graph; use for assets, scale and body dimensions.
Parameters
| Parameter | Type |
|---|---|
props | P |
Returns
Readonly<Record<string, Pick<PrefabSpec, "asset" | "character" | "body" | "scale"> & PlaceholderSpec>>
construct()?
ts
optional construct(self, ctx): void;Runs synchronously after spawn properties are applied.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
ctx | GameContext |
Returns
void
endPlay()?
ts
optional endPlay(
self,
ctx,
reason
): void;Runs exactly once on authority destruction.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
ctx | GameContext |
reason | EndPlayReason |
Returns
void
interactPrompt()?
ts
optional interactPrompt(
self,
seat,
ctx
): string | null;Per-player prompt; null excludes this actor from interaction selection.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
seat | number |
ctx | GameContext |
Returns
string | null
onBeginOverlap()?
ts
optional onBeginOverlap(
self,
other,
ctx
): void;An eligible actor or player entered an overlap shape.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
other | ActorOther |
ctx | GameContext |
Returns
void
onClosed()?
ts
optional onClosed(self, ctx): void;A kit door reached its fully closed pose.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
ctx | GameContext |
Returns
void
onDamage()?
ts
optional onDamage(
self,
amount,
info,
ctx
): void;Receives damage before health is reduced.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
amount | number |
info | DamageInfo |
ctx | GameContext |
Returns
void
onEndOverlap()?
ts
optional onEndOverlap(
self,
other,
ctx
): void;An eligible actor or player exited an overlap shape.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
other | ActorOther |
ctx | GameContext |
Returns
void
onHit()?
ts
optional onHit(
self,
other,
ctx,
contact
): void;A reporting blocking component received a contact.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
other | ActorOther |
ctx | GameContext |
contact | Contact |
Returns
void
onInteract()?
ts
optional onInteract(
self,
who,
ctx
): void;Optional interaction callback invoked by an interactable component.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
who | number |
ctx | GameContext |
Returns
void
onLocked()?
ts
optional onLocked(
self,
who,
ctx
): void;A player attempted to open a kit door without its key.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
who | number |
ctx | GameContext |
Returns
void
onOpened()?
ts
optional onOpened(self, ctx): void;A kit door reached its fully open pose.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
ctx | GameContext |
Returns
void
onPassed()?
ts
optional onPassed(
self,
who,
ctx
): void;A player crossed a kit door's closed plane while not closed.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
who | number |
ctx | GameContext |
Returns
void
onPickedUp()?
ts
optional onPickedUp(
self,
who,
ctx
): void;Optional custom pickup callback.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
who | number |
ctx | GameContext |
Returns
void
onPossess()?
ts
optional onPossess(
self,
pawn,
ctx
): void;This controller took a pawn.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
pawn | number |
ctx | GameContext |
Returns
void
onPressed()?
ts
optional onPressed(self, ctx): void;A pressure plate reaches its required occupancy.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
ctx | GameContext |
Returns
void
onReleased()?
ts
optional onReleased(self, ctx): void;A pressure plate releases after its hold time.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
ctx | GameContext |
Returns
void
onSwitched()?
ts
optional onSwitched(
self,
on,
who,
ctx
): void;A lever changes signal; who is the last activator, or zero for a startOn reset.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
on | boolean |
who | number |
ctx | GameContext |
Returns
void
onTravel()?
ts
optional onTravel(
self,
who,
ctx
): void;A level door accepted a crossing; clear or redirect toLevel before loading.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
who | number |
ctx | GameContext |
Returns
void
onUnlocked()?
ts
optional onUnlocked(
self,
who,
ctx
): void;A player unlocked a kit door.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
who | number |
ctx | GameContext |
Returns
void
onUnPossess()?
ts
optional onUnPossess(
self,
pawn,
ctx
): void;This controller let its pawn go.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
pawn | number |
ctx | GameContext |
Returns
void
possessedBy()?
ts
optional possessedBy(
self,
controller,
ctx
): void;This pawn was taken by a controller.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
controller | ActorHandle |
ctx | GameContext |
Returns
void
restoreState()?
ts
optional restoreState(self): void;Rebuild external bookkeeping from state after all actor handles and ownership are restored.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
Returns
void
saveState()?
ts
optional saveState(self): void;Copy external bookkeeping into JSON-safe state immediately before an actor snapshot.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
Returns
void
tick()?
ts
optional tick(self, ctx): void;Authority and solo fixed-step update.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
ctx | GameContext |
Returns
void
unPossessed()?
ts
optional unPossessed(
self,
controller,
ctx
): void;This pawn's controller let it go.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
controller | ActorHandle |
ctx | GameContext |
Returns
void
AddBodyCmd
Create a rigid body or character controller.
Properties
angularDamping
ts
angularDamping: number;body
ts
body: number;entity
ts
entity: number;flags
ts
flags: BodyFlags;friction
ts
friction: number;kind
ts
kind: BodyKind;layer
ts
layer: CollisionLayers;linearDamping
ts
linearDamping: number;mask
ts
mask: CollisionLayers;mass
ts
mass: number;overlapMask?
ts
optional overlapMask?: CollisionLayers;Mixed response companion sensor mask.
position
ts
position: Vec3;restitution
ts
restitution: number;rotation
ts
rotation: Quat;shape
ts
shape: Shape;AddJointCmd
AddJointCmd: radians and metres at the host boundary.
Example
ts
import type { AddJointCmd } from 'gameable';
const value: AddJointCmd = { joint: 1, kind: 'fixed', bodyA: 1, anchor: { x: 0, y: 0, z: 0 }, axis: { x: 0, y: 1, z: 0 }, limitMin: 1, limitMax: 0, maxFriction: 0, axes: [] };Properties
anchor
ts
anchor: Vec3;anchorB?
ts
optional anchorB?: Vec3;axes
ts
axes: readonly JointAxis[];axis
ts
axis: Vec3;bodyA
ts
bodyA: number;bodyB?
ts
optional bodyB?: number;joint
ts
joint: number;kind
ts
kind: JointKind;limitMax
ts
limitMax: number;limitMin
ts
limitMin: number;maxFriction
ts
maxFriction: number;spring?
ts
optional spring?: JointSpring;AddVehicleCmd
Vehicle attachment command; body must already be dynamic.
Example
ts
const command = { body: 1, settings, initialState };Properties
body
ts
body: number;initialState
ts
initialState: VehicleState;settings
ts
settings: VehicleSettings;AIControllerProps
AI tuning, in metres, seconds and degrees.
Example
ts
const props: AIControllerProps = { moveSpeed: 4, acceptanceRadius: 0.5, turnRate: 360, possessOnSpawn: '' };Properties
acceptanceRadius
ts
acceptanceRadius: number;moveSpeed
ts
moveSpeed: number;possessOnSpawn
ts
possessOnSpawn: string;turnRate
ts
turnRate: number;AnimEventData
An animation clip passed a named marker: 'ended' when a once-only clip finished, 'loop' when a looping clip came round (both from the host's mixer), or a marker embedded in the clip.
Properties
clip
ts
clip: string;entity
ts
entity: number;name
ts
name: string;time
ts
time: number;Clip-local time of the marker, seconds.
ApplyImpulseCmd
Apply a one-shot impulse.
Properties
atPoint?
ts
optional atPoint?: Vec3;body
ts
body: number;impulse
ts
impulse: Vec3;ApplyLevelEditsOptions
What applyLevelEdits accepts besides the edits. classes names the game's own classes for a reader that has not loaded the game: the validation knows them, and a reclass to one keeps only the props the edit names, since their props are not known here.
Extends
Properties
catalog?
ts
optional catalog?: ReadonlyMap<string, ActorClass<object>>;Detached declarations for static tools; bypasses the live registry and deprecation logging.
Inherited from
classes?
ts
optional classes?: readonly string[] | "any";The game's own classes (defineActor in its source), for a reader that has not loaded the game's module, such as a tool on Node: a listed class passes as known, with its props unchecked. 'any' accepts every well-formed class name; prefer the list when the names are at hand.
Inherited from
validate?
ts
optional validate?: boolean;Run validateLevel on the result: the premade classes must be imported first.
AssetDesc
Manifest metadata for one asset handle.
Properties
hasCollider
ts
hasCollider: boolean;id
ts
id: number;kind
ts
kind: AssetKind;name
ts
name: string;ready
ts
ready: boolean;rig?
ts
optional rig?: string;tags
ts
tags: readonly string[];AssetLoadedEvent
An asset finished loading.
Properties
asset
ts
asset: number;name
ts
name: string;AttachmentOptions
Local transform shared by actor components and actor attachments.
Example
ts
const local: AttachmentOptions = { offset: [0, 1, 0] };Extended by
Properties
offset?
ts
optional offset?: readonly [number, number, number];Translation in the parent's space.
rotation?
ts
optional rotation?: Quat;Local quaternion, default identity.
scale?
ts
optional scale?: readonly [number, number, number];Local per-axis scale, default one.
AudioComponentOptions
Playback settings for an entity-attached sound.
Example
ts
const options: AudioComponentOptions = { autoPlay: true };Extends
Properties
attach?
ts
optional attach?: string;Parent component name; defaults to root for non-root components.
Inherited from
autoPlay?
ts
optional autoPlay?: boolean;bus?
ts
optional bus?: AudioBus;looping?
ts
optional looping?: boolean;offset?
ts
optional offset?: readonly [number, number, number];Translation in the parent's space.
Inherited from
pitch?
ts
optional pitch?: number;rotation?
ts
optional rotation?: Quat;Local quaternion, default identity.
Inherited from
scale?
ts
optional scale?: readonly [number, number, number];Local per-axis scale, default one.
Inherited from
volume?
ts
optional volume?: number;AudioVolumeProps
Solo listener region settings.
Example
ts
const props: Partial<AudioVolumeProps> = { reverb: 'cave', priority: 2 };Properties
bus
ts
bus: AudioBus;fadeMs
ts
fadeMs: number;halfExtents
ts
halfExtents: [number, number, number];priority
ts
priority: number;reverb
ts
reverb: FxPreset;AutomaticDoorProps
Automatic sliding door tuning.
Example
ts
const props: Partial<AutomaticDoorProps> = { holdSeconds: 1 };Extends
Properties
action
ts
action: string;Inherited from
asset?
ts
optional asset?: string;Inherited from
autoCloseSeconds
ts
autoCloseSeconds: number;Inherited from
SlidingDoorProps.autoCloseSeconds
closePrompt
ts
closePrompt: string;Inherited from
closeSound
ts
closeSound: string;Inherited from
colour
ts
colour: [number, number, number];Inherited from
consumeKey
ts
consumeKey: boolean;Inherited from
enabled
ts
enabled: boolean;Inherited from
facingDegrees
ts
facingDegrees: number;Inherited from
SlidingDoorProps.facingDegrees
height
ts
height: number;Closed doorway height in metres.
Inherited from
holdSeconds
ts
holdSeconds: number;lockedBy
ts
lockedBy: string;Inherited from
lockedMessage
ts
lockedMessage: string;Inherited from
SlidingDoorProps.lockedMessage
lockedPrompt
ts
lockedPrompt: string;Inherited from
lockedSound
ts
lockedSound: string;Inherited from
look
ts
look: "none" | "wood" | "metal";Inherited from
once
ts
once: boolean;Inherited from
openPrompt
ts
openPrompt: string;Inherited from
openSound
ts
openSound: string;Inherited from
opensWhen
ts
opensWhen: string[];Inherited from
panels
ts
panels: 1 | 2;Inherited from
prompt
ts
prompt: string;Inherited from
range
ts
range: number;Inherited from
seconds
ts
seconds: number;Inherited from
slide
ts
slide: "left" | "right" | "up";Inherited from
startOpen
ts
startOpen: boolean;Inherited from
stayOpen
ts
stayOpen: boolean;Inherited from
thickness
ts
thickness: number;Leaf thickness in metres.
Inherited from
toggledBy
ts
toggledBy: "signal" | "proximity" | "interact";Inherited from
travel
ts
travel: number;Inherited from
width
ts
width: number;Closed doorway width in metres.
Inherited from
Axis2
A two-axis reading. Each facade returns its own object, the same one every call.
Properties
x
ts
x: number;y
ts
y: number;BeatEvent
beat-event payload.
Example
ts
`const value: BeatEvent = { beat: 0, bar: 0, beatInBar: 0, lateMs: 4 };`Properties
bar
ts
bar: number;Bar number from zero.
beat
ts
beat: number;Beat number from zero.
beatInBar
ts
beatInBar: number;Beat within the bar.
lateMs
ts
lateMs: number;Milliseconds since the beat was heard.
BehaviorTree
A compiled tree with independent, preallocated memory for each entity.
Example
ts
import { bt, createBehaviorTree, type BehaviorTree } from 'gameable';
const tree: BehaviorTree<null> = createBehaviorTree(bt.wait(1));
tree.tick(null, 0, 1 / 60);Type Parameters
| Type Parameter |
|---|
C |
Properties
nodeCount
ts
readonly nodeCount: number;Number of node occurrences in the compiled tree.
Methods
reset()
ts
reset(entity): void;Forget all timers, memory and stamps for this entity.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | An integer in [0, maxEntities). |
Returns
void
Nothing.
tick()
ts
tick(
ctx,
entity,
dt
): BtStatus;Tick once per fixed step for this entity. Game callbacks must not allocate.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | C | The game's context. |
entity | number | An integer in [0, maxEntities). |
dt | number | Fixed-step seconds. |
Returns
The root status.
BodyFlags
Per-body behaviour switches. Omitted keys lower as false.
Properties
ccd?
ts
optional ccd?: boolean;debugDraw?
ts
optional debugDraw?: boolean;lockRotation?
ts
optional lockRotation?: boolean;noSleep?
ts
optional noSleep?: boolean;physicsOnly?
ts
optional physicsOnly?: boolean;Simulates but is excluded from queries.
queryOnly?
ts
optional queryOnly?: boolean;Found by queries without simulation response.
reportContacts?
ts
optional reportContacts?: boolean;sensor?
ts
optional sensor?: boolean;BodySpec
The physics body a prefab carries.
Properties
collision?
ts
optional collision?:
| "Spectator"
| CollisionSetup
| "NoCollision"
| "BlockAll"
| "OverlapAll"
| "BlockAllDynamic"
| "OverlapAllDynamic"
| "IgnoreOnlyPawn"
| "OverlapOnlyPawn"
| "Pawn"
| "CharacterMesh"
| "PhysicsActor"
| "Destructible"
| "InvisibleWall"
| "InvisibleWallDynamic"
| "Trigger"
| "Ragdoll"
| "Vehicle"
| "UI";Collision policy; excludes raw layer/mask.
dims?
ts
optional dims?: readonly number[];Dimensions: box half-extents; sphere [r]; capsule/cylinder [r, cylinder half-height]; plane normal.
fit?
ts
optional fit?: string | boolean;Shape built from the model as drawn: true (asset) or a model id; box, convex-hull, mesh.
flags?
ts
optional flags?: BodyFlags;Per-body switches.
friction?
ts
optional friction?: number;Coulomb friction. Default 0.5.
kind
ts
kind: BodyKind;Body kind; character uses CharacterVirtual.
layer?
ts
optional layer?: CollisionLayers;What this body is. Default { defaultLayer: true }.
mask?
ts
optional mask?: CollisionLayers;What this body collides with. Default every layer.
mass?
ts
optional mass?: number;Mass in kg (dynamic only). Default 1.
restitution?
ts
optional restitution?: number;Bounciness in 0..1. Default 0.
shape
ts
shape: ShapeKind;Collision shape family.
BtNode
An opaque, stateless description. Build once, including at module scope.
Example
ts
import { bt, type BtNode } from 'gameable';
const pause: BtNode<null> = bt.wait(1);Type Parameters
| Type Parameter |
|---|
C |
BurstOptions
Burst direction, size, brightness and colour overrides.
Example
ts
import { vfx, type BurstOptions } from 'gameable';
const options: BurstOptions = { scale: 2 };
vfx.burst('explosion', { x: 0, y: 1, z: 0 }, options);Extended by
Properties
direction?
ts
optional direction?: Vec3;Emission direction; absent uses the preset's own direction.
intensity?
ts
optional intensity?: number;Count and brightness multiplier, default 1.
scale?
ts
optional scale?: number;Size multiplier, default 1.
tint?
ts
optional tint?: Vec3;Linear RGB override; values over 1 glow under bloom.
CameraState
The camera the host should render from this frame.
Properties
armLength
ts
armLength: number;far
ts
far: number;follow?
ts
optional follow?: number;fovYDeg
ts
fovYDeg: number;mode
ts
mode: CameraMode;near
ts
near: number;offset
ts
offset: Vec3;position
ts
position: Vec3;projection
ts
projection: ProjectionKind;rotation
ts
rotation: Quat;target?
ts
optional target?: Vec3;Capsule
Capsule dimensions; halfHeight excludes the hemispheres.
Example
ts
const capsule: Capsule = { radius: 0.35, halfHeight: 0.55 };Properties
halfHeight
ts
halfHeight: number;radius
ts
radius: number;CatalogProp
A detached JSON property default and its authoring metadata.
Example
ts
const prop: CatalogProp = { default: 2, description: 'Reach.', type: 'number' };Extends
Properties
const?
ts
optional const?: boolean;Restrict a boolean branch to one literal value.
Inherited from
default
ts
default: unknown;description
ts
description: string;Inherited from
fields?
ts
optional fields?: Record<string, PropMeta>;Inherited from
group?
ts
optional group?: string;Shared reference table; actor-specific differences remain documented on the actor.
Inherited from
items?
ts
optional items?: PropMeta;Inherited from
max?
ts
optional max?: number;Inherited from
min?
ts
optional min?: number;Inherited from
nullable?
ts
optional nullable?: boolean;Accept null in addition to the described shape.
Inherited from
oneOf?
ts
optional oneOf?: readonly PropMeta[];Inherited from
optional?
ts
optional optional?: boolean;Allow this field to be omitted from a fixed-shape object.
Inherited from
type?
ts
optional type?:
| "string"
| "number"
| "boolean"
| "object"
| "vec3"
| "color"
| "enum"
| "array";Inherited from
unit?
ts
optional unit?: string;Inherited from
values?
ts
optional values?: readonly string[];Inherited from
CharacterMovement
Mutable movement state, owned independently by each mover.
Example
ts
const speed = Math.hypot(movement.velocity.x, movement.velocity.z);Properties
currentFloor
ts
currentFloor: FloorResult;forceNextFloorCheck
ts
forceNextFloorCheck: boolean;justTeleported
ts
justTeleported: boolean;mode
ts
mode: "walking" | "falling";settings
ts
settings: CharacterMovementSettings;velocity
ts
velocity: Vec3;work
ts
readonly work: MovementWork;Preallocated algorithm scratch; do not modify.
CharacterMovementOptions
Movement solver settings plus root capsule and facing options. Dims override capsule settings.
Example
ts
const options: CharacterMovementOptions = { maxWalkSpeed: 4, rotationRate: 540 };Extends
Partial<CharacterMovementSettings>
Properties
airControl?
ts
optional airControl?: number;Inherited from
CharacterMovementSettings.airControl
airControlBoostMultiplier?
ts
optional airControlBoostMultiplier?: number;Inherited from
CharacterMovementSettings.airControlBoostMultiplier
airControlBoostVelocityThreshold?
ts
optional airControlBoostVelocityThreshold?: number;Inherited from
CharacterMovementSettings.airControlBoostVelocityThreshold
alwaysCheckFloor?
ts
optional alwaysCheckFloor?: boolean;Inherited from
CharacterMovementSettings.alwaysCheckFloor
brakeToStopVelocity?
ts
optional brakeToStopVelocity?: number;Inherited from
CharacterMovementSettings.brakeToStopVelocity
brakingDecelerationFalling?
ts
optional brakingDecelerationFalling?: number;Inherited from
CharacterMovementSettings.brakingDecelerationFalling
brakingDecelerationWalking?
ts
optional brakingDecelerationWalking?: number;Inherited from
CharacterMovementSettings.brakingDecelerationWalking
brakingFriction?
ts
optional brakingFriction?: number;Inherited from
CharacterMovementSettings.brakingFriction
brakingFrictionFactor?
ts
optional brakingFrictionFactor?: number;Inherited from
CharacterMovementSettings.brakingFrictionFactor
brakingSubStepTime?
ts
optional brakingSubStepTime?: number;Inherited from
CharacterMovementSettings.brakingSubStepTime
canWalkOffLedges?
ts
optional canWalkOffLedges?: boolean;Inherited from
CharacterMovementSettings.canWalkOffLedges
canWalkOffLedgesWhenCrouching?
ts
optional canWalkOffLedgesWhenCrouching?: boolean;Inherited from
CharacterMovementSettings.canWalkOffLedgesWhenCrouching
capsuleHalfHeight?
ts
optional capsuleHalfHeight?: number;Inherited from
CharacterMovementSettings.capsuleHalfHeight
capsuleRadius?
ts
optional capsuleRadius?: number;Inherited from
CharacterMovementSettings.capsuleRadius
collision?
ts
optional collision?:
| "none"
| "block"
| "Spectator"
| "overlap"
| CollisionSetup
| "NoCollision"
| "BlockAll"
| "OverlapAll"
| "BlockAllDynamic"
| "OverlapAllDynamic"
| "IgnoreOnlyPawn"
| "OverlapOnlyPawn"
| "Pawn"
| "CharacterMesh"
| "PhysicsActor"
| "Destructible"
| "InvisibleWall"
| "InvisibleWallDynamic"
| "Trigger"
| "Ragdoll"
| "Vehicle"
| "UI";dims?
ts
optional dims?: readonly [number, number];enablePhysicsInteraction?
ts
optional enablePhysicsInteraction?: boolean;Inherited from
CharacterMovementSettings.enablePhysicsInteraction
fallingLateralFriction?
ts
optional fallingLateralFriction?: number;Inherited from
CharacterMovementSettings.fallingLateralFriction
forceNextFloorCheck?
ts
optional forceNextFloorCheck?: boolean;Inherited from
CharacterMovementSettings.forceNextFloorCheck
gravity?
ts
optional gravity?: number;Inherited from
CharacterMovementSettings.gravity
gravityScale?
ts
optional gravityScale?: number;Inherited from
CharacterMovementSettings.gravityScale
groundFriction?
ts
optional groundFriction?: number;Inherited from
CharacterMovementSettings.groundFriction
initialPushForceFactor?
ts
optional initialPushForceFactor?: number;Inherited from
CharacterMovementSettings.initialPushForceFactor
jumpZVelocity?
ts
optional jumpZVelocity?: number;Inherited from
CharacterMovementSettings.jumpZVelocity
ledgeCheckThreshold?
ts
optional ledgeCheckThreshold?: number;Inherited from
CharacterMovementSettings.ledgeCheckThreshold
maintainHorizontalGroundVelocity?
ts
optional maintainHorizontalGroundVelocity?: boolean;Inherited from
CharacterMovementSettings.maintainHorizontalGroundVelocity
mass?
ts
optional mass?: number;Inherited from
CharacterMovementSettings.mass
maxAcceleration?
ts
optional maxAcceleration?: number;Inherited from
CharacterMovementSettings.maxAcceleration
maxDepenetrationWithGeometry?
ts
optional maxDepenetrationWithGeometry?: number;Inherited from
CharacterMovementSettings.maxDepenetrationWithGeometry
maxDepenetrationWithGeometryAsProxy?
ts
optional maxDepenetrationWithGeometryAsProxy?: number;Inherited from
CharacterMovementSettings.maxDepenetrationWithGeometryAsProxy
maxDepenetrationWithPawn?
ts
optional maxDepenetrationWithPawn?: number;Inherited from
CharacterMovementSettings.maxDepenetrationWithPawn
maxDepenetrationWithPawnAsProxy?
ts
optional maxDepenetrationWithPawnAsProxy?: number;Inherited from
CharacterMovementSettings.maxDepenetrationWithPawnAsProxy
maxFloorDist?
ts
optional maxFloorDist?: number;Inherited from
CharacterMovementSettings.maxFloorDist
maxSimulationIterations?
ts
optional maxSimulationIterations?: number;Inherited from
CharacterMovementSettings.maxSimulationIterations
maxSimulationTimeStep?
ts
optional maxSimulationTimeStep?: number;Inherited from
CharacterMovementSettings.maxSimulationTimeStep
maxStepHeight?
ts
optional maxStepHeight?: number;Inherited from
CharacterMovementSettings.maxStepHeight
maxStepSideZ?
ts
optional maxStepSideZ?: number;Inherited from
CharacterMovementSettings.maxStepSideZ
maxWalkSpeed?
ts
optional maxWalkSpeed?: number;Inherited from
CharacterMovementSettings.maxWalkSpeed
maxWalkSpeedCrouched?
ts
optional maxWalkSpeedCrouched?: number;Inherited from
CharacterMovementSettings.maxWalkSpeedCrouched
minAnalogWalkSpeed?
ts
optional minAnalogWalkSpeed?: number;Inherited from
CharacterMovementSettings.minAnalogWalkSpeed
minFloorDist?
ts
optional minFloorDist?: number;Inherited from
CharacterMovementSettings.minFloorDist
minTickTime?
ts
optional minTickTime?: number;Inherited from
CharacterMovementSettings.minTickTime
orientRotationToMovement?
ts
optional orientRotationToMovement?: boolean;penetrationOverlapCheckInflation?
ts
optional penetrationOverlapCheckInflation?: number;Inherited from
CharacterMovementSettings.penetrationOverlapCheckInflation
penetrationPullbackDistance?
ts
optional penetrationPullbackDistance?: number;Inherited from
CharacterMovementSettings.penetrationPullbackDistance
perchAdditionalHeight?
ts
optional perchAdditionalHeight?: number;Inherited from
CharacterMovementSettings.perchAdditionalHeight
perchRadiusThreshold?
ts
optional perchRadiusThreshold?: number;Inherited from
CharacterMovementSettings.perchRadiusThreshold
planeZ?
ts
optional planeZ?: number;Lock movement to this world Z plane.
pushForceFactor?
ts
optional pushForceFactor?: number;Inherited from
CharacterMovementSettings.pushForceFactor
repulsionForce?
ts
optional repulsionForce?: number;Inherited from
CharacterMovementSettings.repulsionForce
rotationRate?
ts
optional rotationRate?: number;standingDownwardForceScale?
ts
optional standingDownwardForceScale?: number;Inherited from
CharacterMovementSettings.standingDownwardForceScale
sweepEdgeRejectDistance?
ts
optional sweepEdgeRejectDistance?: number;Inherited from
CharacterMovementSettings.sweepEdgeRejectDistance
terminalVelocity?
ts
optional terminalVelocity?: number;Inherited from
CharacterMovementSettings.terminalVelocity
useFlatBaseForFloorChecks?
ts
optional useFlatBaseForFloorChecks?: boolean;Inherited from
CharacterMovementSettings.useFlatBaseForFloorChecks
useRVOAvoidance?
ts
optional useRVOAvoidance?: boolean;Inherited from
CharacterMovementSettings.useRVOAvoidance
useSeparateBrakingFriction?
ts
optional useSeparateBrakingFriction?: boolean;Inherited from
CharacterMovementSettings.useSeparateBrakingFriction
verticalSlopeNormalZ?
ts
optional verticalSlopeNormalZ?: number;Inherited from
CharacterMovementSettings.verticalSlopeNormalZ
walkableFloorAngle?
ts
optional walkableFloorAngle?: number;Inherited from
CharacterMovementSettings.walkableFloorAngle
walkableFloorZ?
ts
optional walkableFloorZ?: number;Inherited from
CharacterMovementSettings.walkableFloorZ
CharacterMovementSettings
Metre-based movement settings. Gravity and terminal speed are port/world inputs.
Example
ts
const settings: Partial<CharacterMovementSettings> = { maxWalkSpeed: 4 };Properties
airControl
ts
airControl: number;airControlBoostMultiplier
ts
airControlBoostMultiplier: number;airControlBoostVelocityThreshold
ts
airControlBoostVelocityThreshold: number;alwaysCheckFloor
ts
alwaysCheckFloor: boolean;brakeToStopVelocity
ts
brakeToStopVelocity: number;brakingDecelerationFalling
ts
brakingDecelerationFalling: number;brakingDecelerationWalking
ts
brakingDecelerationWalking: number;brakingFriction
ts
brakingFriction: number;brakingFrictionFactor
ts
brakingFrictionFactor: number;brakingSubStepTime
ts
brakingSubStepTime: number;canWalkOffLedges
ts
canWalkOffLedges: boolean;canWalkOffLedgesWhenCrouching
ts
canWalkOffLedgesWhenCrouching: boolean;capsuleHalfHeight
ts
capsuleHalfHeight: number;capsuleRadius
ts
capsuleRadius: number;enablePhysicsInteraction
ts
enablePhysicsInteraction: boolean;fallingLateralFriction
ts
fallingLateralFriction: number;forceNextFloorCheck
ts
forceNextFloorCheck: boolean;gravity
ts
gravity: number;gravityScale
ts
gravityScale: number;groundFriction
ts
groundFriction: number;initialPushForceFactor
ts
initialPushForceFactor: number;jumpZVelocity
ts
jumpZVelocity: number;ledgeCheckThreshold
ts
ledgeCheckThreshold: number;maintainHorizontalGroundVelocity
ts
maintainHorizontalGroundVelocity: boolean;mass
ts
mass: number;maxAcceleration
ts
maxAcceleration: number;maxDepenetrationWithGeometry
ts
maxDepenetrationWithGeometry: number;maxDepenetrationWithGeometryAsProxy
ts
maxDepenetrationWithGeometryAsProxy: number;maxDepenetrationWithPawn
ts
maxDepenetrationWithPawn: number;maxDepenetrationWithPawnAsProxy
ts
maxDepenetrationWithPawnAsProxy: number;maxFloorDist
ts
maxFloorDist: number;maxSimulationIterations
ts
maxSimulationIterations: number;maxSimulationTimeStep
ts
maxSimulationTimeStep: number;maxStepHeight
ts
maxStepHeight: number;maxStepSideZ
ts
maxStepSideZ: number;maxWalkSpeed
ts
maxWalkSpeed: number;maxWalkSpeedCrouched
ts
maxWalkSpeedCrouched: number;minAnalogWalkSpeed
ts
minAnalogWalkSpeed: number;minFloorDist
ts
minFloorDist: number;minTickTime
ts
minTickTime: number;penetrationOverlapCheckInflation
ts
penetrationOverlapCheckInflation: number;penetrationPullbackDistance
ts
penetrationPullbackDistance: number;perchAdditionalHeight
ts
perchAdditionalHeight: number;perchRadiusThreshold
ts
perchRadiusThreshold: number;pushForceFactor
ts
pushForceFactor: number;repulsionForce
ts
repulsionForce: number;standingDownwardForceScale
ts
standingDownwardForceScale: number;sweepEdgeRejectDistance
ts
sweepEdgeRejectDistance: number;terminalVelocity
ts
terminalVelocity: number;useFlatBaseForFloorChecks
ts
useFlatBaseForFloorChecks: boolean;useRVOAvoidance
ts
useRVOAvoidance: boolean;useSeparateBrakingFriction
ts
useSeparateBrakingFriction: boolean;verticalSlopeNormalZ
ts
verticalSlopeNormalZ: number;walkableFloorAngle
ts
walkableFloorAngle: number;walkableFloorZ
ts
walkableFloorZ: number;CharacterReadyEvent
A character bundle finished loading and reported its expression space.
Properties
bundle
ts
bundle: number;entity
ts
entity: number;expressionDim
ts
expressionDim: number;space
ts
space: ExpressionSpace;CharactersOptions
Options for the characters feature.
Properties
motion?
ts
optional motion?:
| false
| {
actions?: boolean;
carry?: boolean;
feet?: "performed" | "own";
footPlant?: boolean;
legs?: "performed" | "bent";
naturalness?: number;
responsiveness?: number;
set?: string;
stand?: "middle" | "sole" | "bearing";
standing?: "set" | "own";
turn?: "easy" | "quick";
};The movement system (exported characters moved by whole takes of a performer, their feet held where they land): on by default. false turns it off for the game: every character walks by the clips' blend, as before. An object keeps it on and sets how it moves every character: whether the take carries the walker (carry, default true), and the two dials, each 0 to 1, default 0.6 (responsiveness: how hard a character follows what is asked; naturalness: how far it may leave its place to move as the take does), what it stands on at rest (standing: 'own', the character's own captured stance, the default; 'set', the takes' own standing) and whether the feet are held (footPlant).
Union Members
false
Type Literal
ts
{
actions?: boolean;
carry?: boolean;
feet?: "performed" | "own";
footPlant?: boolean;
legs?: "performed" | "bent";
naturalness?: number;
responsiveness?: number;
set?: string;
stand?: "middle" | "sole" | "bearing";
standing?: "set" | "own";
turn?: "easy" | "quick";
}actions?
ts
optional actions?: boolean;Actions of the character's set (a hurdle, a jump: character.do). Off by default: the default is standing, walking, running, starts, stops, turns and the foot hold.
carry?
ts
optional carry?: boolean;feet?
ts
optional feet?: "performed" | "own";How a move's ankle and toe turns are laid on a character's feet: 'performed' (the default: the performer's joint turns as they stand) or 'own' (laid on the character's own stand's sole, so a character made on a raised heel or in a shoe rolls over its own sole as the performer does over his). Left out, nothing changes.
footPlant?
ts
optional footPlant?: boolean;legs?
ts
optional legs?: "performed" | "bent";How straight a leg the foot hold moves may be: 'bent' (the default: never over 0.995 of its length, which dips the hips about 4 mm once a walking step) or 'performed' (as straight as the move has the leg, and no straighter). Left out, nothing changes.
naturalness?
ts
optional naturalness?: number;responsiveness?
ts
optional responsiveness?: number;set?
ts
optional set?: string;The set every character starts on: 'shared' (the engine's shared set alone: a character's own takes are not laid over it), 'own', or a name the page gave a set. Absent: a character's own takes laid over the shared set, part by part.
stand?
ts
optional stand?: "middle" | "sole" | "bearing";How a walk is stood on the floor: 'middle' (the default: by the middle of the joints of the feet marked down), 'sole' (on the character's own lowest sole point of those feet) or 'bearing' (on her lowest sole point, the toe's end too, of every foot from the frame its sole is down to the frame its toes leave). Only the height the hips are drawn at changes; left out, nothing does.
standing?
ts
optional standing?: "set" | "own";turn?
ts
optional turn?: "easy" | "quick";The pace of a turn on the spot, where the set marks its turns by pace: 'quick' (the default) or 'easy' (unhurried: a character in a room).
CharacterStore
Splat character bundle handle.
Properties
bundle
ts
bundle: Uint32Array;Character bundle asset handle.
dirty
ts
dirty: Uint8Array;Non-zero when the host has not yet seen the current value.
ChaseOptions
Pursuit prediction in seconds/metres. A ram lasts 0.5 seconds; cooldown starts at its onset.
Example
ts
chaseVehicle(ctx, ai, suspect, { leadTime: 0.5, ramCooldown: 4 });Extends
Properties
acceptanceRadius?
ts
optional acceptanceRadius?: number;Inherited from
leadTime?
ts
optional leadTime?: number;maxLead?
ts
optional maxLead?: number;ramCooldown?
ts
optional ramCooldown?: number;ramDistance?
ts
optional ramDistance?: number;speed?
ts
optional speed?: number;Inherited from
stopAtTarget?
ts
optional stopAtTarget?: boolean;Inherited from
tuning?
ts
optional tuning?: Partial<DriveTuning>;Inherited from
CheckpointModuleOptions
Negative-Z checkpoint thresholds and fall recovery.
Example
ts
import type { CheckpointModuleOptions } from 'gameable';
const options: CheckpointModuleOptions = { axis: 'z', direction: 'decreasing', thresholds: [-22], points: [[0,3,-23]], spawns: [[0,3,0]], maxAbsX: 4, minY: 2, fallY: -5, lobbyRespawn: 'seat-start', resetKnock: true };
console.log(options.thresholds);Properties
axis
ts
axis: "z";direction
ts
direction: "decreasing";fallY
ts
fallY: number;lobbyRespawn
ts
lobbyRespawn: "seat-start";maxAbsX
ts
maxAbsX: number;minY
ts
minY: number;points
ts
points: readonly readonly number[][];resetKnock
ts
resetKnock: boolean;spawns
ts
spawns: readonly readonly number[][];thresholds
ts
thresholds: readonly number[];CheckpointProps
Ordered checkpoint data; a higher order never regresses to a lower checkpoint.
Example
ts
const props: Partial<CheckpointProps> = {order: 1, once: true};Properties
forwardOnly
ts
forwardOnly: boolean;mode
ts
mode: "ordered" | "lap";once
ts
once: boolean;order
ts
order: number;raceId
ts
raceId: string;respawnOffset
ts
respawnOffset: [number, number, number];CircuitGate
Gate plane faces local +Z; angles are radians, extents are half sizes.
Example
ts
const gate: CircuitGate = { position: [0,0,10], yaw: 0, halfExtents: [3,2,1] };Properties
forwardOnly?
ts
optional forwardOnly?: boolean;Accept reverse crossings too when false; defaults to true.
halfExtents
ts
halfExtents: CircuitPoint;position
ts
position: CircuitPoint;respawnOffset?
ts
optional respawnOffset?: CircuitPoint;Local safe-pose offset; defaults to [0, 1, -1].
yaw
ts
yaw: number;CircuitOptions
Circuit configuration; array order is dense gate order, with gate zero the start.
Example
ts
const options: CircuitOptions = {id:'race',laps:3,maxRacers:8,gates:[{position:[0,0,0],yaw:0,halfExtents:[3,2,1]},{position:[0,0,20],yaw:0,halfExtents:[3,2,1]}]};Properties
gates
ts
gates: readonly (string | CircuitGate)[];Named box actors resolve once at init; explicit gates can be used without actors.
id
ts
id: string;laps
ts
laps: number;line?
ts
optional line?:
| {
actor: string;
component: string;
}
| readonly readonly CircuitPoint[][];One authored polyline per gate-to-next-gate section, or a named spline sampled at init.
maxRacers
ts
maxRacers: number;onRespawn?
ts
optional onRespawn?: (ctx, racer) => void;Runs after pawn respawn; vehicle adapters can clear their simulation here.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
racer | Readonly<RaceProgress> |
Returns
void
racerRadius?
ts
optional racerRadius?: number;Occupancy sphere radius in metres; defaults to 0.5.
resetOnDisconnect?
ts
optional resetOnDisconnect?: boolean;CircuitRace
Circuit lifecycle and borrowed standings. Teleport adapters must call markTeleported before the next system.
Example
ts
const configure = (o: CircuitOptions): CircuitRace => createCircuitRace(o);Properties
standings
ts
readonly standings: readonly Readonly<RaceProgress>[];Methods
bindEntity()
ts
bindEntity(racer, entity): void;Parameters
| Parameter | Type |
|---|---|
racer | number |
entity | number |
Returns
void
crossGate()
ts
crossGate(
ctx,
racer,
gate,
fraction
): boolean;Internal adapter entry: must supply a genuine forward crossing, in global fraction/id order.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
racer | number |
gate | number |
fraction | number |
Returns
boolean
disconnect()
ts
disconnect(racer): void;Parameters
| Parameter | Type |
|---|---|
racer | number |
Returns
void
init()
ts
init(ctx): void;Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
markTeleported()
ts
markTeleported(racer): void;Parameters
| Parameter | Type |
|---|---|
racer | number |
Returns
void
progress()
ts
progress(racer): Readonly<RaceProgress> | undefined;Parameters
| Parameter | Type |
|---|---|
racer | number |
Returns
Readonly<RaceProgress> | undefined
register()
ts
register(ctx, racer): RaceProgress;Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
racer | CircuitRacer |
Returns
reset()
ts
reset(): void;Returns
void
respawn()
ts
respawn(ctx, racer): boolean;Respawn at the last accepted gate. Returns false and retries every 0.25s while occupied.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
racer | number |
Returns
boolean
restore()
ts
restore(state): void;Parameters
| Parameter | Type |
|---|---|
state | unknown |
Returns
void
snapshot()
ts
snapshot(): unknown;Returns
unknown
spectate()
ts
spectate(racer, value): void;Parameters
| Parameter | Type |
|---|---|
racer | number |
value | boolean |
Returns
void
system()
ts
system(ctx): void;Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
unregister()
ts
unregister(racer): void;Parameters
| Parameter | Type |
|---|---|
racer | number |
Returns
void
CircuitRacer
Stable identity registration. Reuse the racer id only for the same person; unregister on seat reuse.
Example
ts
const racer: CircuitRacer = {racer:42,seat:0,entity:12};Extended by
Properties
entity
ts
entity: number;racer
ts
racer: number;seat
ts
seat: number | null;CircuitStandings
Full circuit HUD publication. Revision advances only when a public row changes.
Example
ts
const show = (state: CircuitStandings) => console.log(state.revision, state.rows);Properties
revision
ts
readonly revision: number;rows
ts
readonly rows: readonly Readonly<Omit<RaceProgress, "respawnPose">>[];CollisionCell
Solid grid cell, with height measured from ground y=0 in metres.
Example
ts
const cell: CollisionCell = { x: 0, z: 0, height: 2 };Properties
height
ts
height: number;x
ts
x: number;z
ts
z: number;CollisionLayers
Broad-phase layer set. Omitted keys lower as false.
Properties
character?
ts
optional character?: boolean;debris?
ts
optional debris?: boolean;defaultLayer?
ts
optional defaultLayer?: boolean;enemy?
ts
optional enemy?: boolean;pickup?
ts
optional pickup?: boolean;player?
ts
optional player?: boolean;projectile?
ts
optional projectile?: boolean;staticGeometry?
ts
optional staticGeometry?: boolean;trigger?
ts
optional trigger?: boolean;user0?
ts
optional user0?: boolean;user1?
ts
optional user1?: boolean;user2?
ts
optional user2?: boolean;user3?
ts
optional user3?: boolean;user4?
ts
optional user4?: boolean;user5?
ts
optional user5?: boolean;water?
ts
optional water?: boolean;CollisionSetup
Complete per-component collision policy.
Example
ts
const setup: CollisionSetup = { objectType: 'pawn', enabled: 'query', responses: { default: 'block' } };Properties
enabled
ts
enabled: CollisionEnabled;objectType
ts
objectType: CollisionChannel;responses
ts
responses: CollisionResponses;CollisionShapeSetup
Shape routing keeps the simple aggregate separate from triangle geometry.
Example
ts
const setup: CollisionShapeSetup<string> = { simple: 'capsule', complex: 'triangles', collisionTraceFlag: 'simpleAndComplex' };Type Parameters
| Type Parameter |
|---|
T |
Properties
collisionTraceFlag
ts
collisionTraceFlag: CollisionTraceFlag;complex
ts
complex: T;defaultFlag?
ts
optional defaultFlag?: "simpleAndComplex" | "simpleAsComplex" | "complexAsSimple";Required for useDefault; must be a resolved project choice.
simple
ts
simple: T;traceComplex?
ts
optional traceComplex?: boolean;Request complex geometry for this query. Default false.
ComponentCatalog
Versioned component factory descriptions in registration order.
Example
ts
const catalog: ComponentCatalog = componentCatalog();Properties
catalogVersion
ts
catalogVersion: 1;components
ts
components: ComponentCatalogEntry[];ComponentCatalogEntry
JSON-safe metadata for a reusable component factory. Callback parameters are listed as events.
Example
ts
const entry: ComponentCatalogEntry = { name: 'scene', description: 'Transform.', options: {} };Properties
description
ts
description: string;events?
ts
optional events?: readonly object[];name
ts
name: string;options
ts
options: Record<string, PropMeta>;ComponentOptions
Options common to scene components.
Example
ts
const options: ComponentOptions = { attach: 'root' };Extends
Extended by
Properties
attach?
ts
optional attach?: string;Parent component name; defaults to root for non-root components.
offset?
ts
optional offset?: readonly [number, number, number];Translation in the parent's space.
Inherited from
rotation?
ts
optional rotation?: Quat;Local quaternion, default identity.
Inherited from
scale?
ts
optional scale?: readonly [number, number, number];Local per-axis scale, default one.
Inherited from
Contact
One reported contact between two bodies.
Properties
a
ts
a: number;b
ts
b: number;entityA
ts
entityA: number;entityB
ts
entityB: number;impulse
ts
impulse: number;normal
ts
normal: Vec3;overlap?
ts
optional overlap?: boolean;True for a mixed-profile companion overlap.
phase
ts
phase: ContactPhase;point
ts
point: Vec3;ConversationCmd
Structural interview controls; service addresses stay in host configuration.
Properties
action
ts
action:
| "end"
| "start"
| "ask"
| "interrupt"
| "microphone-on"
| "microphone-off";character
ts
character: string;entity
ts
entity: number;text
ts
text: string;ConversationEvent
Low-frequency conversation UI/input event. No audio or facial frames cross WIT.
Properties
entity
ts
entity: number;kind
ts
kind: "error" | "status" | "input" | "subtitle" | "story";text
ts
text: string;Story events carry the versioned full snapshot as JSON.
ConversationStory
A talking character's story as the game reads it: the conversation service's snapshot after a turn, sent as the text of a story conversation event. The service judges the objectives and player state; the game decides what they mean (a permission, a refusal, a clue) and owns every outcome.
Properties
completedObjectives
ts
completedObjectives: string[];Objective ids the service judged complete.
currentPhase
ts
currentPhase: string;The story phase now.
playerState
ts
playerState: Record<string, string>;What the service judged about the player (player_state objectives), as plain strings.
revision
ts
revision: number;Rises with every snapshot of a session; an older one than the last read is stale.
transitionCause
ts
transitionCause: string;Why the phase last changed, as the service put it.
Crowd
A fixed-capacity crowd. Live slots are visited in ascending order; removing an agent leaves a hole, reused by the next add. Queries write caller-owned storage.
Example
ts
import { createCrowd, createNavGrid, type Crowd } from 'gameable';
const nav = createNavGrid({ min: [-10, -10], max: [10, 10] });
nav.buildFlat();
const crowd: Crowd = createCrowd(nav);
crowd.add(1);
crowd.moveTo(1, 5, 5);
crowd.step(1 / 60);Properties
count
ts
readonly count: number;Number of live agents.
Methods
add()
ts
add(entity, options?): boolean;Add an entity with optional agent tuning.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
options? | CrowdAgentOptions | Agent tuning. |
Returns
boolean
False if full, invalid or present.
follow()
ts
follow(entity, field): void;Follow a shared navigation field.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
field | FlowField | Shared navigation field. |
Returns
void
Nothing.
has()
ts
has(entity): boolean;Check whether an entity belongs to this crowd.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
Returns
boolean
Whether it belongs to this crowd.
moveTo()
ts
moveTo(
entity,
x,
z
): boolean;Plan a path towards a goal.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
x | number | Goal x. |
z | number | Goal z. |
Returns
boolean
Whether a path exists.
position()
ts
position(entity, out): boolean;Read an agent's simulated position.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
out | NavPoint | Position destination. |
Returns
boolean
Whether found.
remove()
ts
remove(entity): void;Remove an entity from the crowd.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity to remove. |
Returns
void
Nothing.
setPosition()
ts
setPosition(
entity,
x,
z
): void;Set an agent's simulated position.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
x | number | World x. |
z | number | World z. |
Returns
void
Nothing.
state()
ts
state(entity): AgentState;Read an agent's current state.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
Returns
Current state, or Idle for unknown entities.
step()
ts
step(dt): void;Advance the crowd simulation.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | number | Elapsed seconds; nonpositive values do nothing. |
Returns
void
Nothing.
stop()
ts
stop(entity): void;Stop an agent and let it decelerate.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
Returns
void
Nothing; becomes Idle and decelerates.
update()
ts
update(ctx): void;Read transforms and apply movement and facing.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Frame context; reads Transform and applies velocity and facing. |
Returns
void
Nothing.
velocity()
ts
velocity(entity, out): boolean;Read an agent's simulated velocity.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
out | NavPoint | Velocity destination. |
Returns
boolean
Whether found.
CrowdAgentOptions
Per-agent tuning.
Properties
arriveDistance?
ts
readonly optional arriveDistance?: number;Distance at which the goal counts as reached. Default 0.3.
maxAccel?
ts
readonly optional maxAccel?: number;Metres per second squared. Default 20.
maxSpeed?
ts
readonly optional maxSpeed?: number;Metres per second. Default 3.5.
radius?
ts
readonly optional radius?: number;Default: the nav's agentRadius.
CrowdOptions
Crowd-wide tuning.
Properties
face?
ts
readonly optional face?: boolean;Turn each moving agent to face where it walks (faceToward). Default true.
maxAgents?
ts
readonly optional maxAgents?: number;Most agents at once. Default 128.
maxPathPoints?
ts
readonly optional maxPathPoints?: number;Most points one agent's path holds. Default 64.
move?
ts
readonly optional move?: CrowdMove;character: physics.moveCharacter. velocity: the guest-integrated Velocity. Default character.
neighbourRadius?
ts
readonly optional neighbourRadius?: number;How far an agent looks for others to avoid. Default 3.
timeHorizon?
ts
readonly optional timeHorizon?: number;Seconds ahead an agent predicts collisions. Default 2.
CursorHit
Caller-owned cursor query result; allocate once and reuse.
Example
ts
const hit: CursorHit = { point: { x: 0, y: 0, z: 0 }, normal: { x: 0, y: 1, z: 0 }, entity: 0, distance: 0 };Properties
distance
ts
distance: number;entity
ts
entity: number;normal
ts
normal: Vec3;point
ts
point: Vec3;CutsceneCmd
A cutscene: a clip the page draws over the stage at a moment that matters. preload fetches it ahead so play starts at once; skip ends the one playing. The clip is a video asset of the manifest, never a URL.
Properties
action
ts
action: "play" | "preload" | "skip";asset
ts
asset: number;The video asset; 0 for skip.
fadeInMs
ts
fadeInMs: number;Milliseconds of fade in over the stage.
fadeOutMs
ts
fadeOutMs: number;Milliseconds of fade out.
pause
ts
pause: boolean;The stage pauses under it and the game's sound is ducked.
skippable
ts
skippable: boolean;A tap or a key ends it early.
CutsceneEvent
How a cutscene ended.
Properties
asset
ts
asset: number;The video asset that was played.
kind
ts
kind: "ended" | "failed" | "skipped";The clip reached its end, the person skipped it, or it could not play.
seconds
ts
seconds: number;Seconds from the call to the end, fades included.
CutscenePlayOptions
Options for cutscene.play.
Properties
fadeIn?
ts
optional fadeIn?: number;Fade in over the stage, milliseconds. Default 400.
fadeOut?
ts
optional fadeOut?: number;Fade out, milliseconds. Default 400.
pause?
ts
optional pause?: boolean;Pause the stage under it and duck the game's sound. Default true.
skippable?
ts
optional skippable?: boolean;A tap or a key ends it early. Default true.
Damage
Health operations and fixed-step invulnerability. Write Health through this part: step does not infer deaths from external writes. Positive hp clears stale death flags. Snapshot contains only sparse [entity, dead, iframes] rows; the engine saves Health.
Example
ts
import { createDamage, defineGame, type Damage } from 'gameable';
const hits: Damage = createDamage();
hits.reset();
export default defineGame({ systems: [ctx => { hits.fraction(ctx, 0); }] });Extends
Methods
damage()
ts
damage(
ctx,
entity,
amount,
source?
): number;Remove hp; onDamage precedes onDeath synchronously for this entity.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
entity | number |
amount | number |
source? | number |
Returns
number
forget()
ts
forget(entity): void;Clear the death flag and i-frames; call when you despawn an entity.
Parameters
| Parameter | Type |
|---|---|
entity | number |
Returns
void
fraction()
ts
fraction(ctx, entity): number;Current / max clamped to [0, 1], or zero outside the entity range, without Health in ctx.world, or without positive maximum health.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
entity | number |
Returns
number
heal()
ts
heal(
ctx,
entity,
amount
): number;Restore living hp, capped at max; onHeal receives the actual amount.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
entity | number |
amount | number |
Returns
number
isDead()
ts
isDead(entity): boolean;Read the death flag while current hp is nonpositive; clear stale flags and i-frames.
Parameters
| Parameter | Type |
|---|---|
entity | number |
Returns
boolean
isInvulnerable()
ts
isInvulnerable(entity): boolean;Whether any i-frames remain.
Parameters
| Parameter | Type |
|---|---|
entity | number |
Returns
boolean
kill()
ts
kill(
ctx,
entity,
source?
): void;Kill regardless of i-frames; onDamage precedes onDeath when hp was removed.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
entity | number |
source? | number |
Returns
void
reset()
ts
reset(): void;Back to the state right after creation. Call from init.
Returns
void
Inherited from
restore()
ts
restore(state, options?): void;Read back what snapshot returned. Throws on a malformed state.
Parameters
| Parameter | Type |
|---|---|
state | unknown |
options? | { crossBuild?: boolean; } |
options.crossBuild? | boolean |
Returns
void
Inherited from
revive()
ts
revive(
ctx,
entity,
hpFraction?
): void;Revive a flagged death, clamping fraction to [1 hp, max]; fires onRevive.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
entity | number |
hpFraction? | number |
Returns
void
setInvulnerable()
ts
setInvulnerable(
ctx,
entity,
seconds
): void;Replace i-frames; nonpositive seconds clears them.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
entity | number |
seconds | number |
Returns
void
snapshot()
ts
snapshot(): unknown;Plain JSON-safe data for defineGame({ snapshot }).
Returns
unknown
Inherited from
step()
ts
step(ctx): void;Count down i-frames in ascending entity order; does not infer deaths.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
DamageInfo
Attribution attached to a damage operation.
Example
ts
const info: DamageInfo = { type: 'fire' };Properties
causer?
ts
optional causer?: ActorHandle<object>;Actor directly causing the damage.
instigator?
ts
optional instigator?: ActorHandle<object>;Actor responsible for the damage.
type?
ts
optional type?: string;Game-defined damage category.
DataFacade
The ctx.data facade, one per guest. Only the authority writes: on a client every call is a no-op (logged once).
Saving is not free: save serialises the document. Call it when the document changed, not every tick; the room writes at most one per player every 6 s anyway, and always when the player leaves or the room closes.
Example
ts
function earn(ctx: GameContext): void {
for (const [id, p] of ctx.players) {
const doc = (p.data ?? { coins: 0 }) as { coins: number };
if (ctx.frame % 600 === 0) ctx.data.save(id, { ...doc, coins: doc.coins + 1 });
}
for (const r of ctx.data.results()) if (!r.ok) ctx.net.send('trade-failed', { id: r.id, why: r.reason });
}Accessors
game
Get Signature
ts
get game(): unknown;Returns
unknown
The game's own saved document, once the room has handed it over; else null.
Methods
exchange()
ts
exchange(
a,
b,
give,
take
): number;Trade between two players, all or nothing: a gives b everything in give and takes from b everything in take (numbers move amounts, lists move items; see applyTransfer). The result arrives as an exchange-result event a tick or more later, in DataFacade.results; on success both players' data already show the trade.
Parameters
| Parameter | Type | Description |
|---|---|---|
a | number | The first player. |
b | number | The second player. |
give | TransferDoc | What a gives b, such as { coins: 5 }. |
take | TransferDoc | What a takes from b, such as { owned: ['gem'] }. |
Returns
number
The exchange's id, or 0 on a client.
results()
ts
results(): readonly Pick<ExchangeResultEvent, "id" | "ok" | "reason">[];Returns
readonly Pick<ExchangeResultEvent, "id" | "ok" | "reason">[]
This tick's exchange results, in arrival order; reused, read during the tick.
save()
ts
save(player, doc): void;Keep a player's document. ctx.players.get(player).data is the new document at once; the room writes it to its store (throttled).
Parameters
| Parameter | Type | Description |
|---|---|---|
player | number | A joined player. |
doc | unknown | Any JSON value; at most 64 KB as JSON. |
Returns
void
saveGame()
ts
saveGame(doc): void;Keep the game's own document (one per game, shared by every room).
Parameters
| Parameter | Type | Description |
|---|---|---|
doc | unknown | Any JSON value; at most 64 KB as JSON. |
Returns
void
DataFieldSchema
One content field's authoring constraints. Bounds on vec3 apply to each component.
Example
ts
const field: DataFieldSchema = { type: 'number', min: 0, description: 'Health.' };Properties
description
ts
description: string;max?
ts
optional max?: number;min?
ts
optional min?: number;type
ts
type: "string" | "number" | "boolean" | "vec3" | "enum" | "tableRef";values?
ts
optional values?: readonly string[];DataRowHandle
A JSON-safe reference, suitable for level props and saved games.
Example
ts
const handle: DataRowHandle = { table: 'Items', key: 'potion' };Properties
key
ts
readonly key: string;table
ts
readonly table: string;DataTable
Immutable named rows. Missing rows return undefined; find returns the first match. Curves use finite numeric keys and finite numeric field values, with endpoint clamping. Lookup, search, weighted selection and curve sampling allocate no storage per call.
Example
ts
const items: DataTable<{ cost: number }> = defineDataTable('Items', {
description: 'Shop.', rows: { potion: { cost: 5 } },
});
const cost = items.get('potion')?.cost;Type Parameters
| Type Parameter |
|---|
Row extends object |
Properties
name
ts
readonly name: string;size
ts
readonly size: number;Methods
curve()
ts
curve(field, x): number;Equal numeric coordinates use the last row in key order.
Parameters
| Parameter | Type |
|---|---|
field | keyof Row & string |
x | number |
Returns
number
find()
ts
find(predicate): FrozenData<Row> | undefined;Parameters
| Parameter | Type |
|---|---|
predicate | (row, key) => boolean |
Returns
FrozenData<Row> | undefined
get()
ts
get(key): FrozenData<Row> | undefined;Parameters
| Parameter | Type |
|---|---|
key | string |
Returns
FrozenData<Row> | undefined
has()
ts
has(key): boolean;Parameters
| Parameter | Type |
|---|---|
key | string |
Returns
boolean
keys()
ts
keys(): readonly string[];Returns
readonly string[]
pickWeighted()
ts
pickWeighted(rng, weightField): FrozenData<Row>;Nonnegative finite weights are required; empty/all-zero tables throw.
Parameters
| Parameter | Type |
|---|---|
rng | Rng |
weightField | keyof Row & string |
Returns
FrozenData<Row>
DataTableCatalogEntry
A detached catalog entry for content authoring tools.
Example
ts
const entries: DataTableCatalogEntry[] = describeDataTables();Properties
description
ts
description: string;name
ts
name: string;rowKeys
ts
rowKeys: string[];schema
ts
schema: DataSchema;DoCharacterActionCmd
Ask a character to do an action of its motion set (see character.do).
Properties
action
ts
action: string;The action's name in the set.
entity
ts
entity: number;object?
ts
optional object?: ActionObject;plain
ts
plain: boolean;The plain way, for a comparison: the take simply started, nothing fitted.
DoorCoreProps
Shared authored door properties.
Example
ts
const props: Partial<DoorCoreProps> = { lockedBy: 'key' };Extends
Extended by
Properties
action
ts
action: string;Inherited from
asset?
ts
optional asset?: string;Inherited from
autoCloseSeconds
ts
autoCloseSeconds: number;closePrompt
ts
closePrompt: string;closeSound
ts
closeSound: string;colour
ts
colour: [number, number, number];consumeKey
ts
consumeKey: boolean;enabled
ts
enabled: boolean;Inherited from
facingDegrees
ts
facingDegrees: number;Inherited from
InteractableProps.facingDegrees
height
ts
height: number;Closed doorway height in metres.
lockedBy
ts
lockedBy: string;lockedMessage
ts
lockedMessage: string;lockedPrompt
ts
lockedPrompt: string;lockedSound
ts
lockedSound: string;look
ts
look: "none" | "wood" | "metal";once
ts
once: boolean;Inherited from
openPrompt
ts
openPrompt: string;openSound
ts
openSound: string;opensWhen
ts
opensWhen: string[];prompt
ts
prompt: string;Inherited from
range
ts
range: number;Inherited from
seconds
ts
seconds: number;startOpen
ts
startOpen: boolean;stayOpen
ts
stayOpen: boolean;thickness
ts
thickness: number;Leaf thickness in metres.
toggledBy
ts
toggledBy: "signal" | "proximity" | "interact";width
ts
width: number;Closed doorway width in metres.
DoorProps
Sliding or yaw-rotating door data. Offset is world-relative to the closed spawn transform; a nonzero openYaw selects rotation instead.
Example
ts
const props: Partial<DoorProps> = {openOffset: [2,0,0], lockedBy: 'key', consumeKey: true};Extends
Properties
action
ts
action: string;Inherited from
asset?
ts
optional asset?: string;Inherited from
autoCloseSeconds
ts
autoCloseSeconds: number;consumeKey
ts
consumeKey: boolean;enabled
ts
enabled: boolean;Inherited from
facingDegrees
ts
facingDegrees: number;Inherited from
InteractableProps.facingDegrees
lockedBy
ts
lockedBy: string;once
ts
once: boolean;Inherited from
openOffset
ts
openOffset: [number, number, number];openYaw
ts
openYaw: number;prompt
ts
prompt: string;Inherited from
range
ts
range: number;Inherited from
seconds
ts
seconds: number;startOpen
ts
startOpen: boolean;DoorStatus
Borrowed door status.
Example
ts
console.log(doorState(door).phase);Properties
fraction
ts
readonly fraction: number;locked
ts
readonly locked: boolean;phase
ts
readonly phase: "closed" | "open" | "opening" | "closing";DoubleDoorProps
Double leaf tuning; width measures the entire doorway.
Example
ts
const props: Partial<DoubleDoorProps> = { swingDegrees: 90 };Extends
Properties
action
ts
action: string;Inherited from
asset?
ts
optional asset?: string;Inherited from
autoCloseSeconds
ts
autoCloseSeconds: number;Inherited from
DoorCoreProps.autoCloseSeconds
closePrompt
ts
closePrompt: string;Inherited from
closeSound
ts
closeSound: string;Inherited from
colour
ts
colour: [number, number, number];Inherited from
consumeKey
ts
consumeKey: boolean;Inherited from
enabled
ts
enabled: boolean;Inherited from
facingDegrees
ts
facingDegrees: number;Inherited from
height
ts
height: number;Closed doorway height in metres.
Inherited from
lockedBy
ts
lockedBy: string;Inherited from
lockedMessage
ts
lockedMessage: string;Inherited from
lockedPrompt
ts
lockedPrompt: string;Inherited from
lockedSound
ts
lockedSound: string;Inherited from
look
ts
look: "none" | "wood" | "metal";Inherited from
once
ts
once: boolean;Inherited from
openPrompt
ts
openPrompt: string;Inherited from
openSound
ts
openSound: string;Inherited from
opensWhen
ts
opensWhen: string[];Inherited from
prompt
ts
prompt: string;Inherited from
range
ts
range: number;Inherited from
seconds
ts
seconds: number;Inherited from
startOpen
ts
startOpen: boolean;Inherited from
stayOpen
ts
stayOpen: boolean;Inherited from
swingAway
ts
swingAway: boolean;swingDegrees
ts
swingDegrees: number;thickness
ts
thickness: number;Leaf thickness in metres.
Inherited from
toggledBy
ts
toggledBy: "signal" | "proximity" | "interact";Inherited from
width
ts
width: number;Closed doorway width in metres.
Inherited from
DriveOptions
Shared request options; speeds are metres/second and distances metres.
Example
ts
driveTowards(ctx, ai, point, { speed: 15, tuning: { maxSpeed: 20 } });Extended by
Properties
acceptanceRadius?
ts
optional acceptanceRadius?: number;speed?
ts
optional speed?: number;stopAtTarget?
ts
optional stopAtTarget?: boolean;tuning?
ts
optional tuning?: Partial<DriveTuning>;DriveSettings
Pure driver settings; negative speed requests reverse travel.
Example
ts
const settings: DriveSettings = { ...defaultDriveTuning, speed: 12, acceptanceRadius: 1, stopAtTarget: true };Extends
Properties
acceptanceRadius
ts
acceptanceRadius: number;brakeGain
ts
brakeGain: number;Inherited from
lookAheadMin
ts
lookAheadMin: number;Inherited from
lookAheadTime
ts
lookAheadTime: number;Inherited from
maxSpeed
ts
maxSpeed: number;Inherited from
reverseSeconds
ts
reverseSeconds: number;Inherited from
speed
ts
speed: number;speedGain
ts
speedGain: number;Inherited from
steerGain
ts
steerGain: number;Inherited from
stopAtTarget
ts
stopAtTarget: boolean;stuckSeconds
ts
stuckSeconds: number;Inherited from
DriveState
Borrowed chassis pose and signed longitudinal speed.
Example
ts
const state: DriveState = { position: car.position, yaw: 0, speed: 0 };Properties
position
ts
position: Vec3;speed
ts
speed: number;yaw
ts
yaw: number;DriveTuning
Driving gains in SI units; steerGain converts pursuit curvature to normalized steer.
Example
ts
const tuning: DriveTuning = { ...defaultDriveTuning, maxSpeed: 20 };Extended by
Properties
brakeGain
ts
brakeGain: number;lookAheadMin
ts
lookAheadMin: number;lookAheadTime
ts
lookAheadTime: number;maxSpeed
ts
maxSpeed: number;reverseSeconds
ts
reverseSeconds: number;speedGain
ts
speedGain: number;steerGain
ts
steerGain: number;stuckSeconds
ts
stuckSeconds: number;EffectCmd
Particle command payload, copied into a pool by the SDK.
Example
ts
import type { EffectCmd } from 'gameable';
const command: EffectCmd = {
action: 'play', effect: 0, preset: 'dust', position: { x: 0, y: 0, z: 0 },
direction: { x: 0, y: 0, z: 0 }, scale: 1, intensity: 1,
};Properties
action
ts
action: EffectAction;direction
ts
direction: Vec3;Emission direction (a surface normal for sparks); zero is the preset's own.
effect
ts
effect: number;Guest-minted handle; 0 is a one-shot that cannot be moved or stopped.
entity?
ts
optional entity?: number;Follow an entity.
intensity
ts
intensity: number;Count and brightness multiplier; 1 is the preset.
position
ts
position: Vec3;World position; with entity, an offset from the entity.
preset
ts
preset: string;Preset name: hit-sparks, explosion, smoke, fire, magic, dust, trail. play only.
scale
ts
scale: number;Size multiplier; 1 is the preset.
tint?
ts
optional tint?: Vec3;Colour override, linear RGB; over 1 glows under bloom.
EffectDefinition
Effect definition registered at module scope or during game init. Periodic effects pulse first after one period.
Example
ts
defineEffect({ id: 'heal', duration: 'instant', modifiers: [{ attribute: 'health', op: 'add', magnitude: 10 }] });Extends
Gate
Properties
blockedByTags?
ts
optional blockedByTags?: readonly string[];Inherited from
ts
Gate.blockedByTagsduration
ts
duration: number | "instant" | "infinite";grantTags?
ts
optional grantTags?: readonly string[];id
ts
id: string;maxStacks?
ts
optional maxStacks?: number;modifiers
ts
modifiers: readonly object[];period?
ts
optional period?: number;requiresTags?
ts
optional requiresTags?: readonly string[];Inherited from
ts
Gate.requiresTagsstacking?
ts
optional stacking?: "none" | "stack" | "refresh";ExchangeCmd
Trade between two players' documents; the result is an exchange-result event.
Properties
a
ts
a: number;b
ts
b: number;give
ts
give: string;JSON: what a gives b.
id
ts
id: number;Guest-minted; echoed in the result.
take
ts
take: string;JSON: what a takes from b.
ExchangeResultEvent
The outcome of an exchange command, matched by its id.
Properties
aData
ts
aData: string;Player a's document after the trade, as the store wrote it (JSON); empty unless ok.
bData
ts
bData: string;Player b's document after the trade (JSON); empty unless ok.
id
ts
id: number;ok
ts
ok: boolean;reason
ts
reason: string;Empty when ok.
FaceCharacterCmd
Turn a character on the spot to face a way (see character.face).
Properties
entity
ts
entity: number;facing
ts
facing: number;Radians about +Y (0 faces +Z).
quick
ts
quick: boolean;The quickest turn the set has, instead of an unhurried one.
FeatureSpec
The features a game may declare. A key that is false is the same as absent.
Properties
characters?
ts
optional characters?: boolean | CharactersOptions;The splat character bridge (spawn-character and friends).
multiplayer?
ts
optional multiplayer?: boolean | MultiplayerOptions;Rooms, players and replication.
vfx?
ts
optional vfx?: boolean | VfxOptions;Particle effects and post processing, optionally with a declared base look.
FightBase
The fight kit's script door: the take under a fighter's state and how it plays (the pack's name, or '' for the key-pose stance; a hold, start, end or frames below 0 means none; upper '' for none).
Properties
end
ts
end: number;fade
ts
fade: number;frames
ts
frames: number;hold
ts
hold: number;looped
ts
looped: boolean;name
ts
name: string;rate
ts
rate: number;start
ts
start: number;upper
ts
upper: string;FightBaseOptions
The take under a fighter's state (the fight pack's name) and how it plays; every field but the name optional.
Properties
fade?
ts
optional fade?: number;Frames to cross-fade in over.
frames?
ts
optional frames?: number;from?
ts
optional from?: number;A window of the take (fractions) stretched over frames game frames.
hold?
ts
optional hold?: number;A still: the take held at this fraction of its length.
loop?
ts
optional loop?: boolean;Looped (a stance, a walk); once by default.
name
ts
name: string;rate?
ts
optional rate?: number;Playback rate, 1 as captured.
to?
ts
optional to?: number;upper?
ts
optional upper?: string;The body above the hips from this take instead (a walk's legs under the fighter's own stance).
FightBodyEvent
A fighter's body the host leads this step (thrown, lying, or rising): where it is (the pelvis, world), whether it is in the air, whether it lies face up, and the yaw it faces. Said every step the body is the host's, so the game's rules keep its place.
Properties
airborne
ts
airborne: boolean;entity
ts
entity: number;faceUp
ts
faceUp: boolean;facing
ts
facing: number;point
ts
point: Vec3;FightCameraCmd
The fight camera, run on the host (see camera.fight).
Properties
a
ts
a: number;b
ts
b: number;closeUp
ts
closeUp: number;half
ts
half: number;hero
ts
hero: number;on
ts
on: boolean;openFloor
ts
openFloor: boolean;ropeLine
ts
ropeLine: number;shake
ts
shake: number;sides
ts
sides: number;wideFor
ts
wideFor: number;FightContactEvent
A fighter's strike met the other body this step (the fight kit's script door): the striker, the body it met (the strike's target), the part struck (0 the head, 1 the body, 2 the legs), where (world), and which of the struck body's legs is the nearer to the striker (+1 its left, -1 its right). Said every step the striking part is in the other body while the strike can hit; take the first and decide what the blow does.
Properties
entity
ts
entity: number;leg
ts
leg: number;point
ts
point: Vec3;target
ts
target: number;zone
ts
zone: number;FightFallCmd
A fighter thrown into the rag-doll (see character.fightFall).
Properties
entity
ts
entity: number;kick
ts
kick: boolean;The body is thrown already: the blow is blended into its flight.
spin
ts
spin: number;turn
ts
turn: number;velocity
ts
velocity: Vec3;FightGetUpCmd
A fighter up off the floor (see character.fightGetUp).
Properties
entity
ts
entity: number;quick
ts
quick: boolean;FightHitCmd
A blow on a fighter (see character.fightHit).
Properties
blocked
ts
blocked: boolean;Taken on the guard: the block's push and the legs' give by k, nothing else.
dir
ts
dir: number;The way the blow came along the floor (+1 / -1, the striker's facing) and the striker's line's turn.
entity
ts
entity: number;k
ts
k: number;leg
ts
leg: number;reaction
ts
reaction: string;reactionAmount
ts
reactionAmount: number;reactionFrames
ts
reactionFrames: number;rising
ts
rising: boolean;side
ts
side: number;stagger
ts
stagger: boolean;staggerSide
ts
staggerSide: number;staggerUp
ts
staggerUp: number;throws
ts
throws: boolean;The blow throws the body (a fightFall follows): the push on the joints only.
turn
ts
turn: number;zone
ts
zone: number;FightHitOptions
A blow on a fighter, as character.fightHit takes it.
Properties
blocked?
ts
optional blocked?: boolean;Taken on the guard: the block's push on the arms and the legs' give by k, nothing else.
dir
ts
dir: number;The way the blow came along the floor: +1 / -1, the striker's facing.
k
ts
k: number;How hard, 0 to 1.
leg?
ts
optional leg?: number;+1 the left leg was struck, -1 the right.
reaction?
ts
optional reaction?:
| {
amount?: number;
clip: string;
frames?: number;
}
| null;The reaction take laid on top (the pack's hit_head_left and the like), its amount (0 to 1) and frames.
rising?
ts
optional rising?: boolean;An uppercut: it lifts the chin.
side?
ts
optional side?: number;From which side: +1 the fighter's left, -1 its right, 0 straight on.
stagger?
ts
optional stagger?:
| {
side?: number;
up?: number;
}
| null;The stagger (a big blow throws the body loose above the knees for a moment): from which side, up (1 for a rising blow).
throws?
ts
optional throws?: boolean;The blow throws the body (a character.fightFall follows): the push on the joints only.
turn?
ts
optional turn?: number;The striker's line's turn (rad); 0 one on one.
zone
ts
zone: number;Where: 0 the head, 1 the body, 2 the legs.
FightSetEvent
The fight pack the page's bridge loaded (the fight kit's script door), handed to the game once it is read: the pack's name and its fight block as the pack carries it, JSON text (strikes: every strike's frames, level, limb, radius, push, hitstop, strength, launch, travel, aim, its power version, its styles). Read it with JSON.parse and keep no table of your own. Said once, on the first tick after the set is in.
Properties
json
ts
json: string;name
ts
name: string;FightShotOptions
The fight camera's request, as camera.fight takes it; everything but the two fighters optional.
Properties
a
ts
a: number;The two fighters framed.
b
ts
b: number;closeUp?
ts
optional closeUp?: number;Lean in on a knockout, 0 to 1.
half?
ts
optional half?: number;hero?
ts
optional hero?: number;The winner it goes in close on.
on?
ts
optional on?: boolean;Off: the camera is yours again.
openFloor?
ts
optional openFloor?: boolean;The ring: an open floor with ropes (default) or a line between walls; the walls' half width; the ropes' line from the middle; the sides.
ropeLine?
ts
optional ropeLine?: number;shake?
ts
optional shake?: number;A shake added this step (0.02 a hit, 0.1 a knockout).
sides?
ts
optional sides?: number;wideFor?
ts
optional wideFor?: number;Glide out to the wide shot and hold it this many seconds (a knockdown), then back.
FightStateCmd
What a fighter's body is doing this step (see character.fight).
Properties
anchor
ts
anchor: number;The base take's root held (1 where it started, 2 in place); a turn laid on the pose, radians.
arc
ts
arc: number;A jump with no strike in it: its arc (0 to 1; below 0 none), its way (+1 in, -1 back, 0 up), a somersault.
base
ts
base: FightBase;blend
ts
blend: number;Frames to blend from the pose as it was, on the step the state changes (0 none; -1 the driver's own).
bounce
ts
bounce: number;bulk
ts
bulk: number;How thick the body is to a blow, 1 as built.
crouch
ts
crouch: boolean;crouched
ts
crouched: boolean;entity
ts
entity: number;facing
ts
facing: number;fists
ts
fists: string;The take whose hands make the fists in the guard (the fighter's idle); '' for the base's own hands.
flip
ts
flip: boolean;frozen
ts
frozen: boolean;grounded
ts
grounded: boolean;guard
ts
guard: number;guardUp
ts
guardUp: boolean;held
ts
held: boolean;The impact freeze as it was at the start of the step: the physics and the reaction stand still.
jumpDir
ts
jumpDir: number;look
ts
look: Vec3 | undefined;lookWeight
ts
lookWeight: number;mirrored
ts
mirrored: boolean;on
ts
on: boolean;False ends the fight on this body; the next true starts afresh.
pitch
ts
pitch: number;place
ts
place: Vec3;Where the fighter stands (world) and the yaw its object is turned by.
posture
ts
posture: boolean;reach
ts
reach: number;The fighter's real reach, metres (0: the figure's own).
recoil
ts
recoil: number;reset
ts
reset: boolean;A round starts again: the blows' push, the stagger, the springs and the rag-doll cleared.
squash
ts
squash: number;Nudges on the springs this step: the legs' give, the spine's pitch; the legs' give cleared; the striker's recoil.
squashReset
ts
squashReset: boolean;strike
ts
strike: FightStrike;target
ts
target: number;The other fighter (0 none): the strike is aimed at its body and met against it (fight-contact events).
turning
ts
turning: number;turnTo
ts
turnTo: number;yaw
ts
yaw: number;FightStateOptions
What a fighter's body is doing this step; every field optional (the defaults: standing still on its feet).
Properties
anchor?
ts
optional anchor?: number;The base take's root: 0 as the take moves, 1 started where the fighter stands (a celebration), 2 held in place (a dance).
arc?
ts
optional arc?: number;A jump with no strike in it: where in its arc (0 leaving the floor, 1 landing), its way (+1 in, -1 back, 0 up), a somersault.
base?
ts
optional base?: FightBaseOptions | null;The take under the state, or null for the key-pose stance.
blend?
ts
optional blend?: number;Frames to blend from the pose as it was, said on the step the state changes (0 none). Left out, the driver blends four frames on its own whenever what plays changes.
bounce?
ts
optional bounce?: number;The idle's bounce on the key-pose stance, 0 to 1.
bulk?
ts
optional bulk?: number;How thick the body is to a blow (the hurt areas' radius, squared), 1 as built.
crouch?
ts
optional crouch?: boolean;The crouch wanted.
crouched?
ts
optional crouched?: boolean;The key-pose stance is the crouch.
facing?
ts
optional facing?: number;+1 or -1 along its line (1 by default).
fists?
ts
optional fists?: string;The take whose hands make the fists in the guard (the fighter's idle); none: the base's own hands.
flip?
ts
optional flip?: boolean;frozen?
ts
optional frozen?: boolean;The impact freeze after this step (the takes, the stagger and the blend stand still), and held, the freeze as it was at the start of the step (the blows' springs, the legs' give, the rag-doll, the reaction and the rise stand still): a game whose freeze counts down inside its step says both. held follows frozen when left out.
grounded?
ts
optional grounded?: boolean;A standing state: the feet plant, the crouch applies (true by default).
guard?
ts
optional guard?: number;The fists brought up to the face, 0 none to 1.
guardUp?
ts
optional guardUp?: boolean;Blocking: the guard laid on the stance, the gloves up, the chin down.
held?
ts
optional held?: boolean;jumpDir?
ts
optional jumpDir?: number;look?
ts
optional look?: Vec3 | null;A point the face turns to (world), by lookWeight (0 none to 1).
lookWeight?
ts
optional lookWeight?: number;mirrored?
ts
optional mirrored?: boolean;Facing the other way: the pose is the mirror image.
pitch?
ts
optional pitch?: number;posture?
ts
optional posture?: boolean;The spine and neck kept near how the character is built (true by default).
reach?
ts
optional reach?: number;The fighter's real reach, metres: the glove lands that much further than the figure's own arm (none: the figure's).
recoil?
ts
optional recoil?: number;The striker's own recoil this step, by the blow's strength.
reset?
ts
optional reset?: boolean;A round starts again: the blows' push, the stagger, the springs and the rag-doll cleared, the body standing where the entity is; its takes cross-fade on. Say it on the round's first step.
squash?
ts
optional squash?: number;Nudges on the springs this step: the legs' give (a landing, a dash, a special's wind-up), the spine's pitch (an armored hit).
squashReset?
ts
optional squashReset?: boolean;The legs' give cleared (a jump leaving the floor).
strike?
ts
optional strike?: FightStrikeOptions | null;target?
ts
optional target?: number;The other fighter (an entity): a strike with no aim of its own is aimed at that body, and met against it: a fight-contact event in ctx.events every step the striking part is in it while the strike can hit (the part struck, the point, the nearer leg); your rules take the first and decide what the blow does.
turning?
ts
optional turning?: number;Turning round on the spot: how much of the half turn is still to show, 0 to 1.
turnTo?
ts
optional turnTo?: number;A turn about the vertical laid on the pose, radians (a winner turning to the camera).
FightStrike
A strike under way: the pack's strike id ('' none), its frame, the fighter's speed stretch, extra recovery frames, the aim.
Properties
aim
ts
aim: Vec3 | undefined;aimWeight
ts
aimWeight: number;extra
ts
extra: number;frame
ts
frame: number;id
ts
id: string;speed
ts
speed: number;FightStrikeOptions
A strike under way: the pack's strike id and its frame (0 the first); the rest optional.
Properties
aim?
ts
optional aim?: Vec3;Where the striking part is aimed (world), pulled there by aimWeight (0 to 1, 1 by default). None: aimed at the state's target fighter's body as the pack's strike says (the face, the chin, the ribs, the nearer thigh, the raised gloves), the pull growing through the wind-up, held while it can hit, let go in the recovery; with no target either, the take as captured.
aimWeight?
ts
optional aimWeight?: number;extra?
ts
optional extra?: number;Frames added to the recovery.
frame
ts
frame: number;id
ts
id: string;speed?
ts
optional speed?: number;The fighter's speed stretch on the startup and the recovery, 1 as written.
FirstPersonOptions
Options for camera.firstPerson.
Properties
eyeHeight?
ts
optional eyeHeight?: number;Eye height above the entity origin, metres. Default 1.7.
fovYDeg?
ts
optional fovYDeg?: number;Vertical field of view in degrees. Default 75.
FittedShape
Fitted primitive with local center and capsule orientation (engine local Y).
Example
ts
const shape: FittedShape = fitBox(new Float32Array([-1,-1,-1,1,1,1]));Properties
center
ts
center: Vec3;dims
ts
dims: readonly number[];rotation
ts
rotation: Quat;shape
ts
shape: "box" | "sphere" | "capsule";FlatPoint
A point on the ground plane; y is ignored.
Properties
x
ts
readonly x: number;z
ts
readonly z: number;FloorResult
Cached support; distances are measured from the full capsule bottom.
Example
ts
const distance = movement.currentFloor.floorDist;Properties
blockingHit
ts
blockingHit: boolean;floorDist
ts
floorDist: number;hit
ts
hit: SweepHit;lineDist
ts
lineDist: number;lineTrace
ts
lineTrace: boolean;sweepLocation
ts
sweepLocation: Vec3;Capsule centre at the original floor sweep contact, before pullback.
walkableFloor
ts
walkableFloor: boolean;FlowField
One goal for many agents: every cell knows which way to go. After an obstacle or cost area is added or removed the field re-integrates towards its goal on its next query, so it never goes stale.
Methods
direction()
ts
direction(
x,
z,
out
): boolean;Parameters
| Parameter | Type | Description |
|---|---|---|
x | number | World x. |
z | number | World z. |
out | NavPoint | Receives a unit direction towards the goal. |
Returns
boolean
false where the goal cannot be reached (or at the goal itself).
distance()
ts
distance(x, z): number;Parameters
| Parameter | Type |
|---|---|
x | number |
z | number |
Returns
number
Weighted travel cost to the goal in metres, Infinity if unreachable.
setGoal()
ts
setGoal(x, z): boolean;Recompute the field towards a goal. Cost grows with the grid, not the agents.
Parameters
| Parameter | Type |
|---|---|
x | number |
z | number |
Returns
boolean
false when the goal is not on walkable ground.
FollowOptions
Options for camera.follow.
Properties
distance?
ts
optional distance?: number;Boom length behind the target, metres. Default 4.
fovYDeg?
ts
optional fovYDeg?: number;Vertical field of view in degrees. Default 60.
height?
ts
optional height?: number;Rig-local height offset, metres. Default 1.6.
pitch?
ts
optional pitch?: number;Orbit pitch in radians; positive looks up. Defaults to the accumulator.
yaw?
ts
optional yaw?: number;Orbit yaw in radians about +Y; 0 puts the camera behind the target.
Defaults to the built-in look accumulator. Pass it when the game keeps its own orbit — a third-person camera usually wants a tighter pitch range and its own sensitivity than the first-person one the accumulator is tuned for.
ForceFieldProps
Properties for a radial force source.
Example
ts
const props: Partial<ForceFieldProps> = { fireOnBeginPlay: true, radius: 8 };Properties
active
ts
active: boolean;falloff
ts
falloff: "linear" | "constant";fireOnBeginPlay
ts
fireOnBeginPlay: boolean;forceStrength
ts
forceStrength: number;impulseStrength
ts
impulseStrength: number;radius
ts
radius: number;FrameInput
One fixed simulation step of host state handed to the guest.
Properties
bodies
ts
bodies: ArrayLike<number>;Post-step body transforms, stride 15, sorted ascending by body id.
contacts
ts
contacts: readonly Contact[];dt
ts
dt: number;elapsed
ts
elapsed: number;events
ts
events: readonly GameEvent[];frame
ts
frame: number | bigint;Monotonic fixed-step counter. jco lifts u64 as a bigint on the host and a number in the guest, so both are legal here; the runtime Number()s it once, on the way in.
input
ts
input: InputState;players
ts
players: readonly PlayerInput[];Every player's input in a room, ascending by id. Empty for a single-player game. A held seat (its player dropped) is left out until they are back.
vehicles?
ts
optional vehicles?: ArrayLike<number>;Versioned vehicle telemetry; absent for older direct hosts.
FrameOutput
Everything the guest hands back for one fixed step.
Properties
camera
ts
camera: CameraState;commands
ts
commands: readonly Command[];hud?
ts
optional hud?: string;HUD JSON, present only on the frames it changed.
localCommands
ts
localCommands: readonly Command[];Applied by the authority after commands; never forwarded to a client.
look?
ts
optional look?: object;Final local player look after game camera rules, for the page input sequence.
pitch
ts
pitch: number;yaw
ts
yaw: number;transforms
ts
transforms: Float32Array;Entity transforms, stride 12. Never empty: see the zero-row rule.
ui?
ts
optional ui?: string;UI JSON, present only on the frames it changed.
FxOptions
Bus effect overrides.
Example
ts
`audio.fx('music', 'underwater', { fadeMs: 500 });`Properties
compressor?
ts
optional compressor?: boolean;Enable compression.
fadeMs?
ts
optional fadeMs?: number;Ramp duration.
highpassHz?
ts
optional highpassHz?: number;High-pass cutoff.
lowpassHz?
ts
optional lowpassHz?: number;Low-pass cutoff.
reverb?
ts
optional reverb?: number;Wet level.
GameConfig
The init payload.
Properties
devMode
ts
devMode: boolean;fixedHz
ts
fixedHz: number;options?
ts
optional options?: string;seed
ts
seed: number | bigint;Deterministic run seed. A bigint on the host, a number in the guest; the runtime Number()s it once, on the way in.
viewportHeight
ts
viewportHeight: number;viewportWidth
ts
viewportWidth: number;GameContext
Everything a system can reach.
The same object is handed to every system on every frame — it is mutated in place, never rebuilt, so never retain it or destructure frame outside the call.
Properties
audio
ts
readonly audio: object;Sound playback.
fx()
ts
fx(
bus,
preset,
options?
): void;Set bus effects.
Parameters
| Parameter | Type | Description |
|---|---|---|
bus | AudioBus | Mixer bus. |
preset | FxPreset | Base preset. |
options? | FxOptions | Overrides and fade. |
Returns
void
Example
ts
`audio.fx('sfx', 'cave');`listener()
ts
listener(position, rotation): void;Place the audio listener.
Parameters
| Parameter | Type | Description |
|---|---|---|
position | Vec3 | Listener position. |
rotation | Quat | Listener rotation, xyzw. |
Returns
void
Nothing.
occlude()
ts
occlude(
sound,
amount,
fadeMs?
): void;Muffle a sound.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
sound | number | undefined | Sound handle. |
amount | number | undefined | Occlusion from zero to one. |
fadeMs | number | 0 | Ramp duration. |
Returns
void
Example
ts
`audio.occlude(1, 0.8, 120);`play()
ts
play(asset, options?): number;Start a sound.
Parameters
| Parameter | Type | Description |
|---|---|---|
asset | string | number | Manifest string id or asset handle. |
options? | PlayOptions | Attachment, gain, pitch, looping and bus. |
Returns
number
The guest-minted sound handle, or 0 when the asset is unknown.
playOnBeat()
ts
playOnBeat(asset, options?): number;Schedule a sound on the music grid.
Parameters
| Parameter | Type | Description |
|---|---|---|
asset | string | number | Manifest id or handle. |
options? | PlayOnBeatOptions | Grid and mixer options. |
Returns
number
Sound handle or zero for an unknown asset.
Example
ts
`audio.playOnBeat('kick', { subdivision: 2 });`stop()
ts
stop(sound, fadeMs?): void;Stop a playing sound.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
sound | number | undefined | A handle from play. |
fadeMs | number | 0 | Fade-out in milliseconds; 0 stops immediately. |
Returns
void
Nothing.
camera
ts
readonly camera: object;The camera record for this frame.
look
Get Signature
ts
get look(): object;Accumulated look angles, in radians. Mutate to snap the view.
Returns
object
The live look state.
pitch
ts
pitch: number;sensitivity
ts
sensitivity: number;yaw
ts
yaw: number;state
Get Signature
ts
get state(): CameraState;Returns
fight()
ts
fight(shot): void;The fight camera (the fight kit's script door), run on the host: from the side, between the two fighters, pulled back as they part, raised when one flies, never still, inside the ropes; a wide shot on a knockdown, in close on the winner. Say it every step while it is on; the camera is yours again with on: false.
Parameters
| Parameter | Type | Description |
|---|---|---|
shot | FightShotOptions | The two fighters and the moment. |
Returns
void
Nothing.
firstPerson()
ts
firstPerson(entity, options?): void;Mount the camera at an entity's eyes.
Yaw and pitch come from the built-in look accumulator, which integrates input.mouse.dx/dy once per tick.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity to mount on. |
options? | FirstPersonOptions | Eye height and field of view. |
Returns
void
Nothing.
follow()
ts
follow(entity, options?): void;Put the camera on a spring arm behind an entity.
The host owns the arm and its collision; the guest only states the intent. position is the orbit pivot and rotation the direction the player is looking, so a host with no rig still ends up somewhere sensible.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity to follow. |
options? | FollowOptions | Boom length, height offset, field of view and orbit angles. |
Returns
void
Nothing.
lookAt()
ts
lookAt(point): void;Aim the camera at a world point, overriding its rotation.
Parameters
| Parameter | Type | Description |
|---|---|---|
point | Vec3 | null | The point to look at, or null to use the rotation again. |
Returns
void
Nothing.
set()
ts
set(
position,
rotation,
fovYDeg?
): void;Place the camera explicitly, detaching it from any entity.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
position | Vec3 | undefined | Eye position. |
rotation | Quat | undefined | Eye rotation, xyzw. |
fovYDeg | number | 60 | Vertical field of view in degrees. Default 60. |
Returns
void
Nothing.
character
ts
readonly character: object;Splat characters.
bundleOf()
ts
bundleOf(entity): number;The character bundle handle attached to an entity, or 0.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
Returns
number
The bundle asset handle.
cancelAction()
ts
cancelAction(entity): void;Take an action's request back (it cannot be taken back between its gathering and its landing).
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
Returns
void
Nothing.
do()
ts
do(
entity,
action,
object?,
plain?
): void;Ask a character to do an action of its motion set (a hurdle, a jump, a sit), at an object when the action needs one. What follows comes as motion-events in ctx.events: started, contact, release (with the point and its velocity, for a thing let go), landed, done, or failed with its reason.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity with a Character component. |
action | string | undefined | The action's name in the set. |
object? | Readonly<ActionObject> | undefined | The thing it is done at, as the game has it; left out for an action without one. |
plain? | boolean | false | The plain way, for a comparison: the take simply started, nothing fitted. |
Returns
void
Nothing.
Example
ts
character.do(hero, 'hurdle', { id: bar, position: barAt, yaw: 0, height: 0.6, width: 1.2, depth: 0.05 });face()
ts
face(
entity,
facing,
arrive?
): void;Turn a character on the spot to face a way, by its set's own turns. The motion-event arrived named 'face' says when it faces there.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity with a Character component. |
facing | number | undefined | Radians about +Y (0 faces +Z). |
arrive | "easy" | "quick" | 'easy' | 'easy' (the default: an unhurried turn) or 'quick' (the quickest the set has). |
Returns
void
Nothing.
Example
ts
character.face(guide, Math.PI / 2);fight()
ts
fight(entity, state?): void;The fight kit's script door: what this fighter's body is doing this step. The host's fight driver makes the pose on the character's own body from the fight pack (the page's bridge names the set) and lays it on the bones after the character's own clips: the base take under the state, the stance or the crouch, the guard, the look, the strike by the pack's id and its frame pulled to its aim, the posture, the lean, the planted feet. Say it every step. Where the fighter stands is its entity's transform: set the position (x, up, z) and the rotation (the yaw, facing * PI / 2 + turn) yourself. The host answers with motion-events in ctx.events: down (a thrown body came to rest, kind landed) and risen (the get-up finished, kind done), each with point where the body is and facing the yaw it faces: put the entity there. Name the other fighter (target) and the strike is aimed at its body and met against it: a fight-contact event says where. The pack's own table of moves comes once as a fight-set event (its fight block, JSON text).
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
state | FightStateOptions | null | What the body is doing; every field optional. null ends the fight on this body (a round's reset): the clips have it again, and the next call starts afresh, standing. |
Returns
void
Nothing.
Example
ts
character.fight(me, { base: { name: 'fight_idle_bounce', loop: true, fade: 10 }, facing: 1, bounce: 0.7 });
character.fight(me, { base: null, strike: { id: 'jab', frame, aim: theirHead } });fightFall()
ts
fightFall(
entity,
velocity,
spin?,
turn?,
kick?
): void;A fighter thrown into the fight kit's rag-doll: it flies at velocity (metres a second, world), turning at spin, falls, bounces, slides and comes to rest; the entity follows the body; the motion-event down says when it lies still and where. Then character.fightGetUp.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity with a Character component. |
velocity | Vec3 | undefined | Metres a second, world. |
spin | number | 2 | Radians a second about the axis across the blow's line (0.4 to 3 reads as a knockdown). |
turn | number | 0 | The blow's line's angle on the floor (0 along x). |
kick | boolean | false | The body is thrown already (a hit in the air): the blow is blended into its flight. |
Returns
void
Nothing.
fightGetUp()
ts
fightGetUp(entity, quick?): void;A fighter up off the floor: the get-up take chosen by how the body lies (on its back the spring-up, or the kip-up when quick; face down the stomach get-up), facing the way the head points. Keep saying character.fight with grounded: false while it rises; the motion-event risen says when it stands, where, and which way (facing, a yaw).
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity with a Character component. |
quick | boolean | false | The kip-up. |
Returns
void
Nothing.
fightHit()
ts
fightHit(entity, hit): void;A blow on a fighter on the fight kit's door: the push on its joints, the stagger and the reaction take, as the fight pack's own blows do. Your rules decide the damage and the stun; this is the body's answer.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
hit | FightHitOptions | The blow. |
Returns
void
Nothing.
hit()
ts
hit(entity, blow): void;A blow. Every exported character has a physics body (its parts on the engine's physics); the nearest part to at takes the blow along direction, and the body reacts for real: a small hit flinches and recovers over about a second, a big one falls onto the floor and stays down until character.recover, a shot is sharper, a push shoves. Use this before writing a reaction of your own.
What happened comes back as anim-events on the clip ragdoll: hit, fell (the body came to rest on the floor), recovered.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
blow | { at: Vec3; direction?: Vec3; strength: number | "small" | "big" | "shot" | "big-shot"; } | Where it lands (at, world), which way it travels (direction, world; omitted: from the character's front) and how hard (strength: 'small', 'big', 'shot', 'big-shot', or a push's newton-seconds: 40 staggers, 90 and over floors). |
blow.at | Vec3 | - |
blow.direction? | Vec3 | - |
blow.strength | number | "small" | "big" | "shot" | "big-shot" | - |
Returns
void
Nothing.
Example
ts
character.hit(enemy, { at: swordTip, direction: swing, strength: 'small' });
character.hit(enemy, { at: swordTip, direction: swing, strength: 'big' }); // downlookAt()
ts
lookAt(
entity,
target,
weight?
): void;Aim the head and eyes at a world point.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity with a Character component. |
target | Vec3 | null | undefined | The point, or null to release and return to the idle. |
weight | number | 1 | Blend weight in 0..1. Default 1. |
Returns
void
Nothing.
motion()
ts
motion(entity, options?): void;How the movement system moves a character. A character with a motion set (its package's own, else the engine's shared one) is moved by whole takes of a performer matched to the velocity given to character.setState: its starts, stops and turns are the performer's own, its feet are held where they land. That is the default; this call changes it for one character: off, another set, whether the take carries the walker, the two dials, and which kind of stop it makes from a run. What is left out stays as it is.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
options | CharacterMotionOptions | What to change. |
Returns
void
Nothing.
Example
ts
character.motion(hero, { responsiveness: 0.9 }); // a snappier hero
character.motion(guard, { on: false }); // this one by the clips' blend, as before
character.motion(hero, { stop: 'hard' }); // from a run it brakes, instead of slowing to a standrecover()
ts
recover(entity): void;Back into the animation: a character that is down (or reacting) blends back over about a second, where it stood. Move the entity to where the body lies first (anim-event fell; the head and root joints read where it lies) to have it get up there.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
Returns
void
Nothing.
say()
ts
say(
entity,
text,
voice?,
visemes?
): void;Speak a line.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
text | string | Subtitle text; the host decides whether to show it. |
voice? | string | number | Manifest string id or handle of a voice line. |
visemes? | string | Viseme track as JSON, matching the bundle's space. |
Returns
void
Nothing.
setClipWeights()
ts
setClipWeights(
entity,
clips,
weights,
timeScale?
): void;Set explicit per-clip weights on the body layer.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity with a Character component. |
clips | readonly string[] | undefined | Clip names. |
weights | readonly number[] | Float32Array<ArrayBufferLike> | undefined | Positional weights; must be the same length as clips. |
timeScale | number | 1 | Playback rate for the whole layer. Default 1. |
Returns
void
Nothing.
setExpression()
ts
setExpression(
entity,
space,
weights
): void;Set facial expression coefficients.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
space | ExpressionSpace | Coordinate space: 52 ARKit, 387 GNM, or the 68-float view. |
weights | readonly number[] | Float32Array<ArrayBufferLike> | Coefficients; length must match the space. |
Returns
void
Nothing.
setState()
ts
setState(
entity,
state,
vx,
vy,
vz,
grounded?,
facing?
): void;Drive the locomotion state machine.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity with a Character component. |
state | string | undefined | State name, for example `'idle' |
vx | number | undefined | World-space velocity x, drives the locomotion blend. |
vy | number | undefined | World-space velocity y. |
vz | number | undefined | World-space velocity z. |
grounded | boolean | true | Whether the character is on the ground. |
facing? | number | undefined | Optional held world yaw in radians; permits backpedalling without turning. |
Returns
void
Nothing.
stopWalk()
ts
stopWalk(entity): void;Give up a walk to a spot: the character stops where it is, as its takes stop.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
Returns
void
Nothing.
walkTo()
ts
walkTo(
entity,
target,
how?
): void;Send a character to a spot: it turns, walks or runs there and arrives facing the way asked. The motion-event arrived (in ctx.events) says it got there; failed says why not; started and then done, both named stop, say when its stop begins and when it no longer travels; limited says once that the speed it is given (amount) is not the one asked. A velocity given to character.setState while it walks takes over.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
target | Vec3 | The spot, world space, on the floor. |
how | { arrive?: "easy" | "quick"; facing?: number; pace?: number; start?: "moving"; stop?: StopStyle; } | The facing to arrive with (facing, radians about +Y, 0 faces +Z; left out: as it arrives), the pace (pace, metres a second; left out: the set's own walk; above the speeds its walk covers it runs, when its set has a run and the spot is far enough to run to), how it stops (arrive: 'easy', the default, the takes' unhurried stops; 'quick', the shortest stops and turns the set has) and which kind of stop this one walk ends with (stop: 'gradual', it slows and stands upright; 'hard', it brakes; left out: the character's own, see character.motion). arrive says how soon it must be there, stop says which kind of stop; a 'quick' walk that states no stop stops as a quick walk always did. A kind is read on a run's stops: a walk's stop and a sprint's stop are the same under both on the engine's shared set. And how it is begun (start: 'moving', the game says the body is under way already: it comes out of a get-up, it was carried or thrown; the walk is then planned as of a body under way: no turn on the spot first, no start from standing; left out: as its takes have the body). |
how.arrive? | "easy" | "quick" | - |
how.facing? | number | - |
how.pace? | number | - |
how.start? | "moving" | - |
how.stop? | StopStyle | - |
Returns
void
Nothing.
Example
ts
character.walkTo(guide, { x: 2, y: 0, z: -3 }, { facing: Math.PI });
character.walkTo(rider, bikeSide, { pace: 3.4 }); // a run's pace: it runs there
character.walkTo(rider, bikeSide, { pace: 3.4, stop: 'hard' }); // and brakes at the spot
character.walkTo(rider, bikeSide, { pace: 3.4, start: 'moving' }); // out of a get-up: no turn on the spot firstconfig
ts
readonly config: GameConfig;The init config.
contacts
ts
readonly contacts: readonly Contact[];Contacts reported since the previous tick.
data
ts
readonly data: DataFacade;Saved player/game documents and trades. Only the authority writes.
dt
ts
readonly dt: number;Fixed timestep in seconds.
elapsed
ts
readonly elapsed: number;Simulated seconds since init.
events
ts
readonly events: readonly GameEvent[];Host-side occurrences since the previous tick, in order.
frame
ts
readonly frame: number;Monotonic fixed-step counter, starting at 0.
hud
ts
readonly hud: object;The HUD model.
clear()
ts
clear(): void;Drop the HUD: emit an empty model this frame.
Idempotent — calling it every frame emits {} once, exactly like set.
Returns
void
Nothing.
invalidate()
ts
invalidate(): void;Forget what the host has seen, so the next set emits even if the model did not change. Use it after the host reloaded its overlay.
On its own it sends nothing: the next set does. To send an empty model now, call clear().
Returns
void
Nothing.
set()
ts
set(model): boolean;Set the HUD model for this frame.
Nested plain objects are compared by value four levels down, so a model rebuilt inline every frame is recognised as unchanged. Arrays and class instances are compared by identity: keep those out of the model, or build them once and mutate nothing.
Parameters
| Parameter | Type | Description |
|---|---|---|
model | Record<string, unknown> | A JSON-serialisable object. |
Returns
boolean
True when the model changed and JSON will cross this frame.
input
ts
readonly input: object;Keyboard, mouse and gamepad.
touch
ts
touch: object;Fingers on a touch screen, as the host's touch layer packs them: the first finger is the pointer (mouse), a tap is pressed('Tap'), and the thumb sticks, the pinch and the turn are here.
touch.active
Get Signature
ts
get active(): boolean;Is a finger on the screen? (The touch pad is connected.)
Returns
boolean
True while any finger is down.
touch.pinch
Get Signature
ts
get pinch(): number;Two fingers' pinch this step, as a scale factor: over 1 the fingers moved apart (zoom in), under 1 together, exactly 1 with no pinch.
Returns
number
The scale factor.
touch.turn
Get Signature
ts
get turn(): number;Two fingers' turn this step, in radians, counter-clockwise on the screen positive.
Returns
number
The turn.
touch.stick()
ts
stick(side): Axis2;A thumb stick's push.
Parameters
| Parameter | Type | Description |
|---|---|---|
side | "left" | "right" | The left stick (movement) or the right one (the camera). |
Returns
A pooled { x, y }, -1..1, y up the screen positive. Never retain it.
control
Get Signature
ts
get control(): Readonly<NonNullable<InputState["control"]>>;Received page control for this frame. Owned by the SDK; read during the tick.
Returns
Readonly<NonNullable<InputState["control"]>>
The control state received with this input sequence.
focused
Get Signature
ts
get focused(): boolean;Does the canvas have focus? Treat input as neutral when it does not.
Returns
boolean
True while the canvas is focused.
mods
Get Signature
ts
get mods(): InputMods;Keyboard modifier state.
Returns
The modifiers for this frame.
mouse
Get Signature
ts
get mouse(): MouseState;Pointer position, per-frame delta, wheel and button bitsets.
Returns
The mouse state for this frame. Owned by the SDK; never retain it.
action()
ts
action(name): ActionState;Read a declared button into pooled storage. Unknown names throw.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Declared button action name. |
Returns
Pooled button state; read immediately.
axis2()
ts
axis2(
negX,
posX?,
negY?,
posY?,
stick?
): Axis2;Pass a declared axis action name alone, or four keys. A two-axis reading built from four keys, plus a thumb stick on a touch screen: the left one by default, so axis2('A', 'D', 'S', 'W') moves on a phone with no other binding. Pass 'right' for a camera axis, 'none' for keys only. With the left stick and opposing WASD/arrow movement pairs, uses combined movement (both key sets, left touch and first physical pad, radial deadzone and unit-circle clamp), with each binding's requested sign. Page control supplies that same movement when present. Other bindings read only their four keys and the requested touch stick.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
negX | string | undefined | Declared axis name, or key driving x negative, e.g. 'A'. |
posX? | string | undefined | Key that drives x positive, for example 'D'. |
negY? | string | undefined | Key that drives y negative, for example 'S'. |
posY? | string | undefined | Key that drives y positive, for example 'W'. |
stick? | StickSide | 'left' | Which thumb stick to add, 'left' by default. |
Returns
A pooled { x, y } with components in -1..1. Never retain it.
gamepad()
ts
gamepad(index):
| {
axes: ArrayLike<number>;
buttons: number;
connected: boolean;
index: number;
pressed: number;
released: number;
}
| null;One connected gamepad.
Parameters
| Parameter | Type | Description |
|---|---|---|
index | number | Navigator gamepad index. |
Returns
| { axes: ArrayLike<number>; buttons: number; connected: boolean; index: number; pressed: number; released: number; } | null
The gamepad, or null when nothing is connected at that index. Owned by the SDK; never retain it.
isDown()
ts
isDown(key): boolean;Is the key held this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
key | string | A DOM code ('KeyW'), a bare letter/digit ('W', '1') or an alias ('Shift', 'Esc'). |
Returns
boolean
True while the key is down.
mouseDown()
ts
mouseDown(button): boolean;Is a mouse button held?
Parameters
| Parameter | Type | Description |
|---|---|---|
button | number | A MOUSE_BUTTONS value, or a raw bit mask. |
Returns
boolean
True while the button is down.
mousePressed()
ts
mousePressed(button): boolean;Did a mouse button go down this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
button | number | A MOUSE_BUTTONS value, or a raw bit mask. |
Returns
boolean
True on the frame the button went down.
mouseReleased()
ts
mouseReleased(button): boolean;Did a mouse button come up this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
button | number | A MOUSE_BUTTONS value, or a raw bit mask. |
Returns
boolean
True on the frame the button came up.
pressed()
ts
pressed(key): boolean;Did the key go down this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
key | string | A key name. |
Returns
boolean
True on the frame the key went down.
released()
ts
released(key): boolean;Did the key come up this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
key | string | A key name. |
Returns
boolean
True on the frame the key came up.
levels
ts
readonly levels: LevelsFacade;The levels: names(), current, load(ctx, name).
localPlayer
ts
readonly localPlayer: PlayerHandle | null;This page's player on a client; null on the authority and in solo.
music
ts
readonly music: object;Music and the beat.
bar
Get Signature
ts
get bar(): number;Last heard bar number.
Returns
number
beat
Get Signature
ts
get beat(): number;Last heard beat number.
Returns
number
beatInBar
Get Signature
ts
get beatInBar(): number;Last heard beat within the bar.
Returns
number
beatsPerBar
Get Signature
ts
get beatsPerBar(): number;Beats per bar of the last playback request.
Returns
number
bpm
Get Signature
ts
get bpm(): number;Tempo of the last playback request.
Returns
number
layer()
ts
layer(
index,
gain,
fadeMs?
): void;Change a stem gain.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
index | number | undefined | Stem index. |
gain | number | undefined | Linear gain. |
fadeMs | number | 0 | Ramp duration. |
Returns
void
nearestBeat()
ts
nearestBeat(): number;The number of the beat nearest to now, as heard: the beat offsetMs() measures from. A press just before beat 12 gives 12, just after it also 12, so a chart of beat numbers is judged with nearestBeat() === note and Math.abs(offsetMs()).
Returns
number
The beat number, or NaN before a beat or without a tempo.
Example
ts
import { music } from 'gameable';
if (music.nearestBeat() === 12 && Math.abs(music.offsetMs()) <= 45) console.log('perfect');offsetMs()
ts
offsetMs(): number;Signed milliseconds since the nearest beat; negative when it is still ahead.
Returns
number
Offset, or NaN before a beat or without a tempo.
play()
ts
play(assets, options?): void;Stream a track or playlist.
Parameters
| Parameter | Type | Description |
|---|---|---|
assets | string | number | readonly (string | number)[] | Manifest ids or handles. |
options? | MusicOptions | Playback options. |
Returns
void
stems()
ts
stems(assets, options?): void;Play synchronized stems.
Parameters
| Parameter | Type | Description |
|---|---|---|
assets | readonly (string | number)[] | Manifest ids or handles. |
options? | StemOptions | Playback options and gains. |
Returns
void
stop()
ts
stop(fadeMs?): void;Stop music.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
fadeMs | number | 0 | Fade duration. |
Returns
void
net
ts
readonly net: NetFacade;Where this guest runs, game messages in and out, and local-only commands.
pause
ts
readonly pause: object;Named pause owners; release from the host page while simulation is stopped.
pop()
ts
pop(reason): void;Parameters
| Parameter | Type |
|---|---|
reason | string |
Returns
void
push()
ts
push(reason): void;Parameters
| Parameter | Type |
|---|---|
reason | string |
Returns
void
reasons()
ts
reasons(): readonly string[];Returns
readonly string[]
physics
ts
readonly physics: object;Physics queries and body commands.
ALL_LAYERS
ts
ALL_LAYERS: CollisionLayers;Every collision layer, for queries that should hit anything.
vehicle
ts
vehicle: object;Host arcade handling on guest body handles.
vehicle.create()
ts
create(
body,
settings,
initialState?
): Readonly<VehicleState>;Attach once to an existing dynamic body. State is borrowed until removal.
Parameters
| Parameter | Type |
|---|---|
body | number |
settings | VehicleSettings |
initialState? | Readonly<VehicleState> |
Returns
Readonly<VehicleState>
Example
ts
physics.vehicle.create(body, settings);vehicle.remove()
ts
remove(body): void;Remove handling; the chassis remains alive. Safe to repeat.
Parameters
| Parameter | Type |
|---|---|
body | number |
Returns
void
Example
ts
physics.vehicle.remove(body);vehicle.reset()
ts
reset(
body,
position,
rotation
): void;Teleport and clear motion, controls and handling history.
Parameters
| Parameter | Type |
|---|---|
body | number |
position | Vec3 |
rotation | Quat |
Returns
void
Example
ts
physics.vehicle.reset(body, position, rotation);vehicle.setInput()
ts
setInput(
body,
controls,
gripScale?
): void;Submit transient controls; omitted steps use the host parking brake.
Parameters
| Parameter | Type | Default value |
|---|---|---|
body | number | undefined |
controls | Readonly<VehicleInput> | undefined |
gripScale | number | 1 |
Returns
void
Example
ts
physics.vehicle.setInput(body, controls, 0.5);vehicle.state()
ts
state(body): Readonly<VehicleState> | undefined;Borrow the last post-step state without allocating.
Parameters
| Parameter | Type |
|---|---|
body | number |
Returns
Readonly<VehicleState> | undefined
Example
ts
const speed = physics.vehicle.state(body)?.speed;applyImpulse()
ts
applyImpulse(
entity,
x,
y,
z,
atX?,
atY?,
atZ?
): void;Apply a one-shot impulse.
With no application point the impulse acts at the centre of mass. Give one — all three coordinates — to apply it off-centre and impart spin.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a body. |
x | number | Impulse x, newton-seconds. |
y | number | Impulse y. |
z | number | Impulse z. |
atX? | number | World-space application point x, or omit for the centre of mass. |
atY? | number | Application point y. |
atZ? | number | Application point z. |
Returns
void
Nothing.
boxCast()
ts
boxCast(
position,
halfExtents,
rotation,
direction,
maxDistance,
mask?,
ignoreEntity?
): RayHit | null;Cast a box with a quaternion orientation.
Parameters
| Parameter | Type | Description |
|---|---|---|
position | Vec3 | World-space query centre. |
halfExtents | Vec3 | Box half-size in metres. |
rotation | Quat | Unit quaternion orientation. |
direction | Vec3 | Sweep direction; need not be normalised. |
maxDistance | number | Maximum travel in metres. |
mask? | CollisionLayers | Layers to consider, or every layer when omitted. |
ignoreEntity? | number | Entity to skip. |
Returns
RayHit | null
The closest hit, or null on a miss; hit.distance is the shape travel in metres.
Example
ts
import { defineGame, physics } from 'gameable';
export default defineGame({
init() {
const position = { x: 0, y: 1, z: 0 };
const rotation = { x: 0, y: 0, z: 0, w: 1 };
const forward = { x: 0, y: 0, z: 1 };
const halfExtents = { x: 0.5, y: 0.5, z: 0.5 };
const hit = physics.boxCast(position, halfExtents, rotation, forward, 1);
console.log('can the crate be pushed forward one metre?', hit === null);
},
});capsuleCast()
ts
capsuleCast(
position,
radius,
halfHeight,
rotation,
direction,
maxDistance,
mask?,
ignoreEntity?
): RayHit | null;Cast a capsule; halfHeight is half its straight segment.
Parameters
| Parameter | Type | Description |
|---|---|---|
position | Vec3 | World-space query centre. |
radius | number | Radius in metres. |
halfHeight | number | Half the straight capsule segment in metres. |
rotation | Quat | Unit quaternion orientation. |
direction | Vec3 | Sweep direction; need not be normalised. |
maxDistance | number | Maximum travel in metres. |
mask? | CollisionLayers | Layers to consider, or every layer when omitted. |
ignoreEntity? | number | Entity to skip. |
Returns
RayHit | null
The closest hit, or null on a miss; hit.distance is the shape travel in metres.
Example
ts
import { defineGame, physics } from 'gameable';
export default defineGame({
init() {
const position = { x: 0, y: 1, z: 0 };
const rotation = { x: 0, y: 0, z: 0, w: 1 };
const forward = { x: 0, y: 0, z: 1 };
const hit = physics.capsuleCast(position, 0.3, 0.6, rotation, forward, 0.4);
console.log('can the character step here?', hit === null);
},
});distance()
ts
distance(
a,
b,
options
): number;Create a distance joint. Bodyless entities return 0; b=0 anchors to the world. With no limits, this is a rigid rod that keeps its initial length. Set min/max in metres to constrain a rope or rod length.
Parameters
| Parameter | Type | Description |
|---|---|---|
a | number | First entity, with a physics body. |
b | number | Second entity, or 0 to join to the world. |
options | { anchor: Vec3; anchorB?: Vec3; max?: number; min?: number; spring?: JointSpring; } | Joint or motor settings. |
options.anchor | Vec3 | World-space anchor at creation. |
options.anchorB? | Vec3 | World-space second distance-joint end. |
options.max? | number | Upper linear limit in metres. |
options.min? | number | Lower linear limit in metres. |
options.spring? | JointSpring | Limit frequency in Hz and damping ratio. |
Returns
number
The joint id, or 0 when either entity has no body (b = 0 means the world).
Example
ts
import { defineGame, physics, prefab } from 'gameable';
const Weight = prefab({ body: { shape: 'sphere', kind: 'dynamic' } });
export default defineGame({
init(ctx) {
const weight = ctx.spawn(Weight, { x: 0, y: 1, z: 0 });
// No limits: a rigid rod that keeps its initial 3 metre length.
physics.distance(weight, 0, {
anchor: { x: 0, y: 1, z: 0 },
anchorB: { x: 0, y: 4, z: 0 },
});
},
});fixed()
ts
fixed(
a,
b,
options?
): number;Create a fixed joint. Bodyless entities return 0; b=0 anchors to the world.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
a | number | undefined | First entity, with a physics body. |
b | number | undefined | Second entity, or 0 to join to the world. |
options | { anchor?: Vec3; } | EMPTY_JOINT_OPTIONS | Joint or motor settings. |
options.anchor? | Vec3 | undefined | World-space anchor at creation. |
Returns
number
The joint id, or 0 when either entity has no body (b = 0 means the world).
Example
ts
import { defineGame, physics, prefab } from 'gameable';
const Crate = prefab({ body: { shape: 'box', kind: 'dynamic' } });
export default defineGame({
init(ctx) {
const crateA = ctx.spawn(Crate, { x: 0, y: 1, z: 0 });
const crateB = ctx.spawn(Crate, { x: 1.1, y: 1, z: 0 });
physics.fixed(crateA, crateB); // Weld the two crates together.
},
});hinge()
ts
hinge(
a,
b,
options
): number;Create a hinge joint. Bodyless entities return 0; b=0 anchors to the world.
Values and targets measure how far entity a has moved relative to entity b (or the world). Slider positive is along +axis; hinge positive follows the right-hand rule about +axis. Rotation values and rotational position targets are degrees; angular velocity targets are degrees per second.
Parameters
| Parameter | Type | Description |
|---|---|---|
a | number | First entity, with a physics body. |
b | number | Second entity, or 0 to join to the world. |
options | { anchor: Vec3; axis: Vec3; friction?: number; maxDeg?: number; minDeg?: number; spring?: JointSpring; } | Joint or motor settings. |
options.anchor | Vec3 | World-space anchor at creation. |
options.axis | Vec3 | World-space axis; positive motion follows +axis. |
options.friction? | number | Maximum friction torque in N·m. |
options.maxDeg? | number | Upper angular limit in degrees. |
options.minDeg? | number | Lower angular limit in degrees. |
options.spring? | JointSpring | Limit frequency in Hz and damping ratio. |
Returns
number
The joint id, or 0 when either entity has no body (b = 0 means the world).
Example
ts
import { defineGame, physics, prefab } from 'gameable';
const Door = prefab({ body: { shape: 'box', dims: [0.5, 1, 0.05], kind: 'dynamic' } });
export default defineGame({
init(ctx) {
const door = ctx.spawn(Door, { x: 0.5, y: 1, z: 0 });
physics.hinge(door, 0, {
anchor: { x: 0, y: 1, z: 0 },
axis: { x: 0, y: 1, z: 0 },
minDeg: -90,
maxDeg: 90,
});
},
});isGrounded()
ts
isGrounded(entity): boolean;Actual walkable ground contact from the last host physics step. No host call. Unknown, steep and unsupported contacts return false, even at a jump apex.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Character entity. |
Returns
boolean
Whether the character is supported by walkable ground.
jointValue()
ts
jointValue(id, axis?): number | null;Read a joint coordinate, degrees for rotation, metres for translation or distance length. Distance returns the current unsigned length; unavailable coordinates return null.
Values and targets measure how far entity a has moved relative to entity b (or the world). Slider positive is along +axis; hinge positive follows the right-hand rule about +axis. Rotation values and rotational position targets are degrees; angular velocity targets are degrees per second.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
id | number | undefined | Guest-minted joint handle. |
axis | number | 0 | Joint axis: 0 for one-axis joints, 0 through 5 for six-dof. |
Returns
number | null
The coordinate in degrees for rotation or metres for translation/length, or null when unavailable.
Example
ts
import { defineGame, physics, prefab } from 'gameable';
const Lever = prefab({ body: { shape: 'box', kind: 'dynamic' } });
let leverJoint = 0;
export default defineGame({
init(ctx) {
const lever = ctx.spawn(Lever, { x: 0, y: 1, z: 0 });
leverJoint = physics.hinge(lever, 0, {
anchor: { x: 0, y: 1, z: 0 },
axis: { x: 1, y: 0, z: 0 },
minDeg: -90,
maxDeg: 90,
});
},
systems: [
() => {
const angle = physics.jointValue(leverJoint);
const isLeverDown = angle !== null && angle < -80;
if (isLeverDown) console.log('lever down');
},
],
});moveCharacter()
ts
moveCharacter(
entity,
vx,
vy,
vz,
jump?,
crouch?,
maxSlopeDeg?
): void;Drive a character body for this step.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity whose body was created with kind: 'character'. |
vx | number | undefined | Desired world-space velocity x, metres per second. |
vy | number | undefined | Desired world-space velocity y. |
vz | number | undefined | Desired world-space velocity z. |
jump | boolean | false | Request a jump this step. |
crouch | boolean | false | Request a crouch this step. |
maxSlopeDeg | number | 45 | Maximum walkable slope. |
Returns
void
Nothing.
overlapBox()
ts
overlapBox(
position,
halfExtents,
rotation,
maxResults?,
mask?,
ignoreEntity?
): readonly OverlapHit[];Overlap a box.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
position | Vec3 | undefined | World-space query centre. |
halfExtents | Vec3 | undefined | Box half-size in metres. |
rotation | Quat | undefined | Unit quaternion orientation. |
maxResults | number | 16 | Maximum number of hits. |
mask? | CollisionLayers | undefined | Layers to consider, or every layer when omitted. |
ignoreEntity? | number | undefined | Entity to skip. |
Returns
readonly OverlapHit[]
The overlapping hits, nearest first; an empty list when nothing overlaps.
Example
ts
import { defineGame, physics } from 'gameable';
export default defineGame({
init() {
const position = { x: 0, y: 1, z: 0 };
const rotation = { x: 0, y: 0, z: 0, w: 1 };
const halfExtents = { x: 2, y: 1, z: 2 };
const hits = physics.overlapBox(position, halfExtents, rotation);
console.log(
'bodies in this area',
hits.map((hit) => hit.entity),
);
},
});overlapCapsule()
ts
overlapCapsule(
position,
radius,
halfHeight,
rotation,
maxResults?,
mask?,
ignoreEntity?
): readonly OverlapHit[];Overlap a capsule.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
position | Vec3 | undefined | World-space query centre. |
radius | number | undefined | Radius in metres. |
halfHeight | number | undefined | Half the straight capsule segment in metres. |
rotation | Quat | undefined | Unit quaternion orientation. |
maxResults | number | 16 | Maximum number of hits. |
mask? | CollisionLayers | undefined | Layers to consider, or every layer when omitted. |
ignoreEntity? | number | undefined | Entity to skip. |
Returns
readonly OverlapHit[]
The overlapping hits, nearest first; an empty list when nothing overlaps.
Example
ts
import { defineGame, physics } from 'gameable';
export default defineGame({
init() {
const position = { x: 0, y: 1, z: 0 };
const rotation = { x: 0, y: 0, z: 0, w: 1 };
const hits = physics.overlapCapsule(position, 2, 1, rotation);
console.log(
'bodies in this area',
hits.map((hit) => hit.entity),
);
},
});overlapShape()
ts
overlapShape(
shape,
position,
rotation,
maxResults?,
mask?,
ignoreEntity?
): readonly OverlapHit[];Overlap a primitive shape.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
shape | QueryShape | undefined | Primitive shape and its dimensions in metres. |
position | Vec3 | undefined | World-space query centre. |
rotation | Quat | undefined | Unit quaternion orientation. |
maxResults | number | 16 | Maximum number of hits. |
mask? | CollisionLayers | undefined | Layers to consider, or every layer when omitted. |
ignoreEntity? | number | undefined | Entity to skip. |
Returns
readonly OverlapHit[]
Hits nearest first, with the deepest contact point on each other body and real penetration depth (bounds centre and zero depth if no contact is available).
Example
ts
import { defineGame, physics } from 'gameable';
export default defineGame({
init() {
const position = { x: 0, y: 1, z: 0 };
const rotation = { x: 0, y: 0, z: 0, w: 1 };
const shape = { kind: 'cylinder', halfExtents: { x: 2, y: 1, z: 0 } } as const;
const hits = physics.overlapShape(shape, position, rotation);
console.log(
'bodies in this area',
hits.map((hit) => hit.entity),
);
},
});overlapSphere()
ts
overlapSphere(
center,
radius,
maxResults?,
mask?,
ignoreEntity?
): readonly OverlapHit[];Bodies overlapping a sphere, nearest first.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
center | Vec3 | undefined | Sphere centre. |
radius | number | undefined | Sphere radius in metres. |
maxResults | number | 16 | Cap on returned hits. |
mask? | CollisionLayers | undefined | Layers to consider; defaults to every layer. |
ignoreEntity? | number | undefined | Entity to skip. |
Returns
readonly OverlapHit[]
The overlapping bodies.
point()
ts
point(
a,
b,
options
): number;Create a point joint. Bodyless entities return 0; b=0 anchors to the world.
Parameters
| Parameter | Type | Description |
|---|---|---|
a | number | First entity, with a physics body. |
b | number | Second entity, or 0 to join to the world. |
options | { anchor: Vec3; } | Joint or motor settings. |
options.anchor | Vec3 | World-space anchor at creation. |
Returns
number
The joint id, or 0 when either entity has no body (b = 0 means the world).
Example
ts
import { defineGame, physics, prefab } from 'gameable';
const Lamp = prefab({ body: { shape: 'sphere', kind: 'dynamic' } });
export default defineGame({
init(ctx) {
const lamp = ctx.spawn(Lamp, { x: 0, y: 3, z: 0 });
physics.point(lamp, 0, { anchor: { x: 0, y: 4, z: 0 } });
},
});raycast()
ts
raycast(
origin,
direction,
maxDistance,
mask?,
ignoreEntity?,
ignoreBody?
): RayHit | null;Closest hit along a ray.
Parameters
| Parameter | Type | Description |
|---|---|---|
origin | Vec3 | World-space ray origin. |
direction | Vec3 | Ray direction; need not be normalised. |
maxDistance | number | Maximum distance in metres. |
mask? | CollisionLayers | Layers to consider; defaults to every layer. |
ignoreEntity? | number | Entity to skip, usually the caster. |
ignoreBody? | number | Additional body to skip, such as a projectile while ignoring its owner entity. |
Returns
RayHit | null
The hit, or null on a miss. The hit object comes from the host and is freshly allocated: this call is not allocation-free.
raycastBatch()
ts
raycastBatch(rays): readonly (RayHit | null | undefined)[];Many rays in one round trip. Result index i matches rays[i].
Parameters
| Parameter | Type | Description |
|---|---|---|
rays | readonly object[] | The rays. Build them once and mutate them in place. |
Returns
readonly (RayHit | null | undefined)[]
One result per ray; undefined or null entries are misses.
removeJoint()
ts
removeJoint(id): void;Remove a joint.
Parameters
| Parameter | Type | Description |
|---|---|---|
id | number | Guest-minted joint handle. |
Returns
void
Nothing.
Example
ts
import { defineGame, physics, prefab } from 'gameable';
const Crate = prefab({ body: { shape: 'box', kind: 'dynamic' } });
export default defineGame({
init(ctx) {
const crate = ctx.spawn(Crate, { x: 0, y: 1, z: 0 });
const weld = physics.fixed(crate, 0);
physics.removeJoint(weld);
},
});setEnabled()
ts
setEnabled(entity, enabled): void;Enable or disable a body in the broad phase.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a body. |
enabled | boolean | Whether the body participates. |
Returns
void
Nothing.
setMotor()
ts
setMotor(id, options): void;Set a motor; rotational targets use degrees or degrees per second.
Values and targets measure how far entity a has moved relative to entity b (or the world). Slider positive is along +axis; hinge positive follows the right-hand rule about +axis. Rotation values and rotational position targets are degrees; angular velocity targets are degrees per second.
Parameters
| Parameter | Type | Description |
|---|---|---|
id | number | Guest-minted joint handle. |
options | { axis?: number; maxForce?: number; mode: MotorMode; target: number; } | Joint or motor settings. |
options.axis? | number | Motor axis index: 0 for hinge/slider, 0..5 for six-dof. |
options.maxForce? | number | Force limit in N or torque limit in N·m; omitted or 0 means 100, too weak to lift anything heavy (a 20 kg lift needs over 196 N). |
options.mode | MotorMode | Off, velocity, or position control. |
options.target | number | Metres or degrees; per second for velocity mode. |
Returns
void
Nothing.
Example
ts
import { defineGame, physics, prefab } from 'gameable';
const Body = prefab({ body: { shape: 'box', kind: 'dynamic' } });
export default defineGame({
init(ctx) {
const door = ctx.spawn(Body, { x: 0.5, y: 1, z: 0 });
const doorJoint = physics.hinge(door, 0, {
anchor: { x: 0, y: 1, z: 0 },
axis: { x: 0, y: 1, z: 0 },
minDeg: -90,
maxDeg: 90,
});
physics.setMotor(doorJoint, { mode: 'position', target: 90 });
const lift = ctx.spawn(Body, { x: 3, y: 1, z: 0 });
const liftJoint = physics.slider(lift, 0, {
anchor: { x: 3, y: 1, z: 0 },
axis: { x: 0, y: 1, z: 0 },
min: 0,
max: 5,
});
physics.setMotor(liftJoint, { mode: 'velocity', target: 1 }); // 1 m/s upward.
},
});setVelocity()
ts
setVelocity(
entity,
x,
y,
z,
ax?,
ay?,
az?
): void;Overwrite a body's velocity.
Angular velocity is left alone unless all three angular components are given.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a body. |
x | number | Linear velocity x. |
y | number | Linear velocity y. |
z | number | Linear velocity z. |
ax? | number | Angular velocity x, radians per second. |
ay? | number | Angular velocity y. |
az? | number | Angular velocity z. |
Returns
void
Nothing.
shapeCast()
ts
shapeCast(
shape,
position,
rotation,
direction,
maxDistance,
mask?,
ignoreEntity?
): RayHit | null;Cast a primitive shape along a direction.
Parameters
| Parameter | Type | Description |
|---|---|---|
shape | QueryShape | Primitive shape and its dimensions in metres. |
position | Vec3 | World-space query centre. |
rotation | Quat | Unit quaternion orientation. |
direction | Vec3 | Sweep direction; need not be normalised. |
maxDistance | number | Maximum travel in metres. |
mask? | CollisionLayers | Layers to consider, or every layer when omitted. |
ignoreEntity? | number | Entity to skip. |
Returns
RayHit | null
The closest hit, or null on a miss; hit.distance is the shape travel in metres.
Example
ts
import { defineGame, physics } from 'gameable';
export default defineGame({
init() {
const position = { x: 0, y: 1, z: 0 };
const rotation = { x: 0, y: 0, z: 0, w: 1 };
const forward = { x: 0, y: 0, z: 1 };
const shape = { kind: 'cylinder', halfExtents: { x: 0.4, y: 0.5, z: 0 } } as const;
const hit = physics.shapeCast(shape, position, rotation, forward, 2);
console.log('travel before contact', hit?.distance);
},
});sixDof()
ts
sixDof(
a,
b,
options
): number;Create a sixDof joint. Bodyless entities return 0; b=0 anchors to the world.
Parameters
| Parameter | Type | Description |
|---|---|---|
a | number | First entity, with a physics body. |
b | number | Second entity, or 0 to join to the world. |
options | { anchor: Vec3; axes: readonly [JointAxis, JointAxis, JointAxis, JointAxis, JointAxis, JointAxis]; } | Joint or motor settings. |
options.anchor | Vec3 | World-space anchor at creation. |
options.axes | readonly [JointAxis, JointAxis, JointAxis, JointAxis, JointAxis, JointAxis] | Six axis settings: tx, ty, tz, rx, ry, rz; rotational limits in degrees. |
Returns
number
The joint id, or 0 when either entity has no body (b = 0 means the world).
Example
ts
import { defineGame, physics, prefab } from 'gameable';
const Hook = prefab({ body: { shape: 'box', kind: 'dynamic' } });
const locked = { mode: 'locked', min: 0, max: 0 } as const;
const free = { mode: 'free', min: 0, max: 0 } as const;
export default defineGame({
init(ctx) {
const hook = ctx.spawn(Hook, { x: 0, y: 3, z: 0 });
physics.sixDof(hook, 0, {
anchor: { x: 0, y: 3, z: 0 },
axes: [locked, locked, locked, free, free, free],
});
},
});slider()
ts
slider(
a,
b,
options
): number;Create a slider joint. Bodyless entities return 0; b=0 anchors to the world.
Values and targets measure how far entity a has moved relative to entity b (or the world). Slider positive is along +axis; hinge positive follows the right-hand rule about +axis. Rotation values and rotational position targets are degrees; angular velocity targets are degrees per second.
Parameters
| Parameter | Type | Description |
|---|---|---|
a | number | First entity, with a physics body. |
b | number | Second entity, or 0 to join to the world. |
options | { anchor: Vec3; axis: Vec3; friction?: number; max?: number; min?: number; spring?: JointSpring; } | Joint or motor settings. |
options.anchor | Vec3 | World-space anchor at creation. |
options.axis | Vec3 | World-space axis; positive motion follows +axis. |
options.friction? | number | Maximum friction force in N. |
options.max? | number | Upper linear limit in metres. |
options.min? | number | Lower linear limit in metres. |
options.spring? | JointSpring | Limit frequency in Hz and damping ratio. |
Returns
number
The joint id, or 0 when either entity has no body (b = 0 means the world).
Example
ts
import { defineGame, physics, prefab } from 'gameable';
const Drawer = prefab({ body: { shape: 'box', kind: 'dynamic' } });
export default defineGame({
init(ctx) {
const drawer = ctx.spawn(Drawer, { x: 0, y: 1, z: 0 });
physics.slider(drawer, 0, {
anchor: { x: 0, y: 1, z: 0 },
axis: { x: 0, y: 0, z: 1 },
min: 0,
max: 0.6,
});
},
});sphereCast()
ts
sphereCast(
position,
radius,
direction,
maxDistance,
mask?,
ignoreEntity?
): RayHit | null;Cast a sphere.
Parameters
| Parameter | Type | Description |
|---|---|---|
position | Vec3 | World-space query centre. |
radius | number | Radius in metres. |
direction | Vec3 | Sweep direction; need not be normalised. |
maxDistance | number | Maximum travel in metres. |
mask? | CollisionLayers | Layers to consider, or every layer when omitted. |
ignoreEntity? | number | Entity to skip. |
Returns
RayHit | null
The closest hit, or null on a miss; hit.distance is the shape travel in metres.
Example
ts
import { defineGame, physics } from 'gameable';
export default defineGame({
init() {
const position = { x: 0, y: 1, z: 0 };
const forward = { x: 0, y: 0, z: 1 };
const hit = physics.sphereCast(position, 0.5, forward, 2);
console.log('will the ball fit through this passage?', hit === null);
},
});teleport()
ts
teleport(
entity,
x,
y,
z,
rotation?
): void;Teleport a body, clearing its velocities.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a body. |
x | number | Position x. |
y | number | Position y. |
z | number | Position z. |
rotation? | Quat | Optional facing; defaults to identity for existing callers. |
Returns
void
Nothing.
player
ts
readonly player: number;The entity the player block spawned in a single-player game, or 0; in a room, playerEntity(id).
players
ts
readonly players: Players;Players by id; host, and list in id order. Solo uses seat 0.
rng
ts
readonly rng: Rng;The seeded generator. Never Math.random.
rules
ts
readonly rules: Readonly<Record<string, unknown>>;The rules object from defineGame, verbatim.
started
ts
readonly started: boolean;True after the page's start event, until init; use to gate gameplay.
ui
ts
readonly ui: object;The game's UI.
events
Get Signature
ts
get events(): readonly UiEvent[];This tick's UI events in arrival order; the array is reused each tick.
Returns
readonly UiEvent[]
The pooled event array.
clear()
ts
clear(): void;Clear the UI once; subsequent clears emit nothing.
Returns
void
clicked()
ts
clicked(id): boolean;Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Button or clickable card id. |
Returns
boolean
Whether it was clicked this tick.
dropped()
ts
dropped(id): UiEvent | null;Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Draggable node id. |
Returns
UiEvent | null
Its drop event this tick, including the target, or null.
invalidate()
ts
invalidate(): void;Forget the previous model so the next set emits again.
Returns
void
set()
ts
set(nodes, options?): boolean;Emit a model only when its value changes, comparing up to 24 levels.
Parameters
| Parameter | Type | Description |
|---|---|---|
nodes | UiNode | readonly UiNode[] | One node or the ordered top-level nodes. |
options? | { theme?: UiTheme; } | Optional theme overrides. |
options.theme? | UiTheme | Theme token overrides. |
Returns
boolean
True when JSON will cross this frame.
submitted()
ts
submitted(id): boolean;Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Input id. |
Returns
boolean
Whether Enter submitted it this tick.
value()
ts
value(id): string | null;Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Input id. |
Returns
string | null
Latest changed or submitted text across ticks, or null if unedited.
vfx
ts
readonly vfx: object;Effects and post.
burst()
ts
burst(
preset,
at,
options?
): void;Play a one-shot preset at a world position.
Parameters
| Parameter | Type | Description |
|---|---|---|
preset | VfxPreset | Built-in preset name. |
at | Vec3 | World position. |
options? | BurstOptions | Optional overrides. |
Returns
void
Nothing.
Example
ts
import { vfx } from 'gameable';
vfx.burst('dust', { x: 0, y: 0, z: 0 });move()
ts
move(id, at): void;Move an emitter (or change its entity offset).
Parameters
| Parameter | Type | Description |
|---|---|---|
id | number | Handle from start; 0 is ignored. |
at | Vec3 | Position or offset. |
Returns
void
Nothing.
Example
ts
import { vfx } from 'gameable';
const id = vfx.start('fire', {});
vfx.move(id, { x: 1, y: 0, z: 0 });post()
ts
post(settings): void;Apply partial post settings.
Parameters
| Parameter | Type | Description |
|---|---|---|
settings | PostSettings | Fields to change; reset first restores neutral values. |
Returns
void
Nothing.
Example
ts
import { vfx } from 'gameable';
vfx.post({ reset: true, exposure: 1.2 });start()
ts
start(preset, options): number;Start an emitter that runs until stopped.
Parameters
| Parameter | Type | Description |
|---|---|---|
preset | VfxPreset | Built-in preset name. |
options | StartOptions | Position or entity attachment and overrides. |
Returns
number
A guest-minted effect handle.
Example
ts
import { vfx } from 'gameable';
const id = vfx.start('smoke', { at: { x: 0, y: 0, z: 0 } });
vfx.stop(id);stop()
ts
stop(id): void;Stop an emitter.
Parameters
| Parameter | Type | Description |
|---|---|---|
id | number | Handle from start; 0 is ignored. |
Returns
void
Nothing.
Example
ts
import { vfx } from 'gameable';
const id = vfx.start('trail', {});
vfx.stop(id);world
ts
readonly world: object;The bitecs world, for query and addComponent.
Methods
assetId()
ts
assetId(name): number;Resolve a manifest string id to a handle, cached.
Parameters
| Parameter | Type |
|---|---|
name | string |
Returns
number
despawn()
ts
despawn(entity): void;Destroy an entity and its body.
Parameters
| Parameter | Type |
|---|---|
entity | number |
Returns
void
playerEntity()
ts
playerEntity(id): number;A room player's spawned entity, or 0.
Parameters
| Parameter | Type |
|---|---|
id | number |
Returns
number
spawn()
ts
spawn(
def,
position,
rotation?
): number;Instantiate a prefab.
Parameters
| Parameter | Type |
|---|---|
def | PrefabDef |
position | Vec3 |
rotation? | Quat |
Returns
number
GameDataEvent
The room's saved game-wide document as JSON.
Properties
data
ts
data: string;GameError
The error payload of init and restore.
Properties
code
ts
code: ErrorCode;message
ts
message: string;GameModeHooks
Mode extension points, independent of actor tick.
Example
ts
const hooks: GameModeHooks<GameModeProps> = {};Type Parameters
| Type Parameter |
|---|
P extends object |
Methods
onLogout()?
ts
optional onLogout(
self,
controller,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
controller | ActorHandle |
ctx | GameContext |
Returns
void
onMatchEnded()?
ts
optional onMatchEnded(
self,
event,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
event | Readonly<RuleEvent> |
ctx | GameContext |
Returns
void
onMatchStateChanged()?
ts
optional onMatchStateChanged(
self,
state,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
state | MatchState |
ctx | GameContext |
Returns
void
onPhaseEnded()?
ts
optional onPhaseEnded(
self,
event,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
event | Readonly<RuleEvent> |
ctx | GameContext |
Returns
void
onPhaseStarted()?
ts
optional onPhaseStarted(
self,
event,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
event | Readonly<RuleEvent> |
ctx | GameContext |
Returns
void
onPlayerDied()?
ts
optional onPlayerDied(
self,
victim,
killer,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
victim | ActorHandle |
killer | ActorHandle<object> | null |
ctx | GameContext |
Returns
void
onPostLogin()?
ts
optional onPostLogin(
self,
controller,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
controller | ActorHandle |
ctx | GameContext |
Returns
void
onRoundEnded()?
ts
optional onRoundEnded(
self,
event,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
event | Readonly<RuleEvent> |
ctx | GameContext |
Returns
void
onRoundStarted()?
ts
optional onRoundStarted(
self,
event,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
event | Readonly<RuleEvent> |
ctx | GameContext |
Returns
void
readyToEndMatch()?
ts
optional readyToEndMatch(self, ctx): boolean;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
ctx | GameContext |
Returns
boolean
readyToStartMatch()?
ts
optional readyToStartMatch(self, ctx): boolean;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<P> |
ctx | GameContext |
Returns
boolean
GameModeProps
Match rules and framework classes.
Example
ts
const rules: Partial<GameModeProps> = { matchTime: 60 };Properties
allowLateJoin
ts
allowLateJoin: boolean;autoAssign
ts
autoAssign: "none" | "balanced";friendlyFire
ts
friendlyFire: boolean;gameStateClass
ts
gameStateClass: string;killScore
ts
killScore: number;lastTeamStanding
ts
lastTeamStanding: boolean;matchTime
ts
matchTime: number;minPlayers
ts
minPlayers: number;phases
ts
phases: readonly object[];Ordered phases, repeated for each round; an empty list keeps legacy match flow.
playerControllerClass
ts
playerControllerClass: string;playerStateClass
ts
playerStateClass: string;respawnDelay
ts
respawnDelay: number;restartAfter
ts
restartAfter: number;rounds
ts
rounds: number;roundsToWin
ts
roundsToWin: number;scoreToWin
ts
scoreToWin: number;startDelay
ts
startDelay: number;teams
ts
teams: readonly object[];tieBreak
ts
tieBreak: "draw" | "suddenDeath";GamepadState
One gamepad in the standard mapping.
Properties
axes
ts
axes: ArrayLike<number>;buttons
ts
buttons: number;connected
ts
connected: boolean;index
ts
index: number;pressed
ts
pressed: number;released
ts
released: number;GameplayModule
A headless module with snapshot-safe initialization and one fixed-step system.
Example
ts
import type { GameplayModule } from 'gameable';
const module: GameplayModule = { init() {}, system() {} };
console.log(module.system);Extended by
Properties
init
ts
init: (ctx) => void;Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
system
ts
system: (ctx) => void;Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
GameplayPart
The lifecycle every gameplay part shares.
Example
ts
import { createTimers, type GameplayPart } from 'gameable';
const part: GameplayPart = createTimers({ capacity: 4 });
part.reset();Extended by
Methods
reset()
ts
reset(): void;Back to the state right after creation. Call from init.
Returns
void
restore()
ts
restore(state, options?): void;Read back what snapshot returned. Throws on a malformed state.
Parameters
| Parameter | Type |
|---|---|
state | unknown |
options? | { crossBuild?: boolean; } |
options.crossBuild? | boolean |
Returns
void
snapshot()
ts
snapshot(): unknown;Plain JSON-safe data for defineGame({ snapshot }).
Returns
unknown
GameSpec
Everything a game declares.
Properties
actions?
ts
optional actions?: Record<string, ActionDecl>;Named device bindings, compiled at guest creation.
assets?
ts
optional assets?: readonly string[];Manifest string ids to resolve during init and cache.
features?
ts
optional features?: FeatureSpec;Engine modules this game needs (featuresOf).
framework?
ts
optional framework?: "default";Opt in to default match actors, an origin start and match HUD.
init?
ts
optional init?: (ctx) => void;Extra setup, run after the declarative spawns.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
level?
ts
optional level?: LevelFile;Level actors: the level main.
levels?
ts
optional levels?: Record<string, LevelFile>;Named levels, one at a time; ctx.levels.load switches.
limits?
ts
optional limits?: object;Spawn caps; default 64 per step, 2048 live.
actors?
ts
optional actors?: number;spawnsPerStep?
ts
optional spawnsPerStep?: number;player?
ts
optional player?: PlayerSpec;Player and camera: spawned at solo init, or per room join on the authority.
restore?
ts
optional restore?: (state, options?) => void;Read back what snapshot returned.
Parameters
| Parameter | Type |
|---|---|
state | unknown |
options? | { crossBuild?: boolean; } |
options.crossBuild? | boolean |
Returns
void
rules?
ts
optional rules?: Record<string, unknown>;Arbitrary tuning values, handed back as ctx.rules.
save?
ts
optional save?: object;Save schema; migrate[n] upgrades version n - 1 to n. Omit for legacy JSON.
migrate?
ts
optional migrate?: Record<number, (data) => unknown>;version
ts
version: number;shutdown?
ts
optional shutdown?: (ctx) => void;Called once before the guest is torn down.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
snapshot?
ts
optional snapshot?: () => unknown;JSON state folded into snapshot().
Returns
unknown
spawns?
ts
optional spawns?: readonly SpawnSpec[];Entities to create during init.
startLevel?
ts
optional startLevel?: string;Level init loads: options' level, else main, else the first.
systems?
ts
optional systems?: readonly (System | SidedSystem)[];User systems, after the built-ins; { run, on } picks where (default: authority when multiplayer).
update?
ts
optional update?: (ctx) => void;One more system, after systems.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
world?
ts
optional world?: WorldSpec;World settings.
GameStateProps
Mode-owned match mirrors; consumers should only read these.
Example
ts
const state: MatchState = gameState()?.props.matchState ?? 'waitingToStart';Properties
elapsed
ts
readonly elapsed: number;matchState
ts
readonly matchState: MatchState;phase
ts
readonly phase: string;phaseTimeRemaining
ts
readonly phaseTimeRemaining: number;remaining
ts
readonly remaining: number;round
ts
readonly round: number;rulesState
ts
readonly rulesState: "ended" | "waiting" | "inProgress";Normalized lifecycle for legacy and phased modes: waiting, inProgress or ended.
teamScores
ts
readonly teamScores: readonly number[];winners
ts
readonly winners: readonly number[];GateProps
Rising gate tuning.
Example
ts
const props: Partial<GateProps> = { lip: 0.2 };Extends
Properties
action
ts
action: string;Inherited from
asset?
ts
optional asset?: string;Inherited from
autoCloseSeconds
ts
autoCloseSeconds: number;Inherited from
DoorCoreProps.autoCloseSeconds
closePrompt
ts
closePrompt: string;Inherited from
closeSound
ts
closeSound: string;Inherited from
colour
ts
colour: [number, number, number];Inherited from
consumeKey
ts
consumeKey: boolean;Inherited from
enabled
ts
enabled: boolean;Inherited from
facingDegrees
ts
facingDegrees: number;Inherited from
height
ts
height: number;Closed doorway height in metres.
Inherited from
lip
ts
lip: number;lockedBy
ts
lockedBy: string;Inherited from
lockedMessage
ts
lockedMessage: string;Inherited from
lockedPrompt
ts
lockedPrompt: string;Inherited from
lockedSound
ts
lockedSound: string;Inherited from
look
ts
look: "none" | "wood" | "metal";Inherited from
once
ts
once: boolean;Inherited from
openPrompt
ts
openPrompt: string;Inherited from
openSound
ts
openSound: string;Inherited from
opensWhen
ts
opensWhen: string[];Inherited from
prompt
ts
prompt: string;Inherited from
range
ts
range: number;Inherited from
seconds
ts
seconds: number;Inherited from
startOpen
ts
startOpen: boolean;Inherited from
stayOpen
ts
stayOpen: boolean;Inherited from
thickness
ts
thickness: number;Leaf thickness in metres.
Inherited from
toggledBy
ts
toggledBy: "signal" | "proximity" | "interact";Inherited from
width
ts
width: number;Closed doorway width in metres.
Inherited from
GridMovementOptions
Tile stepping settings and synchronous callbacks; callback tiles are borrowed.
Example
ts
const options: GridMovementOptions = { tileSize: 1, stepSeconds: 0.22 };Properties
blockMask?
ts
optional blockMask?: CollisionLayers;collision?
ts
optional collision?:
| "Spectator"
| CollisionSetup
| "NoCollision"
| "BlockAll"
| "OverlapAll"
| "BlockAllDynamic"
| "OverlapAllDynamic"
| "IgnoreOnlyPawn"
| "OverlapOnlyPawn"
| "Pawn"
| "CharacterMesh"
| "PhysicsActor"
| "Destructible"
| "InvisibleWall"
| "InvisibleWallDynamic"
| "Trigger"
| "Ragdoll"
| "Vehicle"
| "UI";dims?
ts
optional dims?:
| readonly [number, number, number]
| readonly [number, number];Capsule radius/straight half height, or box half extents.
directions?
ts
optional directions?: 8 | 4;interpolation?
ts
optional interpolation?: "linear" | "smoothstep";origin?
ts
optional origin?: GridTile;runMultiplier?
ts
optional runMultiplier?: number;stepSeconds?
ts
optional stepSeconds?: number;tileSize?
ts
optional tileSize?: number;turnInPlaceSeconds?
ts
optional turnInPlaceSeconds?: number;Methods
onBump()?
ts
optional onBump(
self,
tile,
hitEntity,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle |
tile | Readonly<GridTile> |
hitEntity | number | undefined |
ctx | GameContext |
Returns
void
onStepEnd()?
ts
optional onStepEnd(
self,
tile,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle |
tile | Readonly<GridTile> |
ctx | GameContext |
Returns
void
onStepStart()?
ts
optional onStepStart(
self,
tile,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle |
tile | Readonly<GridTile> |
ctx | GameContext |
Returns
void
GridState
Borrowed grid state; read without retaining or mutating.
Example
ts
const moving: GridState['moving'] = false;Properties
bumped
ts
bumped: boolean;facing
ts
facing: GridDirection;moving
ts
moving: boolean;progress
ts
progress: number;tile
ts
tile: GridTile;GridTile
Integer tile coordinates.
Example
ts
const tile: GridTile = { x: 2, z: 3 };Properties
x
ts
x: number;z
ts
z: number;Guest
A guest instance: the five WIT exports plus a liveness flag.
Extends
Properties
dead
ts
readonly dead: boolean;True once the runtime has given up on user code.
rehydrateReload?
ts
optional rehydrateReload?: (state, apply) => () => void;Dev-only: rehydrate a freshly booted host through normal lifecycle commands.
Parameters
| Parameter | Type |
|---|---|
state | Uint8Array |
apply | (output) => void |
Returns
() => void
Example
ts
guest.rehydrateReload?.(saved, output => applyOutput(adapter, output));state
ts
readonly state: RuntimeState;The runtime, for tests and tooling.
Methods
init()
ts
init(config): void;Parameters
| Parameter | Type |
|---|---|
config | GameConfig |
Returns
void
Inherited from
restore()
ts
restore(state): void;Parameters
| Parameter | Type |
|---|---|
state | ArrayLike<number> |
Returns
void
Inherited from
restoreAcrossBuild()
ts
restoreAcrossBuild(state): void;Restore an older build, migrating actor props by name and typeof. Throws snapshot-version-mismatch when a kept prop changes type. This overwrites the realm's shared stores, just like ordinary restore.
Parameters
| Parameter | Type | Description |
|---|---|---|
state | ArrayLike<number> | A snapshot from an older build of this game. |
Returns
void
Example
ts
nextGuest.restoreAcrossBuild(oldGuest.snapshot());shutdown()
ts
shutdown(): void;Returns
void
Inherited from
snapshot()
ts
snapshot(): Uint8Array;Returns
Uint8Array
Inherited from
tick()
ts
tick(input): FrameOutput;Parameters
| Parameter | Type |
|---|---|
input | FrameInput |
Returns
Inherited from
GuestExports
The five functions the WIT game interface exports.
Extended by
Methods
init()
ts
init(config): void;Parameters
| Parameter | Type |
|---|---|
config | GameConfig |
Returns
void
restore()
ts
restore(state): void;Parameters
| Parameter | Type |
|---|---|
state | ArrayLike<number> |
Returns
void
shutdown()
ts
shutdown(): void;Returns
void
snapshot()
ts
snapshot(): Uint8Array;Returns
Uint8Array
tick()
ts
tick(input): FrameOutput;Parameters
| Parameter | Type |
|---|---|
input | FrameInput |
Returns
HealthStore
Current and maximum hit points.
Properties
current
ts
current: Float32Array;max
ts
max: Float32Array;HingedDoorProps
Hinged leaf tuning, measured in its closed local frame.
Example
ts
const props: Partial<HingedDoorProps> = { hinge: 'right' };Extends
Extended by
Properties
action
ts
action: string;Inherited from
asset?
ts
optional asset?: string;Inherited from
autoCloseSeconds
ts
autoCloseSeconds: number;Inherited from
DoorCoreProps.autoCloseSeconds
closePrompt
ts
closePrompt: string;Inherited from
closeSound
ts
closeSound: string;Inherited from
colour
ts
colour: [number, number, number];Inherited from
consumeKey
ts
consumeKey: boolean;Inherited from
enabled
ts
enabled: boolean;Inherited from
facingDegrees
ts
facingDegrees: number;Inherited from
height
ts
height: number;Closed doorway height in metres.
Inherited from
hinge
ts
hinge: "left" | "right";lockedBy
ts
lockedBy: string;Inherited from
lockedMessage
ts
lockedMessage: string;Inherited from
lockedPrompt
ts
lockedPrompt: string;Inherited from
lockedSound
ts
lockedSound: string;Inherited from
look
ts
look: "none" | "wood" | "metal";Inherited from
once
ts
once: boolean;Inherited from
openPrompt
ts
openPrompt: string;Inherited from
openSound
ts
openSound: string;Inherited from
opensWhen
ts
opensWhen: string[];Inherited from
prompt
ts
prompt: string;Inherited from
range
ts
range: number;Inherited from
seconds
ts
seconds: number;Inherited from
startOpen
ts
startOpen: boolean;Inherited from
stayOpen
ts
stayOpen: boolean;Inherited from
swingAway
ts
swingAway: boolean;swingDegrees
ts
swingDegrees: number;thickness
ts
thickness: number;Leaf thickness in metres.
Inherited from
toggledBy
ts
toggledBy: "signal" | "proximity" | "interact";Inherited from
width
ts
width: number;Closed doorway width in metres.
Inherited from
HitCharacterCmd
A blow on a character: the nearest part of its physics body to at takes an impulse along direction, and the body reacts on the physics. The anim-events hit, fell and recovered on the clip ragdoll say what happened.
Properties
at
ts
at: Vec3;Where the blow lands, world space.
direction
ts
direction: Vec3;Which way the blow travels, world space; zero means from the character's front.
entity
ts
entity: number;strength
ts
strength: HitStrength;HostApi
The host services a guest may call, in guest-side JS shapes.
This is the SDK's own narrow view of the three gameable:engine import interfaces. packages/sdk/src/wit/entry.ts adapts the real WIT imports to it; gameable/test implements it directly for node tests.
Extended by
Methods
describe()
ts
describe(id): AssetDesc | null | undefined;Metadata for a handle, or nullish when the handle is unknown.
Parameters
| Parameter | Type |
|---|---|
id | number |
Returns
AssetDesc | null | undefined
jointValue()
ts
jointValue(joint, axis): number | null | undefined;Joint coordinate, in radians or metres.
Parameters
| Parameter | Type |
|---|---|
joint | number |
axis | number |
Returns
number | null | undefined
log()
ts
log(level, msg): void;Route a message to the host logger.
Parameters
| Parameter | Type |
|---|---|
level | LogLevel |
msg | string |
Returns
void
nowMs()
ts
nowMs(): number;Monotonic milliseconds since engine start. Never feed this to simulation.
Returns
number
overlapShape()
ts
overlapShape(
shape,
position,
rotation,
filter,
maxResults
): readonly OverlapHit[];Bodies overlapping a primitive shape.
Parameters
| Parameter | Type |
|---|---|
shape | QueryShape |
position | Vec3 |
rotation | Quat |
filter | QueryFilter |
maxResults | number |
Returns
readonly OverlapHit[]
overlapSphere()
ts
overlapSphere(
center,
radius,
filter,
maxResults
): readonly OverlapHit[];Bodies overlapping a sphere, nearest first.
Parameters
| Parameter | Type |
|---|---|
center | Vec3 |
radius | number |
filter | QueryFilter |
maxResults | number |
Returns
readonly OverlapHit[]
raycast()
ts
raycast(
origin,
direction,
maxDistance,
filter
): RayHit | null | undefined;Closest hit along a ray, or nullish on a miss.
Parameters
| Parameter | Type |
|---|---|
origin | Vec3 |
direction | Vec3 |
maxDistance | number |
filter | QueryFilter |
Returns
RayHit | null | undefined
raycastBatch()
ts
raycastBatch(rays): readonly (RayHit | null | undefined)[];One round trip for many rays; result index i matches rays[i].
Parameters
| Parameter | Type |
|---|---|
rays | readonly RayQuery[] |
Returns
readonly (RayHit | null | undefined)[]
resolveId()
ts
resolveId(name): number | null | undefined;Manifest string id to handle, or nullish when the manifest has no entry.
Parameters
| Parameter | Type |
|---|---|
name | string |
Returns
number | null | undefined
seed()
ts
seed(): number;The deterministic run seed, as a number (already Number()-coerced).
Returns
number
shapeCast()
ts
shapeCast(
shape,
position,
rotation,
direction,
maxDistance,
filter
): RayHit | null | undefined;Sweep a primitive shape, in metres.
Parameters
| Parameter | Type |
|---|---|
shape | QueryShape |
position | Vec3 |
rotation | Quat |
direction | Vec3 |
maxDistance | number |
filter | QueryFilter |
Returns
RayHit | null | undefined
HostFrameInput
frame-input in host-side shapes.
jco lifts u64 to bigint on the host and to number in the guest, and the host is free to hand over real typed arrays. Everything else is identical, which is why the guest types accept ArrayLike<number>.
Properties
bodies
ts
bodies: Float32Array;contacts
ts
contacts: readonly Contact[];dt
ts
dt: number;elapsed
ts
elapsed: number;events
ts
events: readonly GameEvent[];frame
ts
frame: bigint;input
ts
input: InputState;players
ts
players: readonly PlayerInput[];vehicles?
ts
optional vehicles?: Float32Array<ArrayBufferLike>;Versioned packed vehicle telemetry.
HostGameConfig
game-config in host-side shapes: seed is a bigint.
Properties
devMode
ts
devMode: boolean;fixedHz
ts
fixedHz: number;options?
ts
optional options?: string;seed
ts
seed: bigint;viewportHeight
ts
viewportHeight: number;viewportWidth
ts
viewportWidth: number;InputMods
Keyboard modifier state. Every key is present on input.
Properties
alt
ts
alt: boolean;capsLock
ts
capsLock: boolean;ctrl
ts
ctrl: boolean;meta
ts
meta: boolean;numLock
ts
numLock: boolean;shift
ts
shift: boolean;InputState
Everything the host knows about input for one fixed step.
Extended by
Properties
control?
ts
optional control?: object;Page-decided absolute direction, final movement axes and last observed spawn. Missing keeps local key/stick and pointer integration.
moveX
ts
moveX: number;moveY
ts
moveY: number;pitch
ts
pitch: number;spawn
ts
spawn: number;yaw
ts
yaw: number;focused
ts
focused: boolean;gamepads
ts
gamepads: readonly GamepadState[];keys
ts
keys: KeyState;mods
ts
mods: InputMods;mouse
ts
mouse: MouseState;InteractableProps
Interaction tuning. Action is a keyboard/touch action name supported by the input facade; default E.
Example
ts
const props: InteractableProps = {prompt: 'Open', range: 2, facingDegrees: 75, action: 'E', once: false, enabled: true, asset: ''};Extended by
Properties
action
ts
action: string;asset?
ts
optional asset?: string;enabled
ts
enabled: boolean;facingDegrees
ts
facingDegrees: number;once
ts
once: boolean;prompt
ts
prompt: string;range
ts
range: number;Inventory
A fixed-slot bag for each owner. Owners are indices 0..owners-1, not entity ids. Counts and amounts are nonnegative safe integers. Moves preserve totals and emit no events. Transfers notify in ascending owner order; clear notifies in ascending item order. Other changes notify once, synchronously, after the whole mutation. Reset and restore do not notify. A transfer to oneself succeeds if the items exist.
Example
ts
import { createInventory, type Inventory } from 'gameable';
const bag: Inventory = createInventory({ owners: 1, slots: 4, items: [{ id: 'key' }] });
bag.add(0, 'key');Extends
Methods
add()
ts
add(
owner,
item,
amount?
): number;Fill existing stacks, then empty slots, lowest first; return overflow.
Parameters
| Parameter | Type |
|---|---|
owner | number |
item | string | number |
amount? | number |
Returns
number
clear()
ts
clear(owner): void;Empty an owner's bag.
Parameters
| Parameter | Type |
|---|---|
owner | number |
Returns
void
count()
ts
count(owner, item): number;Total amount of an item.
Parameters
| Parameter | Type |
|---|---|
owner | number |
item | string | number |
Returns
number
has()
ts
has(
owner,
item,
amount?
): boolean;Whether at least amount (default 1) is held.
Parameters
| Parameter | Type |
|---|---|
owner | number |
item | string | number |
amount? | number |
Returns
boolean
item()
ts
item(id): number;Resolve an item id; unknown ids throw with the known ids.
Parameters
| Parameter | Type |
|---|---|
id | string |
Returns
number
itemId()
ts
itemId(index): string;Get an item's id. Invalid indices throw.
Parameters
| Parameter | Type |
|---|---|
index | number |
Returns
string
move()
ts
move(
owner,
fromSlot,
toSlot
): void;Merge matching stacks; otherwise swap slots. Moving onto itself does nothing.
Parameters
| Parameter | Type |
|---|---|
owner | number |
fromSlot | number |
toSlot | number |
Returns
void
remove()
ts
remove(
owner,
item,
amount?
): boolean;Remove from highest slots first, atomically; zero always succeeds.
Parameters
| Parameter | Type |
|---|---|
owner | number |
item | string | number |
amount? | number |
Returns
boolean
reset()
ts
reset(): void;Back to the state right after creation. Call from init.
Returns
void
Inherited from
restore()
ts
restore(state, options?): void;Read back what snapshot returned. Throws on a malformed state.
Parameters
| Parameter | Type |
|---|---|
state | unknown |
options? | { crossBuild?: boolean; } |
options.crossBuild? | boolean |
Returns
void
Inherited from
slotCount()
ts
slotCount(owner, slot): number;Count at a slot, or zero when empty.
Parameters
| Parameter | Type |
|---|---|
owner | number |
slot | number |
Returns
number
slotItem()
ts
slotItem(owner, slot): number;Item index at a slot, or -1 when empty.
Parameters
| Parameter | Type |
|---|---|
owner | number |
slot | number |
Returns
number
snapshot()
ts
snapshot(): unknown;Plain JSON-safe data for defineGame({ snapshot }).
Returns
unknown
Inherited from
transfer()
ts
transfer(
fromOwner,
toOwner,
item,
amount
): boolean;Transfer atomically, only if the source holds and destination fits everything.
Parameters
| Parameter | Type |
|---|---|
fromOwner | number |
toOwner | number |
item | string | number |
amount | number |
Returns
boolean
InventoryComponentOptions
Bag schema and synchronous notifications. Amounts count bag items, excluding equipment. Identical schemas share storage. Callbacks observe committed state.
Example
ts
const options: InventoryComponentOptions = { slots: 4, items: [{ id: 'key' }] };Properties
equipSlots?
ts
optional equipSlots?: readonly string[];Unique equipment slot names; defaults to none.
items
ts
items: readonly object[];Unique ids, per-slot stack limits (default one), and optional allowed equipment slot.
onInventoryFull?
ts
optional onInventoryFull?: (actor, item, overflow) => void;Once when an insertion cannot fit, with its overflow; failed atomic operations keep all items.
Parameters
| Parameter | Type |
|---|---|
actor | ActorHandle |
item | string |
overflow | number |
Returns
void
onItemAdded?
ts
optional onItemAdded?: (actor, item, amount) => void;Once per successful insertion, with the amount inserted.
Parameters
| Parameter | Type |
|---|---|
actor | ActorHandle |
item | string |
amount | number |
Returns
void
onItemEquipped?
ts
optional onItemEquipped?: (actor, slot, item) => void;Once after equipping, with the equipment slot and item id.
Parameters
| Parameter | Type |
|---|---|
actor | ActorHandle |
slot | string |
item | string |
Returns
void
onItemRemoved?
ts
optional onItemRemoved?: (actor, item, amount) => void;Once per successful removal, with the amount removed.
Parameters
| Parameter | Type |
|---|---|
actor | ActorHandle |
item | string |
amount | number |
Returns
void
onItemUnequipped?
ts
optional onItemUnequipped?: (actor, slot, item) => void;Once after unequipping or replacing equipment.
Parameters
| Parameter | Type |
|---|---|
actor | ActorHandle |
slot | string |
item | string |
Returns
void
slots
ts
slots: number;Positive number of bag slots per actor.
JointAxis
JointAxis: radians and metres at the host boundary.
Example
ts
import type { JointAxis } from 'gameable';
const value: JointAxis = { mode: 'locked', min: 0, max: 0 };Properties
max
ts
max: number;min
ts
min: number;mode
ts
mode: JointAxisMode;JointSpring
JointSpring: radians and metres at the host boundary.
Example
ts
import type { JointSpring } from 'gameable';
const value: JointSpring = { frequency: 2, damping: 1 };Properties
damping
ts
damping: number;frequency
ts
frequency: number;JumpPadProps
Jump launch velocity and optional mesh appearance.
Example
ts
const props: Partial<JumpPadProps> = { launch: [0,12,4] };Properties
asset
ts
asset: string;Manifest mesh id; empty means no mesh.
launch
ts
launch: [number, number, number];Launch velocity in metres/second.
scale
ts
scale: [number, number, number];Mesh scale only; collider remains in world metres.
tint
ts
tint: [number, number, number];Mesh RGB material colour.
KeyState
256 key codes packed into 8 u32 words, one list per edge.
Properties
down
ts
down: ArrayLike<number>;pressed
ts
pressed: ArrayLike<number>;released
ts
released: ArrayLike<number>;LevelActor
One placeable actor. Attached transforms are local to the named parent. Quaternion rotation takes precedence over yaw.
Example
ts
const entry: LevelActor = { class: 'PlayerStart', position: [0, 0, 0] };Properties
attachTo?
ts
optional attachTo?: string;class
ts
class: string;name?
ts
optional name?: string;Unique within the level. Left out, the actor is still named: Door1, Door2, ... (levelActorNames).
position
ts
position: readonly [number, number, number];props?
ts
optional props?: Record<string, unknown>;rotation?
ts
optional rotation?: readonly [number, number, number, number];scale?
ts
optional scale?: readonly [number, number, number];Root scale [x, y, z]; attached parts inherit it, a body's dims do not.
tags?
ts
optional tags?: readonly string[];yaw?
ts
optional yaw?: number;Degrees about +Y; zero faces +Z.
LevelDoorProps
A door's destination and which players travel through it.
Example
ts
const props: Partial<LevelDoorProps> = { toLevel: 'cave', toPlayerStart: 'stairs' };Extends
Properties
action
ts
action: string;Inherited from
asset?
ts
optional asset?: string;Inherited from
autoCloseSeconds
ts
autoCloseSeconds: number;Inherited from
HingedDoorProps.autoCloseSeconds
closePrompt
ts
closePrompt: string;Inherited from
closeSound
ts
closeSound: string;Inherited from
colour
ts
colour: [number, number, number];Inherited from
consumeKey
ts
consumeKey: boolean;Inherited from
enabled
ts
enabled: boolean;Inherited from
facingDegrees
ts
facingDegrees: number;Inherited from
height
ts
height: number;Closed doorway height in metres.
Inherited from
hinge
ts
hinge: "left" | "right";Inherited from
lockedBy
ts
lockedBy: string;Inherited from
lockedMessage
ts
lockedMessage: string;Inherited from
lockedPrompt
ts
lockedPrompt: string;Inherited from
lockedSound
ts
lockedSound: string;Inherited from
look
ts
look: "none" | "wood" | "metal";Inherited from
once
ts
once: boolean;Inherited from
openPrompt
ts
openPrompt: string;Inherited from
opens
ts
opens: "slide" | "swing";openSound
ts
openSound: string;Inherited from
opensWhen
ts
opensWhen: string[];Inherited from
prompt
ts
prompt: string;Inherited from
range
ts
range: number;Inherited from
requireOpen
ts
requireOpen: boolean;seconds
ts
seconds: number;Inherited from
startOpen
ts
startOpen: boolean;Inherited from
stayOpen
ts
stayOpen: boolean;Inherited from
swingAway
ts
swingAway: boolean;Inherited from
swingDegrees
ts
swingDegrees: number;Inherited from
thickness
ts
thickness: number;Leaf thickness in metres.
Inherited from
toggledBy
ts
toggledBy: "signal" | "proximity" | "interact";Inherited from
toLevel
ts
toLevel: string;toPlayerStart
ts
toPlayerStart: string;travel
ts
travel: "party" | "player";travelPrompt
ts
travelPrompt: string;width
ts
width: number;Closed doorway width in metres.
Inherited from
LevelFile
Versioned JSON actor placement document. Import premade/user classes before validation.
Example
ts
const level: LevelFile = { format: 1, actors: [] };Properties
$schema?
ts
optional $schema?: string;The schema's address, for an editor.
actors
ts
actors: readonly LevelActor[];format
ts
format: 1;place?
ts
optional place?: string;Where this level plays: the manifest id of its world (env.*). Left out, the page's default place. Switching to a level with another place swaps the world.
LevelsFacade
ctx.levels: which levels the game has and which is loaded.
Example
ts
import { levels, type LevelsFacade } from 'gameable';
const facade: LevelsFacade = levels;
console.log(facade.names(), facade.current);Properties
current
ts
readonly current: string | null;The loaded level's name, or null when none is.
Methods
load()
ts
load(
ctx,
name,
options?
): object;Unload the loaded level, then place name's actors.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | The game context. |
name | string | A declared level. |
options? | { arrival?: string | true; } | Require the first PlayerStart or a named arrival marker before teardown. |
options.arrival? | string | true | - |
Returns
object
The placed actors, as loadLevel returns them.
actors
ts
actors: ActorHandle<object>[];named
ts
named: Record<string, ActorHandle>;Throws
When the destination or requested arrival is invalid.
names()
ts
names(): readonly string[];Every declared level, in declaration order.
Returns
readonly string[]
place()
ts
place(name?): string | null;The world a level plays in.
Parameters
| Parameter | Type | Description |
|---|---|---|
name? | string | A level; the loaded one when left out. |
Returns
string | null
Its place, or null when it has none.
unload()
ts
unload(ctx): void;Destroy the loaded level's actors with reason levelUnload. Actors from code are removed unless marked session.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | The game context. |
Returns
void
LeverProps
Authored lever tuning; a positive resetSeconds makes a momentary button.
Example
ts
const props: Partial<LeverProps> = { resetSeconds: 2, lockedBy: 'key' };Extends
Properties
action
ts
action: string;Inherited from
asset?
ts
optional asset?: string;Inherited from
colour
ts
colour: [number, number, number];consumeKey
ts
consumeKey: boolean;enabled
ts
enabled: boolean;Inherited from
facingDegrees
ts
facingDegrees: number;Inherited from
InteractableProps.facingDegrees
lockedBy
ts
lockedBy: string;lockedMessage
ts
lockedMessage: string;lockedPrompt
ts
lockedPrompt: string;offPrompt
ts
offPrompt: string;once
ts
once: boolean;Inherited from
onPrompt
ts
onPrompt: string;prompt
ts
prompt: string;Inherited from
range
ts
range: number;Inherited from
resetSeconds
ts
resetSeconds: number;seconds
ts
seconds: number;startOn
ts
startOn: boolean;switchSound
ts
switchSound: string;LoadAssetCmd
Ask the host to start loading an asset.
Properties
asset
ts
asset: number;priority
ts
priority: number;LoadLevelOptions
What loadLevel accepts besides the document.
Properties
name?
ts
optional name?: string;The level's name, written into every actor's source. Defaults to 'main'.
LookAtCmd
Aim a character's head and eyes at a world point.
Properties
entity
ts
entity: number;target?
ts
optional target?: Vec3;weight
ts
weight: number;LoweredCollision
Lowered body fields plus information the current body command cannot carry.
Example
ts
const body: LoweredCollision = lowerCollision('Pawn');Properties
flags
ts
flags: BodyFlags;layer
ts
layer: CollisionLayers;mask
ts
mask: CollisionLayers;overlapMask
ts
overlapMask: CollisionLayers;physicsOnly
ts
physicsOnly: boolean;queryOnly
ts
queryOnly: boolean;MatchHudModuleOptions
HUD namespace and elapsed-time quantization.
Example
ts
import type { MatchHudModuleOptions } from 'gameable';
const options: MatchHudModuleOptions = { namespace: 'race', secondsStep: 0.1 };
console.log(options.namespace);Properties
namespace
ts
namespace: string;secondsStep
ts
secondsStep: number;MatchModule
The match module and its shared seat state.
Example
ts
import type { MatchModule } from 'gameable';
const inspect = (match: MatchModule) => match.state.phase;
console.log(inspect);Extends
Properties
init
ts
init: (ctx) => void;Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
Inherited from
state
ts
readonly state: object;checkpoint
ts
checkpoint: Uint8Array;entity
ts
entity: Uint32Array;first
ts
first: number;hitAfter
ts
hitAfter: Float64Array;knockUntil
ts
knockUntil: Float64Array;knockX
ts
knockX: Float32Array;knockZ
ts
knockZ: Float32Array;loaded
ts
loaded: Uint8Array;next
ts
next: number;phase
ts
phase: string;place
ts
place: Uint8Array;ready
ts
ready: Uint8Array;revision
ts
revision: number;round
ts
round: number;since
ts
since: number;spectator
ts
spectator: Uint8Array;system
ts
system: (ctx) => void;Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
Inherited from
MatchModuleOptions
All-ready match deadlines and seat policy.
Example
ts
import type { MatchModuleOptions } from 'gameable';
const options: MatchModuleOptions = { maxPlayers: 1, history: 8, spawns: [[0,3,0]], start: 'all-ready', minPlayers: 2, soloMinPlayers: 1, lateJoin: 'spectate-after-loading', spectatorSpawnZ: 3, loadingSeconds: 20, cardSeconds: 1.5, countdownSeconds: 4.5, limitSeconds: 180, afterFirstSeconds: 90, resultsSeconds: 8 };
console.log(options.maxPlayers);Properties
afterFirstSeconds
ts
afterFirstSeconds: number;cardSeconds
ts
cardSeconds: number;countdownSeconds
ts
countdownSeconds: number;history
ts
history: number;lateJoin
ts
lateJoin: "spectate-after-loading";limitSeconds
ts
limitSeconds: number;loadingSeconds
ts
loadingSeconds: number;maxPlayers
ts
maxPlayers: number;minPlayers
ts
minPlayers: number;resultsSeconds
ts
resultsSeconds: number;soloMinPlayers
ts
soloMinPlayers: number;spawns
ts
spawns: readonly readonly number[][];spectatorSpawnZ
ts
spectatorSpawnZ: number;start
ts
start: "all-ready";MatchPlayerSummary
One logged-in player's public statistics.
Example
ts
const row: MatchPlayerSummary = { seat: 0, name: '', score: 0, kills: 0, deaths: 0, team: 0 };Properties
deaths
ts
deaths: number;kills
ts
kills: number;name
ts
name: string;score
ts
score: number;seat
ts
seat: number;team
ts
team: number;MatchSummary
Borrowed match model, refreshed after actor hooks each authority or solo step.
Example
ts
ctx.hud.set({ match: matchSummary() });Properties
elapsed
ts
elapsed: number;players
ts
players: readonly Readonly<MatchPlayerSummary>[];remaining
ts
remaining: number;state
ts
state: MatchState;winners
ts
winners: readonly number[];MessageOptions
Options for defineMessage.
Example
ts
const Chat = defineMessage('chat', (p): p is string => typeof p === 'string', { maxBytes: 256 });Properties
maxBytes?
ts
optional maxBytes?: number;The largest payload, in UTF-8 bytes of its JSON; 1 to 2,048. Default 2,048, the wire cap.
ModuleCatalog
Gameplay factory metadata in registration order.
Example
ts
const catalog: ModuleCatalog = moduleCatalog();Properties
modules
ts
modules: ModuleCatalogEntry[];ModuleCatalogEntry
A detached gameplay factory entry with its public import source.
Example
ts
const entry: ModuleCatalogEntry = moduleCatalog().modules[0];Extends
Properties
aliases
ts
aliases: readonly string[];Overrides
category
ts
category: string;Inherited from
description
ts
description: string;Inherited from
events
ts
events: readonly object[];Overrides
example
ts
example: string;Overrides
import
ts
import: "gameable";kind
ts
kind: "module";name
ts
name: string;Inherited from
options
ts
options: Record<string, ModuleOptionMeta>;Overrides
ModuleDescription
Authoring metadata registered beside a gameplay factory.
Example
ts
const entry: ModuleDescription = { name: 'custom', category: 'gameplay', description: 'Custom helper.' };Extended by
Properties
aliases?
ts
optional aliases?: readonly string[];category
ts
category: string;description
ts
description: string;events?
ts
optional events?: readonly object[];example?
ts
optional example?: string;name
ts
name: string;options?
ts
optional options?: Record<string, ModuleOptionMeta>;ModuleOptionMeta
Factory option hints, including callback signatures and actual defaults. Omitted defaults mean required options or optional callbacks without a default.
Example
ts
const option: ModuleOptionMeta = { type: 'number', description: 'Slots.', min: 0 };Extends
Omit<PropMeta,"type"|"items"|"fields">
Properties
const?
ts
optional const?: boolean;Restrict a boolean branch to one literal value.
Inherited from
default?
ts
optional default?: string | number | boolean;description
ts
description: string;Inherited from
fields?
ts
optional fields?: Record<string, ModuleOptionMeta>;group?
ts
optional group?: string;Shared reference table; actor-specific differences remain documented on the actor.
Inherited from
items?
ts
optional items?: ModuleOptionMeta;max?
ts
optional max?: number;Inherited from
min?
ts
optional min?: number;Inherited from
nullable?
ts
optional nullable?: boolean;Accept null in addition to the described shape.
Inherited from
oneOf?
ts
optional oneOf?: readonly PropMeta[];Inherited from
optional?
ts
optional optional?: boolean;Allow this field to be omitted from a fixed-shape object.
Inherited from
type?
ts
optional type?:
| "string"
| "number"
| "boolean"
| "object"
| "function"
| "vec3"
| "color"
| "enum"
| "array";unit?
ts
optional unit?: string;Inherited from
values?
ts
optional values?: readonly string[];Inherited from
MotionEvent
What the movement system says of a character.
Properties
amount
ts
amount: number;For arrived: how far from the spot asked it stands, metres (for 'face': how far from the facing asked, radians). For limited: the speed it is given, metres a second.
entity
ts
entity: number;facing
ts
facing: number;The way the character faces there, radians about +Y (0 faces +Z): where a walk left it.
kind
ts
kind:
| "landed"
| "limited"
| "done"
| "arrived"
| "failed"
| "release"
| "started"
| "contact"
| "ready";ready (its motion set has the body), arrived (a walk to a spot got there), an action's moments (started, contact, release, landed, done), or failed.
limb
ts
limb: number;The limb (0 left hand, 1 right hand, 2 left foot, 3 right foot), or -1.
name
ts
name: string;The action's name; the set's name for ready; 'walk' for a walk to a spot, 'face' for a turn on the spot; the gait ('walk', 'run') for limited.
object
ts
object: number;The object's id as the game gave it, or -1.
point
ts
point: Vec3;Where, world space: the contact, the hand at a release, where the walk arrived.
reason
ts
reason: string;Why, for failed; empty otherwise.
velocity
ts
velocity: Vec3;How fast that point moves, world metres a second: a release gives the object this.
MouseState
Pointer position, deltas, wheel and button edges for one frame.
Properties
buttons
ts
buttons: number;dx
ts
dx: number;dy
ts
dy: number;locked
ts
locked: boolean;pressed
ts
pressed: number;released
ts
released: number;wheel
ts
wheel: number;x
ts
x: number;y
ts
y: number;MoveCharacterCmd
Drive a character body for one step.
Properties
body
ts
body: number;crouch
ts
crouch: boolean;desiredVelocity
ts
desiredVelocity: Vec3;jump
ts
jump: boolean;maxSlopeDeg
ts
maxSlopeDeg: number;MoveQuery
Blocking-world adapter. Returned records may be reused by the next query. Probes/rays enable the exact shrunken-capsule floor algorithm; basic adapters use full sweeps.
Example
ts
const empty: MoveQuery = { sweep: () => null, overlap: () => [] };Methods
overlap()
ts
overlap(at, inflation?): readonly Penetration[];Parameters
| Parameter | Type |
|---|---|
at | Vec3 |
inflation? | number |
Returns
readonly Penetration[]
raycast()?
ts
optional raycast(from, delta): SweepHit | null;Parameters
| Parameter | Type |
|---|---|
from | Vec3 |
delta | Vec3 |
Returns
SweepHit | null
sweep()
ts
sweep(from, delta): SweepHit | null;Parameters
| Parameter | Type |
|---|---|
from | Vec3 |
delta | Vec3 |
Returns
SweepHit | null
sweepCapsule()?
ts
optional sweepCapsule(
from,
delta,
capsule
): SweepHit | null;Parameters
| Parameter | Type |
|---|---|
from | Vec3 |
delta | Vec3 |
capsule | Capsule |
Returns
SweepHit | null
sweepFloorBox()?
ts
optional sweepFloorBox(
from,
delta,
radius,
halfHeight,
rotated
): SweepHit | null;Parameters
| Parameter | Type |
|---|---|
from | Vec3 |
delta | Vec3 |
radius | number |
halfHeight | number |
rotated | boolean |
Returns
SweepHit | null
MoverModule
Kinematic authority system and declarative course spawns.
Example
ts
import type { MoverModule } from 'gameable';
const inspect = (movers: MoverModule) => movers.spawns.length;
console.log(inspect);Extends
Properties
init
ts
init: (ctx) => void;Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
Inherited from
spawns
ts
readonly spawns: readonly SpawnSpec[];system
ts
system: (ctx) => void;Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
Inherited from
MoverModuleOptions
Explicit course bodies, motion and contact policies.
Example
ts
import type { MoverModuleOptions } from 'gameable';
const inspect = (options: MoverModuleOptions) => options.movers.length;
console.log(inspect);Properties
contact
ts
contact: object;carryTolerance
ts
carryTolerance: number;foot
ts
foot: number;floors
ts
floors: readonly readonly number[][];knock
ts
knock: object;cooldown
ts
cooldown: number;duration
ts
duration: number;margin
ts
margin: number;speed
ts
speed: number;movers
ts
movers: readonly object[];palette
ts
palette: readonly readonly number[][];MovingPlatformProps
Moving platform data; points are relative to spawn. Wait occurs at path endpoints.
Example
ts
const props: Partial<MovingPlatformProps> = {points: [[4, 0, 0]], seconds: 3, mode: 'pingPong'};Extends
Properties
asset
ts
asset: string;mode
ts
mode: "loop" | "once" | "pingPong";Inherited from
points
ts
points: readonly (readonly [number, number, number] | Vec3)[];Inherited from
WaypointMovementOptions.points
seconds?
ts
optional seconds?: number;Inherited from
WaypointMovementOptions.seconds
speed?
ts
optional speed?: number;Inherited from
startPaused?
ts
optional startPaused?: boolean;Inherited from
WaypointMovementOptions.startPaused
waitSeconds?
ts
optional waitSeconds?: number;Inherited from
WaypointMovementOptions.waitSeconds
MultiplayerOptions
Options for the multiplayer feature.
Properties
maxPlayers?
ts
optional maxPlayers?: number;Seats in a room, ids 0..maxPlayers - 1. Default 8. roomSeats reads it, for the guest's player slots and for the room's door alike.
predict?
ts
optional predict?: boolean;Predict each page's own character body: the page steps its own Jolt world (the level's static colliders and the body its client guest adds for its player) so the player moves on key-down, and the authority's rows correct it. Default false. See the multiplayer concept page.
sendHz?
ts
optional sendHz?: number;Transform rows per second sent to each player. Default 20.
MusicOptions
Music playback options.
Example
ts
`music.play('theme', { bpm: 120 });`Extended by
Properties
beatsPerBar?
ts
optional beatsPerBar?: number;Beats in each bar; defaults to four.
bpm?
ts
optional bpm?: number;Beats per minute; zero disables the clock.
fadeMs?
ts
optional fadeMs?: number;Crossfade duration.
firstBeat?
ts
optional firstBeat?: number;Seconds to beat zero.
loop?
ts
optional loop?: boolean;Loop playback.
start?
ts
optional start?: BeatQuantize;Starting grid; defaults to now.
volume?
ts
optional volume?: number;Linear gain.
MusicTrackEvent
music-track-event payload.
Example
ts
`const value: MusicTrackEvent = { index: 0, asset: 1 };`Properties
asset
ts
asset: number;Manifest asset handle.
index
ts
index: number;Playlist track index.
NavGrid
A grid over the level: built once, queried every frame, edited by obstacles.
Extends
Properties
agentRadius
ts
readonly agentRadius: number;Agent radius the walkable space was shrunk by.
Inherited from
cellSize
ts
readonly cellSize: number;cols
ts
readonly cols: number;revision
ts
readonly revision: number;Topology/area revision; edits invalidate cached paths and integration fields.
rows
ts
readonly rows: number;Methods
addCostArea()
ts
addCostArea(
x,
z,
halfX,
halfZ,
cost
): number;Add a rectangular cell-centre area. Entry costs multiply by cost (finite, >= 1). Overlapping areas take the maximum multiplier. Returns -1 at capacity/invalid input.
Parameters
| Parameter | Type |
|---|---|
x | number |
z | number |
halfX | number |
halfZ | number |
cost | number |
Returns
number
Example
ts
const mud = grid.addCostArea(3, 4, 2, 1, 3);addLink()
ts
addLink(
ax,
az,
bx,
bz,
options?
): number;Add an extra edge only when both endpoint cells are walkable. Exact XZ endpoints appear consecutively in findPath. Endpoint heights default to their cells; optional startY/endY override the sampled heights for authored jump/ladder points. radius limits endpoint-to-cell-centre distance (default cellSize); cost is an absolute traversal cost in metres (default endpoint distance, minimum 0). Flow fields integrate areas only; link traversal requires a flagged path follower.
Parameters
| Parameter | Type |
|---|---|
ax | number |
az | number |
bx | number |
bz | number |
options? | { bidirectional?: boolean; cost?: number; endY?: number; radius?: number; startY?: number; } |
options.bidirectional? | boolean |
options.cost? | number |
options.endY? | number |
options.radius? | number |
options.startY? | number |
Returns
number
Example
ts
const jump = grid.addLink(1, 2, 5, 2, { bidirectional: false });addObstacle()
ts
addObstacle(
x,
z,
halfX,
halfZ
): number;Block a rectangle (inflated by the agent radius) until removed.
Parameters
| Parameter | Type |
|---|---|
x | number |
z | number |
halfX | number |
halfZ | number |
Returns
number
An obstacle id, or -1 when maxObstacles are alive.
buildFlat()
ts
buildFlat(y?): void;Make every cell walkable floor at height y (default 0). For 2D, tests and box-built levels.
Parameters
| Parameter | Type |
|---|---|
y? | number |
Returns
void
buildFromPhysics()
ts
buildFromPhysics(mask?): number;Build from the level's static colliders: one downward ray per cell, one raycastBatch per row. Call from init, never per frame.
Parameters
| Parameter | Type | Description |
|---|---|---|
mask? | CollisionLayers | Layers that count as floor and walls. Default { staticGeometry: true }. |
Returns
number
How many cells an agent may stand on. 0 means no floor was found: the level's colliders are not loaded yet, or a headless test's mock host has no physics.
createFlowField()
ts
createFlowField(): FlowField;A flow field over this grid. Allocates: make it in init.
Returns
findPath()
ts
findPath(
fromX,
fromZ,
toX,
toZ,
out,
linkFlags?
): number;Cheapest walkable path. Uniform grids are string-pulled; weighted routes retain turning cell waypoints so smoothing cannot shortcut through expensive areas.
Parameters
| Parameter | Type | Description |
|---|---|---|
fromX | number | Start x; snapped to the nearest walkable cell when blocked. |
fromZ | number | Start z. |
toX | number | Goal x; snapped likewise. |
toZ | number | Goal z. |
out | Float32Array | Receives x, y, z per point, start first, goal last. |
linkFlags? | Uint8Array<ArrayBufferLike> | Optional caller-owned flags, cleared and filled per query: 1 at a link start, followed by its exact end point. Copy flags with the path before another query. A truncated path never ends with an unmatched link start. |
Returns
number
How many points were written; 0 when there is no path.
Inherited from
hasPath()
ts
hasPath(
fromX,
fromZ,
toX,
toZ
): boolean;Parameters
| Parameter | Type |
|---|---|
fromX | number |
fromZ | number |
toX | number |
toZ | number |
Returns
boolean
Whether a walkable path joins the two points (snapped like findPath).
Inherited from
heightAt()
ts
heightAt(x, z): number;Parameters
| Parameter | Type | Description |
|---|---|---|
x | number | World x. |
z | number | World z. |
Returns
number
Floor height there, or NaN outside the grid or where there is no floor.
Inherited from
isWalkable()
ts
isWalkable(x, z): boolean;Parameters
| Parameter | Type | Description |
|---|---|---|
x | number | World x. |
z | number | World z. |
Returns
boolean
Whether an agent centre may stand there.
Inherited from
lineOfSight()
ts
lineOfSight(
ax,
az,
bx,
bz
): boolean;Parameters
| Parameter | Type |
|---|---|
ax | number |
az | number |
bx | number |
bz | number |
Returns
boolean
Whether a straight walk from a to b stays on walkable, connected cells.
Inherited from
nearestWalkable()
ts
nearestWalkable(
x,
z,
out
): boolean;Parameters
| Parameter | Type | Description |
|---|---|---|
x | number | World x. |
z | number | World z. |
out | NavPoint | Receives the nearest walkable cell centre. |
Returns
boolean
false when nothing walkable is within the search radius.
Inherited from
removeCostArea()
ts
removeCostArea(id): void;Remove an area; unknown ids are ignored.
Parameters
| Parameter | Type |
|---|---|
id | number |
Returns
void
Example
ts
grid.removeCostArea(mud);removeLink()
ts
removeLink(id): void;Remove a link; unknown ids are ignored.
Parameters
| Parameter | Type |
|---|---|
id | number |
Returns
void
Example
ts
grid.removeLink(jump);removeObstacle()
ts
removeObstacle(id): void;Unblock what addObstacle blocked. Unknown ids are ignored.
Parameters
| Parameter | Type |
|---|---|
id | number |
Returns
void
NavGridOptions
How a nav grid covers the level. Every field but min and max has a default.
Properties
agentRadius?
ts
readonly optional agentRadius?: number;Radius of the agents the grid is for; walkable space is shrunk by it. Default 0.4.
cellSize?
ts
readonly optional cellSize?: number;Cell edge in metres. Default 0.5.
height?
ts
readonly optional height?: readonly [number, number];Vertical range [minY, maxY] probed by NavGrid.buildFromPhysics. Default [-10, 50].
max
ts
readonly max: readonly [number, number];Opposite corner, [x, z].
maxClimb?
ts
readonly optional maxClimb?: number;Highest step between neighbouring cells an agent can walk up or down. Default 0.4.
maxCostAreas?
ts
readonly optional maxCostAreas?: number;Most cost areas alive at once. Default 64.
maxLinks?
ts
readonly optional maxLinks?: number;Most links alive at once. Default 32.
maxObstacles?
ts
readonly optional maxObstacles?: number;Most obstacles alive at once. Default 256.
maxPathPoints?
ts
readonly optional maxPathPoints?: number;Most points one path can hold; longer paths are cut. Default 256.
maxSlope?
ts
readonly optional maxSlope?: number;Steepest walkable floor, in degrees. Default 45.
min
ts
readonly min: readonly [number, number];World-space corner of the covered area, [x, z].
NavigationBoundsProps
Grid bounds and agent tuning, in metres and degrees.
Example
ts
const props: Partial<NavigationBoundsProps> = { build: 'flat', cellSize: 0.5 };Properties
agentRadius
ts
agentRadius: number;build
ts
build: "physics" | "flat";cellSize
ts
cellSize: number;halfExtents
ts
halfExtents: [number, number, number];maxClimb
ts
maxClimb: number;maxSlope
ts
maxSlope: number;NavigationLinkProps
A connection from the actor position to a relative endpoint. The path and teleport preserve both authored endpoint heights.
Example
ts
const props: NavigationLinkProps = { end: [4, 0, 0], bidirectional: false, cost: 4 };Properties
bidirectional
ts
bidirectional: boolean;cost
ts
cost: number;end
ts
end: [number, number, number];NavigationModifierProps
Axis-aligned blocking or weighted area dimensions.
Example
ts
const props: NavigationModifierProps = { halfExtents: [1, 2, 3], areaClass: 'null', cost: 3 };Properties
areaClass
ts
areaClass: "null" | "costly";cost
ts
cost: number;halfExtents
ts
halfExtents: [number, number, number];NavPoint
A point on the ground plane, written in place by queries.
Properties
x
ts
x: number;z
ts
z: number;NavQuery
The query side every navigation user needs. A nav grid implements it; a baked navmesh may later implement it too.
Extended by
Properties
agentRadius
ts
readonly agentRadius: number;Agent radius the walkable space was shrunk by.
Methods
findPath()
ts
findPath(
fromX,
fromZ,
toX,
toZ,
out,
linkFlags?
): number;Cheapest walkable path. Uniform grids are string-pulled; weighted routes retain turning cell waypoints so smoothing cannot shortcut through expensive areas.
Parameters
| Parameter | Type | Description |
|---|---|---|
fromX | number | Start x; snapped to the nearest walkable cell when blocked. |
fromZ | number | Start z. |
toX | number | Goal x; snapped likewise. |
toZ | number | Goal z. |
out | Float32Array | Receives x, y, z per point, start first, goal last. |
linkFlags? | Uint8Array<ArrayBufferLike> | Optional caller-owned flags, cleared and filled per query: 1 at a link start, followed by its exact end point. Copy flags with the path before another query. A truncated path never ends with an unmatched link start. |
Returns
number
How many points were written; 0 when there is no path.
hasPath()
ts
hasPath(
fromX,
fromZ,
toX,
toZ
): boolean;Parameters
| Parameter | Type |
|---|---|
fromX | number |
fromZ | number |
toX | number |
toZ | number |
Returns
boolean
Whether a walkable path joins the two points (snapped like findPath).
heightAt()
ts
heightAt(x, z): number;Parameters
| Parameter | Type | Description |
|---|---|---|
x | number | World x. |
z | number | World z. |
Returns
number
Floor height there, or NaN outside the grid or where there is no floor.
isWalkable()
ts
isWalkable(x, z): boolean;Parameters
| Parameter | Type | Description |
|---|---|---|
x | number | World x. |
z | number | World z. |
Returns
boolean
Whether an agent centre may stand there.
lineOfSight()
ts
lineOfSight(
ax,
az,
bx,
bz
): boolean;Parameters
| Parameter | Type |
|---|---|
ax | number |
az | number |
bx | number |
bz | number |
Returns
boolean
Whether a straight walk from a to b stays on walkable, connected cells.
nearestWalkable()
ts
nearestWalkable(
x,
z,
out
): boolean;Parameters
| Parameter | Type | Description |
|---|---|---|
x | number | World x. |
z | number | World z. |
out | NavPoint | Receives the nearest walkable cell centre. |
Returns
boolean
false when nothing walkable is within the search radius.
NetFacade
The ctx.net facade, one per guest.
Example
ts
function votes(ctx: GameContext): void {
if (!ctx.net.isAuthority) return;
for (const vote of ctx.net.messages(Vote)) {
ctx.net.send('voted', { by: vote.player, for: vote.payload.for });
}
ctx.net.local(() => ctx.audio.play('tick')); // never sent to a player
}Properties
stats
ts
readonly stats: NetStats;Counters since init.
Accessors
isAuthority
Get Signature
ts
get isAuthority(): boolean;Returns
boolean
True on the authority and in a single-player game.
localPlayer
Get Signature
ts
get localPlayer(): number;Returns
number
The player this page belongs to on a client; 0 elsewhere.
predicts
Get Signature
ts
get predicts(): boolean;Returns
boolean
True on a client page that actually predicts its own character body (the client loop's own predict option, not merely the game's declared features.multiplayer.predict). False on the authority and in solo.
role
Get Signature
ts
get role(): NetRole;Returns
Where this guest runs.
soloRoom
Get Signature
ts
get soloRoom(): boolean;Identify the authority that Play Solo runs in this page.
Example
ts
if (ctx.net.soloRoom) ctx.net.setPhase('loading');Returns
boolean
True for Play Solo’s in-page authority.
Methods
beginTick()
ts
beginTick(): void;Start a tick: this tick's messages are read afresh. Runtime only.
Returns
void
local()
ts
local(fn): void;Run fn with every command it queues routed to frame-output.local-commands: applied where this guest runs, never sent to a player. Nested calls stay local; a throw still restores the network buffer. Allocates nothing.
Parameters
| Parameter | Type | Description |
|---|---|---|
fn | () => void | The code whose commands stay local. |
Returns
void
messages()
ts
messages<T>(message): readonly NetMessage<T>[];This tick's validated messages for one definition, in arrival order.
A payload over the definition's maxBytes, not JSON, or failing its check is dropped and counted in stats.dropped, never thrown at a system; the rest count in stats.received. The list and its entries are pooled and refilled each tick: read them inside the tick, never retain them. Reading the same name twice in a tick counts nothing twice.
A bare name (deprecated) reads the same list without a check, unless the name's definition has been read before in this run; it caps at 2,048 bytes.
Type Parameters
| Type Parameter |
|---|
T |
Parameters
| Parameter | Type | Description |
|---|---|---|
message | string | MessageDef<T> | The definition, or a bare message name. |
Returns
readonly NetMessage<T>[]
The messages, { player, payload }.
reset()
ts
reset(): void;Forget the counters and every cached message list. init only.
Returns
void
send()
Call Signature
ts
send<T>(
message,
payload,
options?
): void;Send a game message: from the authority to one player or all of them, from a client up to the authority (to is ignored there).
Pass a defineMessage definition to check the payload with its guard and cap it at its maxBytes before it leaves; a bare name (deprecated) checks only the 2,048-byte wire cap.
The payload is serialised with JSON.stringify, so a tick that sends allocates that one string; a tick that sends nothing allocates nothing. undefined sends null.
Type Parameters
| Type Parameter |
|---|
T |
Parameters
| Parameter | Type | Description |
|---|---|---|
message | MessageDef<T> | The definition, or a bare message name. |
payload | T | Anything JSON-serialisable; at most maxBytes (2,048) as UTF-8 JSON. |
options? | SendOptions | to one player, and reliable (default true). A payload that does not serialise (a function or a symbol), fails the definition's check, or whose JSON is over the cap sends nothing and counts in stats.unsent; it never throws, since a throwing system fails the tick. |
Returns
void
Call Signature
ts
send(
name,
payload,
options?
): void;Send a game message: from the authority to one player or all of them, from a client up to the authority (to is ignored there).
Pass a defineMessage definition to check the payload with its guard and cap it at its maxBytes before it leaves; a bare name (deprecated) checks only the 2,048-byte wire cap.
The payload is serialised with JSON.stringify, so a tick that sends allocates that one string; a tick that sends nothing allocates nothing. undefined sends null.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | - |
payload | unknown | Anything JSON-serialisable; at most maxBytes (2,048) as UTF-8 JSON. |
options? | SendOptions | to one player, and reliable (default true). A payload that does not serialise (a function or a symbol), fails the definition's check, or whose JSON is over the cap sends nothing and counts in stats.unsent; it never throws, since a throwing system fails the tick. |
Returns
void
setPhase()
ts
setPhase(word): void;Say what the room is doing, in a word (lobby, playing, voting), for the public room list beside its code and seats. Authority only: on a client, and in a game with no room, it does nothing. The same word again sends nothing and allocates nothing; a new one sends the reserved message aos:phase, which the room server reads and never forwards to a player.
Parameters
| Parameter | Type | Description |
|---|---|---|
word | string | 1 to 32 ASCII letters, digits or dashes. Anything else sends nothing, counts in stats.unsent and is logged once; it never throws. |
Returns
void
Example
ts
function lobby(ctx: GameContext): void {
ctx.net.setPhase(started ? 'playing' : 'lobby');
}NetMessage
What messages hands back: one player's message, its payload parsed.
Example
ts
for (const m of ctx.net.messages(Vote)) tally(m.player, m.payload.for);Type Parameters
| Type Parameter |
|---|
T |
Properties
payload
ts
readonly payload: T;The JSON payload, parsed.
player
ts
readonly player: number;The sender.
NetMessageEvent
A game message a player sent, delivered to the authority on its next tick.
Named NetMessageEvent rather than the WIT's message-event so it never shadows the DOM's MessageEvent in a page that imports both.
Properties
name
ts
name: string;payload
ts
payload: string;JSON.
player
ts
player: number;The sender.
NetStats
Counters a game or the debug overlay can read.
Example
ts
ctx.hud.set({ dropped: ctx.net.stats.dropped, received: ctx.net.stats.received });Properties
dropped
ts
dropped: number;Messages read and dropped: over their maxBytes, not JSON, or failing their defineMessage check. A payload over 2,048 bytes is dropped by the room before it reaches the guest, and is not counted here.
received
ts
received: number;Messages read and handed to a system.
unsent
ts
unsent: number;ctx.net.send calls since init that sent nothing: the payload failed its check, did not serialise, or was over the cap. Never thrown, because a throw fails the tick and enough of them kill the guest for the room.
OverlapHit
One body overlapping a query volume.
Properties
body
ts
body: number;depth
ts
depth: number;entity
ts
entity: number;point
ts
point: Vec3;Deepest contact point on the other body for shape overlaps; bounds centre if unavailable.
PathPreview
Caller-owned path preview, with world-space endpoint and budget marker.
Example
ts
const result: PathPreview = { count: 0, length: 0, reachable: false, endX: 0, endZ: 0, budgetX: 0, budgetZ: 0, withinBudget: false };Properties
budgetX
ts
budgetX: number;budgetZ
ts
budgetZ: number;count
ts
count: number;endX
ts
endX: number;endZ
ts
endZ: number;length
ts
length: number;reachable
ts
reachable: boolean;withinBudget
ts
withinBudget: boolean;Penetration
Minimum translation out of an obstacle.
Example
ts
const overlap: Penetration = { normal: {x:1,y:0,z:0}, depth: 0.1, entity: 2 };Properties
depth
ts
depth: number;entity
ts
entity: number;isPawn?
ts
optional isPawn?: boolean;normal
ts
normal: Vec3;PhysicsJointOptions
Joint settings in degrees and metres.
Example
ts
const opts: PhysicsJointOptions = { kind: 'hinge' };Extends
Properties
actorA?
ts
optional actorA?: string;actorB?
ts
optional actorB?: string;attach?
ts
optional attach?: string;Parent component name; defaults to root for non-root components.
Inherited from
axis?
ts
optional axis?: readonly [number, number, number];kind
ts
kind: ConstraintKind;max?
ts
optional max?: number;min?
ts
optional min?: number;motor?
ts
optional motor?: object;maxForce
ts
maxForce: number;mode
ts
mode: MotorMode;target
ts
target: number;offset?
ts
optional offset?: readonly [number, number, number];Translation in the parent's space.
Inherited from
rotation?
ts
optional rotation?: Quat;Local quaternion, default identity.
Inherited from
scale?
ts
optional scale?: readonly [number, number, number];Local per-axis scale, default one.
Inherited from
spring?
ts
optional spring?: JointSpring;PhysicsJointProps
Level-friendly joint settings; null limits leave the joint free.
Example
ts
const props: Partial<PhysicsJointProps> = { actorA: 'door' };Properties
actorA
ts
actorA: string;actorB
ts
actorB: string;axis
ts
axis: readonly [number, number, number];kind
ts
kind: ConstraintKind;max
ts
max: number | null;min
ts
min: number | null;motorMaxForce
ts
motorMaxForce: number;motorMode
ts
motorMode: MotorMode;motorTarget
ts
motorTarget: number;PickupProps
Pickup tuning in level data.
Example
ts
const props: PickupProps = { give: {heal: 25}, respawnSeconds: 10, spin: 90, bob: 0.1, asset: '' };Properties
asset
ts
asset: string;bob
ts
bob: number;give
ts
give: PickupGive;respawnSeconds
ts
respawnSeconds: number;spin
ts
spin: number;PlaceholderSpec
A shape the host draws for a prefab with no body and no asset, such as a collision: 'none' actor box. It makes no physics body. Kept out of PrefabSpec: actors set it, script authors never need to.
Properties
placeholder?
ts
optional placeholder?: Pick<BodySpec, "shape" | "dims">;Shape and dimensions to draw.
PlacingModuleOptions
Bounded finish plane, with ascending-seat ties.
Example
ts
import type { PlacingModuleOptions } from 'gameable';
const options: PlacingModuleOptions = { axis: 'z', direction: 'decreasing', at: -68, maxAbsX: 5, minY: 2, maxY: 6, tieBreak: 'seat', requiresAllCheckpoints: false, freezeFinishers: true };
console.log(options.at);Properties
at
ts
at: number;axis
ts
axis: "z";direction
ts
direction: "decreasing";freezeFinishers
ts
freezeFinishers: boolean;maxAbsX
ts
maxAbsX: number;maxY
ts
maxY: number;minY
ts
minY: number;requiresAllCheckpoints
ts
requiresAllCheckpoints: false;tieBreak
ts
tieBreak: "seat";PlatformingOptions
Platforming tuning in metres and seconds. Requires a physics character body.
Example
ts
const abilities: PlatformingOptions = { coyoteSeconds: 0.12, dashSpeed: 14 };Properties
coyoteSeconds?
ts
optional coyoteSeconds?: number;dashAction?
ts
optional dashAction?: string;dashCooldown?
ts
optional dashCooldown?: number;dashSeconds?
ts
optional dashSeconds?: number;dashSpeed?
ts
optional dashSpeed?: number;jumpAction?
ts
optional jumpAction?: string;jumpBufferSeconds?
ts
optional jumpBufferSeconds?: number;wallJumpSpeed?
ts
optional wallJumpSpeed?: number;wallProbeDistance?
ts
optional wallProbeDistance?: number;wallSlideSpeed?
ts
optional wallSlideSpeed?: number;PlayerHandle
One player: who they are, the entity definition.player spawned for them, and facades that read their input and write their own camera and HUD.
Example
ts
for (const [id, p] of ctx.players) {
if (p.input.pressed('Space')) jump(p.entity);
p.hud.set({ name: p.name, id });
}Properties
camera
ts
readonly camera: object;This player's camera: every write queues one set-player-camera per tick.
look
Get Signature
ts
get look(): object;Accumulated look angles, in radians. Mutate to snap the view.
Returns
object
The live look state.
pitch
ts
pitch: number;sensitivity
ts
sensitivity: number;yaw
ts
yaw: number;state
Get Signature
ts
get state(): CameraState;Returns
fight()
ts
fight(shot): void;The fight camera (the fight kit's script door), run on the host: from the side, between the two fighters, pulled back as they part, raised when one flies, never still, inside the ropes; a wide shot on a knockdown, in close on the winner. Say it every step while it is on; the camera is yours again with on: false.
Parameters
| Parameter | Type | Description |
|---|---|---|
shot | FightShotOptions | The two fighters and the moment. |
Returns
void
Nothing.
firstPerson()
ts
firstPerson(entity, options?): void;Mount the camera at an entity's eyes.
Yaw and pitch come from the built-in look accumulator, which integrates input.mouse.dx/dy once per tick.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity to mount on. |
options? | FirstPersonOptions | Eye height and field of view. |
Returns
void
Nothing.
follow()
ts
follow(entity, options?): void;Put the camera on a spring arm behind an entity.
The host owns the arm and its collision; the guest only states the intent. position is the orbit pivot and rotation the direction the player is looking, so a host with no rig still ends up somewhere sensible.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity to follow. |
options? | FollowOptions | Boom length, height offset, field of view and orbit angles. |
Returns
void
Nothing.
lookAt()
ts
lookAt(point): void;Aim the camera at a world point, overriding its rotation.
Parameters
| Parameter | Type | Description |
|---|---|---|
point | Vec3 | null | The point to look at, or null to use the rotation again. |
Returns
void
Nothing.
set()
ts
set(
position,
rotation,
fovYDeg?
): void;Place the camera explicitly, detaching it from any entity.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
position | Vec3 | undefined | Eye position. |
rotation | Quat | undefined | Eye rotation, xyzw. |
fovYDeg | number | 60 | Vertical field of view in degrees. Default 60. |
Returns
void
Nothing.
hud
ts
readonly hud: object;This player's HUD: a changed model queues a set-player-hud.
clear()
ts
clear(): void;Drop the HUD: emit an empty model this frame.
Idempotent — calling it every frame emits {} once, exactly like set.
Returns
void
Nothing.
invalidate()
ts
invalidate(): void;Forget what the host has seen, so the next set emits even if the model did not change. Use it after the host reloaded its overlay.
On its own it sends nothing: the next set does. To send an empty model now, call clear().
Returns
void
Nothing.
set()
ts
set(model): boolean;Set the HUD model for this frame.
Nested plain objects are compared by value four levels down, so a model rebuilt inline every frame is recognised as unchanged. Arrays and class instances are compared by identity: keep those out of the model, or build them once and mutate nothing.
Parameters
| Parameter | Type | Description |
|---|---|---|
model | Record<string, unknown> | A JSON-serialisable object. |
Returns
boolean
True when the model changed and JSON will cross this frame.
id
ts
readonly id: number;The player id this slot belongs to.
input
ts
readonly input: object;This player's keys, mouse and gamepads, read like input.
touch
ts
touch: object;Fingers on a touch screen, as the host's touch layer packs them: the first finger is the pointer (mouse), a tap is pressed('Tap'), and the thumb sticks, the pinch and the turn are here.
touch.active
Get Signature
ts
get active(): boolean;Is a finger on the screen? (The touch pad is connected.)
Returns
boolean
True while any finger is down.
touch.pinch
Get Signature
ts
get pinch(): number;Two fingers' pinch this step, as a scale factor: over 1 the fingers moved apart (zoom in), under 1 together, exactly 1 with no pinch.
Returns
number
The scale factor.
touch.turn
Get Signature
ts
get turn(): number;Two fingers' turn this step, in radians, counter-clockwise on the screen positive.
Returns
number
The turn.
touch.stick()
ts
stick(side): Axis2;A thumb stick's push.
Parameters
| Parameter | Type | Description |
|---|---|---|
side | "left" | "right" | The left stick (movement) or the right one (the camera). |
Returns
A pooled { x, y }, -1..1, y up the screen positive. Never retain it.
control
Get Signature
ts
get control(): Readonly<NonNullable<InputState["control"]>>;Received page control for this frame. Owned by the SDK; read during the tick.
Returns
Readonly<NonNullable<InputState["control"]>>
The control state received with this input sequence.
focused
Get Signature
ts
get focused(): boolean;Does the canvas have focus? Treat input as neutral when it does not.
Returns
boolean
True while the canvas is focused.
mods
Get Signature
ts
get mods(): InputMods;Keyboard modifier state.
Returns
The modifiers for this frame.
mouse
Get Signature
ts
get mouse(): MouseState;Pointer position, per-frame delta, wheel and button bitsets.
Returns
The mouse state for this frame. Owned by the SDK; never retain it.
action()
ts
action(name): ActionState;Read a declared button into pooled storage. Unknown names throw.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Declared button action name. |
Returns
Pooled button state; read immediately.
axis2()
ts
axis2(
negX,
posX?,
negY?,
posY?,
stick?
): Axis2;Pass a declared axis action name alone, or four keys. A two-axis reading built from four keys, plus a thumb stick on a touch screen: the left one by default, so axis2('A', 'D', 'S', 'W') moves on a phone with no other binding. Pass 'right' for a camera axis, 'none' for keys only. With the left stick and opposing WASD/arrow movement pairs, uses combined movement (both key sets, left touch and first physical pad, radial deadzone and unit-circle clamp), with each binding's requested sign. Page control supplies that same movement when present. Other bindings read only their four keys and the requested touch stick.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
negX | string | undefined | Declared axis name, or key driving x negative, e.g. 'A'. |
posX? | string | undefined | Key that drives x positive, for example 'D'. |
negY? | string | undefined | Key that drives y negative, for example 'S'. |
posY? | string | undefined | Key that drives y positive, for example 'W'. |
stick? | StickSide | 'left' | Which thumb stick to add, 'left' by default. |
Returns
A pooled { x, y } with components in -1..1. Never retain it.
gamepad()
ts
gamepad(index):
| {
axes: ArrayLike<number>;
buttons: number;
connected: boolean;
index: number;
pressed: number;
released: number;
}
| null;One connected gamepad.
Parameters
| Parameter | Type | Description |
|---|---|---|
index | number | Navigator gamepad index. |
Returns
| { axes: ArrayLike<number>; buttons: number; connected: boolean; index: number; pressed: number; released: number; } | null
The gamepad, or null when nothing is connected at that index. Owned by the SDK; never retain it.
isDown()
ts
isDown(key): boolean;Is the key held this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
key | string | A DOM code ('KeyW'), a bare letter/digit ('W', '1') or an alias ('Shift', 'Esc'). |
Returns
boolean
True while the key is down.
mouseDown()
ts
mouseDown(button): boolean;Is a mouse button held?
Parameters
| Parameter | Type | Description |
|---|---|---|
button | number | A MOUSE_BUTTONS value, or a raw bit mask. |
Returns
boolean
True while the button is down.
mousePressed()
ts
mousePressed(button): boolean;Did a mouse button go down this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
button | number | A MOUSE_BUTTONS value, or a raw bit mask. |
Returns
boolean
True on the frame the button went down.
mouseReleased()
ts
mouseReleased(button): boolean;Did a mouse button come up this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
button | number | A MOUSE_BUTTONS value, or a raw bit mask. |
Returns
boolean
True on the frame the button came up.
pressed()
ts
pressed(key): boolean;Did the key go down this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
key | string | A key name. |
Returns
boolean
True on the frame the key went down.
released()
ts
released(key): boolean;Did the key come up this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
key | string | A key name. |
Returns
boolean
True on the frame the key came up.
lanes
ts
readonly lanes: InputLanes;The decoded input this handle's input reads. Internal.
present
ts
present: boolean = false;In this step's frame-input.players. Internal.
seq
ts
seq: number = 0;The input sequence number this step consumed.
spawn
ts
spawn: number = 0;The current authoritative camera reset generation (u16).
Accessors
connected
Get Signature
ts
get connected(): boolean;Returns
boolean
True between this player's player-joined and player-left.
data
Get Signature
ts
get data(): unknown;Returns
unknown
The player's document: the one the room loaded at join, then whatever ctx.data.save or a finished exchange made it; null for none.
entity
Get Signature
ts
get entity(): number;Returns
number
The entity this player controls: the one definition.player spawned at join, or the last one possessed; 0 for none (also after that entity is despawned).
isHost
Get Signature
ts
get isHost(): boolean;Returns
boolean
True for the host (ctx.players.host): the first joiner, until they leave; then the lowest seat still joined.
joinedAt
Get Signature
ts
get joinedAt(): number | null;Returns
number | null
The server's clock when the room loaded this player's document, in ms since the epoch, or null when the room has no store. The guest has no clock of its own (now-ms counts from engine start), so this is the one wall time it gets: add ctx.elapsed since the join to it.
name
Get Signature
ts
get name(): string;Returns
string
The display name the room gave at join, or ''.
savedAt
Get Signature
ts
get savedAt(): number | null;Returns
number | null
When the store last wrote the document handed over at join, in ms since the epoch by the server's clock, or null when there was none. Offline time is joinedAt - savedAt.
Methods
forgetEntity()
ts
forgetEntity(entity): void;The possessed entity was despawned: the player controls none. The host clears its own mapping on the despawn, so nothing is sent.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | A despawned entity. |
Returns
void
integrateLook()
ts
integrateLook(): void;Apply received absolute look in the room, or integrate pointer movement on the page and for inputs without control. Allocates nothing.
Returns
void
join()
ts
join(name, data): void;The player took this seat. Parses the saved document: a join-tick allocation.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | The display name. |
data | string | null | undefined | The room's { doc, savedAt, now } as JSON, when it has a store (a bare document is taken as the doc). |
Returns
void
leave()
ts
leave(): void;The player left; the caller has already despawned PlayerHandle.entity.
Returns
void
possess()
ts
possess(entity): void;Make this player control another entity: a respawn, a vehicle, a class swap. On the authority it queues a set-player-entity, so the room follows the player there (relevancy) and their client learns which entity is theirs. Despawning the entity later leaves the player with none until the next possess. A different nonzero entity advances the camera reset generation; possessing the same entity keeps the look. Use resetView() when a same-entity respawn should also reset the camera.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | The entity, or 0 to control none. |
Returns
void
Example
ts
const body = ctx.spawn(Avatar, spawnPoint);
ctx.players.get(id)?.possess(body);resetView()
ts
resetView(): void;Request an authoritative camera reset, including for a respawn that reuses the same entity. Client-role calls do nothing; the page resets when it observes the generation. The page acknowledges the new generation before its look is accepted.
Returns
void
Example
ts
ctx.players.get(id)?.resetView();restoreSeat()
ts
restoreSeat(
connected,
name,
entity,
data
): void;Overwrite who holds this seat from a snapshot. The caller rebuilds the map.
Parameters
| Parameter | Type | Description |
|---|---|---|
connected | boolean | Joined and not left. |
name | string | The display name. |
entity | number | The player's entity in the restored world, or 0. |
data | unknown | The saved document, already parsed. |
Returns
void
setEntity()
ts
setEntity(entity): void;The authority spawned this player's entity at join: possess it (which tells the host). Nothing is sent for 0 (a game with no player prefab).
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | The entity spawned for this player, or 0. |
Returns
void
PlayerInput
One player's input for a step, as frame-input.players carries it.
Properties
input
ts
input: InputState;That player's keys, mouse and gamepads.
player
ts
player: number;The player id. 0 is the single-player player, which travels as frame-input.input.
seq
ts
seq: number;The client's input sequence number this step consumed; 0 when unknown.
PlayerJoinedEvent
A player entered the room.
Properties
data?
ts
optional data?: string;The player's saved document as JSON, when the room has a store. Absent otherwise (null in a wasm guest, as every incoming option is).
name
ts
name: string;player
ts
player: number;PlayerLeftEvent
A player left the room.
Properties
player
ts
player: number;reason
ts
reason: string;Why: "left", "timeout", "kicked", ...
Players
The room's players: a read-only Map from id to PlayerHandle, plus who the host is and a list to walk without allocating.
A for...of over the map (or keys(), values(), entries()) makes an iterator, and an entry pair per player, every call: fine in a join handler, not in a system that runs every tick. Walk list with an index there.
Example
ts
const players = ctx.players;
for (let i = 0; i < players.list.length; i += 1) {
const p = players.list[i];
if (p.isHost && p.input.pressed('Enter')) startRound();
}
const host = players.host === undefined ? undefined : players.get(players.host);Extends
ReadonlyMap<number,PlayerHandle>
Properties
host
ts
readonly host: number | undefined;The host's seat id, or undefined while nobody is joined. The first joiner is the host and stays host until they leave (player-left); only then does it pass to the lowest seat still joined. A newcomer who takes a lower, freed seat does not become host. Snapshots keep it.
A host who drops counts as gone for this alone: while the room holds their seat (they are still joined, but out of the frame's players list), the role passes to the lowest seat in that list, and it stays there when they come back. If nobody else is in the list, the held host keeps it.
list
ts
readonly list: readonly PlayerHandle[];The same players as the map, in id order. The same array for the whole run, updated in place on a join or a leave; never per tick. Read it, do not keep a copy of its contents across ticks.
PlayerSpec
The declarative player block.
Properties
camera?
ts
optional camera?: "firstPerson" | "thirdPerson";Which built-in camera rig to drive.
character?
ts
optional character?: (seat) => string;Character asset id for a seat, overriding the prefab's character.
Parameters
| Parameter | Type |
|---|---|
seat | number |
Returns
string
distance?
ts
optional distance?: number;Third-person boom length, metres. Default 4.
eyeHeight?
ts
optional eyeHeight?: number;First-person eye height, metres. Default 1.7.
height?
ts
optional height?: number;Third-person height offset, metres. Default 1.6.
prefab?
ts
optional prefab?: PrefabDef;Prefab to spawn for the player.
sensitivity?
ts
optional sensitivity?: number;Radians of look per pixel of mouse movement. Default 0.0025.
spawn?
ts
optional spawn?: PlayerSpawn | MarkerSpawn;Where each seat spawns; see PlayerSpawn. Default [0, 0, 0].
PlayerStateProps
Persistent seat statistics.
Example
ts
const stats: Partial<PlayerStateProps> = { team: 1 };Properties
deaths
ts
deaths: number;kills
ts
kills: number;playerName
ts
playerName: string;score
ts
score: number;seat
ts
seat: number;team
ts
team: number;PlayMusicCmd
play-music payload.
Example
ts
`const value: PlayMusicCmd = {tracks: [], stems: [], stemGains: [], bpm: 0, beatsPerBar: 4, firstBeat: 0, fadeMs: 0, start: 'now', looping: false, volume: 1};`Properties
beatsPerBar
ts
beatsPerBar: number;Beats per bar; 0 means 4.
bpm
ts
bpm: number;Beats per minute; 0 disables the clock.
fadeMs
ts
fadeMs: number;Crossfade duration in milliseconds.
firstBeat
ts
firstBeat: number;Seconds from file start to beat zero.
looping
ts
looping: boolean;Loop tracks or stems.
start
ts
start: BeatQuantize;Start relative to the current grid.
stemGains
ts
stemGains: number[];Initial gains; missing entries mean 1.
stems
ts
stems: number[];Sample-locked layers; ignores tracks when non-empty.
tracks
ts
tracks: number[];Streamed playlist in order.
volume
ts
volume: number;Linear gain.
PlayOnBeatOptions
Grid-scheduled sound options.
Example
ts
`audio.playOnBeat('kick', { quantize: 'bar' });`Properties
bus?
ts
optional bus?: AudioBus;Mixer bus.
quantize?
ts
optional quantize?: BeatQuantize;Grid; defaults to beat.
subdivision?
ts
optional subdivision?: number;Points per beat; defaults to one.
volume?
ts
optional volume?: number;Linear gain.
PlayOptions
Options for audio.play.
Properties
bus?
ts
optional bus?: AudioBus;Mixer bus. Default 'sfx'.
entity?
ts
optional entity?: number;Attach to an entity for positional audio that follows it.
looping?
ts
optional looping?: boolean;Loop until stopped. Default false.
pitch?
ts
optional pitch?: number;Playback-rate multiplier. Default 1.
volume?
ts
optional volume?: number;Linear gain in 0..1. Default 1.
PlaySoundCmd
Start a sound.
Properties
asset
ts
asset: number;bus
ts
bus: AudioBus;entity?
ts
optional entity?: number;looping
ts
looping: boolean;pitch
ts
pitch: number;position?
ts
optional position?: Vec3;sound
ts
sound: number;volume
ts
volume: number;PlaySoundOnBeatCmd
play-sound-on-beat payload.
Example
ts
`const value: PlaySoundOnBeatCmd = {sound: 0, asset: 0, quantize: 'beat', subdivision: 1, volume: 1, bus: 'sfx'};`Properties
asset
ts
asset: number;Manifest asset handle.
bus
ts
bus: AudioBus;Mixer bus.
quantize
ts
quantize: BeatQuantize;Grid to schedule on.
sound
ts
sound: number;Guest-minted sound handle.
subdivision
ts
subdivision: number;Grid points per beat; ignored for bars.
volume
ts
volume: number;Linear gain.
PlaytestCmd
A playtest mark (playtest facade): something a playtest should know happened. It changes nothing in the game; the page's recorder, its agent and the playtest reports read it.
Properties
entity
ts
entity: number;The entity it concerns (the player, the goal), or 0.
kind
ts
kind: string;What happened: death, win, checkpoint, damage, reward, goal, player, restart, or a word of the game's own.
note
ts
note: string;Why, in a few words: a death's cause. May be empty.
position
ts
position: Vec3 | undefined;Where, in world space, or undefined.
value
ts
value: number;How much: damage taken, a reward; 0 when it has no amount.
PostCmd
Partial post command; absent fields preserve the current look.
Example
ts
import type { PostCmd } from 'gameable';
const command: PostCmd = { reset: true, bloom: 0.5 };Properties
bloom?
ts
optional bloom?: number;bloomRadius?
ts
optional bloomRadius?: number;bloomThreshold?
ts
optional bloomThreshold?: number;contrast?
ts
optional contrast?: number;exposure?
ts
optional exposure?: number;fogColor?
ts
optional fogColor?: Vec3;fogDensity?
ts
optional fogDensity?: number;reset
ts
reset: boolean;Back to neutral before this command's fields apply.
saturation?
ts
optional saturation?: number;tint?
ts
optional tint?: Vec3;toneMapping?
ts
optional toneMapping?: ToneMapping;vignette?
ts
optional vignette?: number;PostSettings
Partial post settings. Omitted fields retain the host's current values.
Example
ts
import { vfx, type PostSettings } from 'gameable';
const settings: PostSettings = { reset: true, bloom: 0.4, toneMapping: 'aces' };
vfx.post(settings);Properties
bloom?
ts
optional bloom?: number;Bloom strength; neutral 0.
bloomRadius?
ts
optional bloomRadius?: number;Bloom radius; neutral 0.4.
bloomThreshold?
ts
optional bloomThreshold?: number;Bloom threshold in linear light; neutral 1.
contrast?
ts
optional contrast?: number;Contrast multiplier; neutral 1.
exposure?
ts
optional exposure?: number;Exposure multiplier; neutral 1.
fogColor?
ts
optional fogColor?: Vec3;Fog linear RGB colour; neutral (0.5, 0.55, 0.6).
fogDensity?
ts
optional fogDensity?: number;Exponential fog density; neutral 0.
reset?
ts
optional reset?: boolean;Return to neutral before applying the supplied fields.
saturation?
ts
optional saturation?: number;Saturation multiplier; neutral 1.
tint?
ts
optional tint?: Vec3;Linear RGB grade; neutral (1, 1, 1).
toneMapping?
ts
optional toneMapping?: ToneMapping;Tone mapping; neutral 'none'.
vignette?
ts
optional vignette?: number;Vignette strength; neutral 0.
PrefabDef
A prefab, ready to spawn.
Extends
Properties
asset?
ts
optional asset?: string | number;Renderable asset: a manifest string id, or a handle.
Inherited from
body?
ts
optional body?: BodySpec;Physics body, if any.
Inherited from
character?
ts
optional character?: string | number;Splat character bundle: a manifest string id, or a handle.
Inherited from
components?
ts
optional components?: readonly object[];Extra bitecs components and tags to add on spawn.
Inherited from
health?
ts
optional health?: number;Starting hit points; adds the Health component when present.
Inherited from
name?
ts
optional name?: string;Debug label shown in the engine overlay.
Inherited from
prefabId
ts
readonly prefabId: number;Stable index, assigned in declaration order.
scale?
ts
optional scale?: readonly number[];Uniform or per-axis scale. Default [1, 1, 1].
Inherited from
PrefabSpec
Everything a prefab can declare.
Extended by
Properties
asset?
ts
optional asset?: string | number;Renderable asset: a manifest string id, or a handle.
body?
ts
optional body?: BodySpec;Physics body, if any.
character?
ts
optional character?: string | number;Splat character bundle: a manifest string id, or a handle.
components?
ts
optional components?: readonly object[];Extra bitecs components and tags to add on spawn.
health?
ts
optional health?: number;Starting hit points; adds the Health component when present.
name?
ts
optional name?: string;Debug label shown in the engine overlay.
scale?
ts
optional scale?: readonly number[];Uniform or per-axis scale. Default [1, 1, 1].
PressurePlateProps
Floor-level pressure plate tuning. Occupants are tested by their actor/player origin.
Example
ts
const props: Partial<PressurePlateProps> = { weight: 2, pressedBy: ['crate'] };Properties
colour
ts
colour: [number, number, number];depth
ts
depth: number;holdSeconds
ts
holdSeconds: number;once
ts
once: boolean;pressedBy
ts
pressedBy: string[];pressSound
ts
pressSound: string;releaseSound
ts
releaseSound: string;weight
ts
weight: number;width
ts
width: number;ProjectileOptions
Guest projectile integration; homing target is an ECS entity id, resolved each step.
Example
ts
const options: ProjectileOptions = { speed: 20, gravityScale: 1, bounces: 2, bounciness: 0.7 };Properties
bounces?
ts
optional bounces?: number;bounciness?
ts
optional bounciness?: number;gravityScale?
ts
optional gravityScale?: number;homingTarget?
ts
optional homingTarget?: number;onHit?
ts
optional onHit?: (self, hit, ctx, stopped) => void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle |
hit | RayHit |
ctx | GameContext |
stopped | boolean |
Returns
void
speed
ts
speed: number;ProjectileProps
Projectile level data. Launch is along local +Z; lifeSpan zero means forever.
Example
ts
const props: Partial<ProjectileProps> = {speed: 30, damage: 20, gravityScale: 0, lifeSpan: 3};Properties
asset
ts
asset: string;bounces
ts
bounces: number;bounciness
ts
bounciness: number;damage
ts
damage: number;gravityScale
ts
gravityScale: number;hitResponse
ts
hitResponse: "damage" | "effect" | "both";homingTarget
ts
homingTarget: number;Target ECS entity id, resolved each step; zero disables homing.
lifeSpan
ts
lifeSpan: number;speed
ts
speed: number;PropMeta
Authoring hints and constraints for one property; omitted type is inferred from its default.
Example
ts
const meta: PropMeta = { description: 'Reach.', min: 0, unit: 'metres' };Extended by
Properties
const?
ts
optional const?: boolean;Restrict a boolean branch to one literal value.
description
ts
description: string;fields?
ts
optional fields?: Record<string, PropMeta>;group?
ts
optional group?: string;Shared reference table; actor-specific differences remain documented on the actor.
items?
ts
optional items?: PropMeta;max?
ts
optional max?: number;min?
ts
optional min?: number;nullable?
ts
optional nullable?: boolean;Accept null in addition to the described shape.
oneOf?
ts
optional oneOf?: readonly PropMeta[];optional?
ts
optional optional?: boolean;Allow this field to be omitted from a fixed-shape object.
type?
ts
optional type?:
| "string"
| "number"
| "boolean"
| "object"
| "vec3"
| "color"
| "enum"
| "array";unit?
ts
optional unit?: string;values?
ts
optional values?: readonly string[];Quat
A unit quaternion in xyzw order (three.js / Jolt order).
Properties
w
ts
w: number;x
ts
x: number;y
ts
y: number;z
ts
z: number;QueryFilter
Which bodies a physics query considers.
Properties
excludeBody?
ts
optional excludeBody?: number;excludeEntity?
ts
optional excludeEntity?: number;layers
ts
layers: CollisionLayers;solidOnly
ts
solidOnly: boolean;QueryShape
QueryShape: radians and metres at the host boundary.
Example
ts
import type { QueryShape } from 'gameable';
const value: QueryShape = { kind: 'sphere', halfExtents: { x: 1, y: 1, z: 1 } };Properties
halfExtents
ts
halfExtents: Vec3;Box uses xyz; sphere radius is x; capsule/cylinder radius is x and half-height is y.
kind
ts
kind: "box" | "sphere" | "capsule" | "cylinder";Quests
An owner's quest log. Callbacks run synchronously: progress, objective-done, then complete. Forced completion visits objectives in ascending index order. Empty quests complete immediately when started. Values clamp to [0, target].
Example
ts
import { createQuests, type Quests } from 'gameable';
const log: Quests = createQuests({ owners: 1, quests: [{ id: 'visit', objectives: [{ id: 'gate' }] }] });
log.start(0, 'visit');
log.progress(0, 'visit', 'gate');Extends
Methods
abandon()
ts
abandon(owner, quest): boolean;Abandon an active quest and clear its values.
Parameters
| Parameter | Type |
|---|---|
owner | number |
quest | string | number |
Returns
boolean
complete()
ts
complete(owner, quest): boolean;Force completion from available or active; false otherwise.
Parameters
| Parameter | Type |
|---|---|
owner | number |
quest | string | number |
Returns
boolean
done()
ts
done(
owner,
quest,
objective
): boolean;Whether the objective reached its target.
Parameters
| Parameter | Type |
|---|---|
owner | number |
quest | string | number |
objective | string | number |
Returns
boolean
objective()
ts
objective(quest, id): number;Resolve an objective within a quest.
Parameters
| Parameter | Type |
|---|---|
quest | string | number |
id | string | number |
Returns
number
progress()
ts
progress(
owner,
quest,
objective,
amount?
): number;Add progress while active; return the clamped value.
Parameters
| Parameter | Type |
|---|---|
owner | number |
quest | string | number |
objective | string | number |
amount? | number |
Returns
number
quest()
ts
quest(id): number;Resolve a quest id or validate its index.
Parameters
| Parameter | Type |
|---|---|
id | string | number |
Returns
number
reset()
ts
reset(): void;Back to the state right after creation. Call from init.
Returns
void
Inherited from
restore()
ts
restore(state, options?): void;Read back what snapshot returned. Throws on a malformed state.
Parameters
| Parameter | Type |
|---|---|
state | unknown |
options? | { crossBuild?: boolean; } |
options.crossBuild? | boolean |
Returns
void
Inherited from
set()
ts
set(
owner,
quest,
objective,
value
): number;Set progress while active; return the clamped value.
Parameters
| Parameter | Type |
|---|---|
owner | number |
quest | string | number |
objective | string | number |
value | number |
Returns
number
snapshot()
ts
snapshot(): unknown;Plain JSON-safe data for defineGame({ snapshot }).
Returns
unknown
Inherited from
start()
ts
start(owner, quest): boolean;Start an available quest.
Parameters
| Parameter | Type |
|---|---|
owner | number |
quest | string | number |
Returns
boolean
status()
ts
status(owner, quest): "active" | "locked" | "available" | "complete";Prerequisites are checked immediately for this owner.
Parameters
| Parameter | Type |
|---|---|
owner | number |
quest | string | number |
Returns
"active" | "locked" | "available" | "complete"
value()
ts
value(
owner,
quest,
objective
): number;Read progress.
Parameters
| Parameter | Type |
|---|---|
owner | number |
quest | string | number |
objective | string | number |
Returns
number
RaceProgress
Borrowed live progress; immutable to callers. FinishedAt uses the swept substep time.
Example
ts
const show = (p: RaceProgress) => console.log(p.place, p.completedLaps);Extends
Properties
completedLaps
ts
completedLaps: number;entity
ts
entity: number;Inherited from
finishedAt
ts
finishedAt: number | null;finishPlace
ts
finishPlace: number;lastGate
ts
lastGate: number;nextGate
ts
nextGate: number;place
ts
place: number;racer
ts
racer: number;Inherited from
respawnPose
ts
respawnPose: object;position
ts
position: [number, number, number];yaw
ts
yaw: number;seat
ts
seat: number | null;Inherited from
segmentDistance
ts
segmentDistance: number;status
ts
status: "finished" | "active" | "disconnected" | "spectating";RacingLineOptions
Racing line controls. cornerSpeed is the minimum preview corner speed in m/s.
Example
ts
followRacingLine(ctx, ai, ['start', 'bend', 'finish'], { speed: 15, loop: true });Extends
Properties
acceptanceRadius?
ts
optional acceptanceRadius?: number;Inherited from
cornerSpeed?
ts
optional cornerSpeed?: number;lateralOffset?
ts
optional lateralOffset?: number;lookAhead?
ts
optional lookAhead?: number;loop?
ts
optional loop?: boolean;speed?
ts
optional speed?: number;Inherited from
stopAtTarget?
ts
optional stopAtTarget?: boolean;Inherited from
tuning?
ts
optional tuning?: Partial<DriveTuning>;Inherited from
RadialForceOptions
Radial impulses and continuous force, in metres and SI physics units.
Example
ts
const options: RadialForceOptions = { radius: 8, falloff: 'linear' };Properties
active?
ts
optional active?: boolean;falloff?
ts
optional falloff?: "linear" | "constant";forceStrength?
ts
optional forceStrength?: number;impulseStrength?
ts
optional impulseStrength?: number;radius?
ts
optional radius?: number;velocityChange?
ts
optional velocityChange?: boolean;RayHit
Closest hit along a ray.
Properties
body
ts
body: number;distance
ts
distance: number;entity
ts
entity: number;normal
ts
normal: Vec3;point
ts
point: Vec3;RayQuery
One ray in a raycastBatch call.
Properties
direction
ts
direction: Vec3;filter
ts
filter: QueryFilter;maxDistance
ts
maxDistance: number;origin
ts
origin: Vec3;RenderableStore
Renderable asset handle plus host-side flags.
Properties
asset
ts
asset: Uint32Array;Manifest asset handle; 0 means "no renderable".
dirty
ts
dirty: Uint8Array;Non-zero when the host has not yet seen the current value.
flags
ts
flags: Uint32Array;Reserved host flags bitset.
ResetVehicleCmd
Reset pose in world coordinates.
Example
ts
const command = { body: 1, position: {x:0,y:1,z:0}, rotation: {x:0,y:0,z:0,w:1} };Properties
body
ts
body: number;position
ts
position: Vec3;rotation
ts
rotation: Quat;Rgba
Linear RGBA, components in 0..1.
Properties
a
ts
a: number;b
ts
b: number;g
ts
g: number;r
ts
r: number;RigidBodyStore
Rigid body handle and classification.
Properties
dirty
ts
dirty: Uint8Array;Non-zero when the host has not yet seen the current value.
groundState
ts
groundState: Uint8Array;Post-step contact: 0 unknown, 1 ground, 2 steep, 3 unsupported, 4 air.
handle
ts
handle: Uint32Array;Guest-minted body id; 0 means "no body".
kind
ts
kind: Uint8Array;BODY_KIND index.
shape
ts
shape: Uint8Array;SHAPE_KIND index.
Rng
A seeded, serialisable random source.
Methods
float()
ts
float(): number;Next float in [0, 1).
Returns
number
int()
ts
int(n): number;Next integer in [0, n). Returns 0 when n <= 0.
Parameters
| Parameter | Type |
|---|---|
n | number |
Returns
number
load()
ts
load(state): void;Overwrite the state.
Parameters
| Parameter | Type |
|---|---|
state | RngState |
Returns
void
pick()
ts
pick<T>(items): T | undefined;A uniformly chosen element, or undefined when the array is empty.
Type Parameters
| Type Parameter |
|---|
T |
Parameters
| Parameter | Type |
|---|---|
items | ArrayLike<T> |
Returns
T | undefined
range()
ts
range(min, max): number;Next float in [min, max).
Parameters
| Parameter | Type |
|---|---|
min | number |
max | number |
Returns
number
save()
ts
save(out?): RngState;Copy the state out, into out when given.
Parameters
| Parameter | Type |
|---|---|
out? | RngState |
Returns
seed()
ts
seed(value): void;Re-seed from a 32-bit integer.
Parameters
| Parameter | Type |
|---|---|
value | number |
Returns
void
uint32()
ts
uint32(): number;Next u32.
Returns
number
RngState
Four-word xoshiro128** state, as it appears in a snapshot.
Properties
s0
ts
s0: number;s1
ts
s1: number;s2
ts
s2: number;s3
ts
s3: number;RuleEvent
Borrowed lifecycle payload; winner is a team id or player seat, null for a draw.
Example
ts
const result: RuleEvent = { phase: 'round', round: 1, winner: null };Properties
phase
ts
phase: string;round
ts
round: number;winner
ts
winner: number | null;SaveGameDataCmd
Persist the room's game-wide document (JSON). Authority only.
Properties
data
ts
data: string;SavePlayerDataCmd
Persist one player's document (JSON). Authority only.
Properties
data
ts
data: string;player
ts
player: number;SayCmd
Speak a line, optionally with audio and a viseme track.
Properties
audio?
ts
optional audio?: number;entity
ts
entity: number;text
ts
text: string;visemes?
ts
optional visemes?: string;ScreenPoint
Screen position and distance along the view axis, in metres.
Example
ts
const point: ScreenPoint = { x: 0, y: 0, depth: 0, visible: false };Properties
depth
ts
depth: number;visible
ts
visible: boolean;x
ts
x: number;y
ts
y: number;ScreenRay
World ray with a normalised direction; allocate once and reuse.
Example
ts
const ray: ScreenRay = { origin: { x: 0, y: 0, z: 0 }, direction: { x: 0, y: 0, z: -1 } };Properties
direction
ts
direction: Vec3;origin
ts
origin: Vec3;Selection
Stable, duplicate-free selection in insertion order. Full sets ignore new entries.
Example
ts
const selection = createSelection(32); selection.add(unit);Properties
entities
ts
readonly entities: readonly number[];Methods
add()
ts
add(entity): void;Parameters
| Parameter | Type |
|---|---|
entity | number |
Returns
void
box()
ts
box(
candidates,
x0,
y0,
x1,
y1,
project,
additive?
): void;Parameters
| Parameter | Type |
|---|---|
candidates | readonly number[] |
x0 | number |
y0 | number |
x1 | number |
y1 | number |
project | (entity, out) => boolean |
additive? | boolean |
Returns
void
clear()
ts
clear(): void;Returns
void
has()
ts
has(entity): boolean;Parameters
| Parameter | Type |
|---|---|
entity | number |
Returns
boolean
prune()
ts
prune(isAlive): void;Parameters
| Parameter | Type |
|---|---|
isAlive | (entity) => boolean |
Returns
void
set()
ts
set(entity): void;Parameters
| Parameter | Type |
|---|---|
entity | number |
Returns
void
toggle()
ts
toggle(entity): void;Parameters
| Parameter | Type |
|---|---|
entity | number |
Returns
void
SendCmd
Send a game message to one player, every player, or up to the authority.
Properties
name
ts
name: string;payload
ts
payload: string;JSON, at most 2,048 bytes.
reliable
ts
reliable: boolean;to?
ts
optional to?: number;One player; absent sends to every player (authority) or to the authority (client).
SendOptions
Options for NetFacade.send.
Example
ts
ctx.net.send('role', { role: 'murderer' }, { to: 3 });
ctx.net.send('aim', { x: 1 }, { reliable: false }); // every player, may dropProperties
reliable?
ts
optional reliable?: boolean;Ordered and guaranteed. Default true.
to?
ts
optional to?: number;One player; absent sends to every player. Ignored on a client.
SensesOptions
Sensing settings and callbacks retained by derived actor specs.
Example
ts
const options: SensesOptions = { sightRadius: 20, onSeePawn(self, pawn, ctx) {} };Extends
Properties
attach?
ts
optional attach?: string;Parent component name; defaults to root for non-root components.
Inherited from
hearingThreshold?
ts
optional hearingThreshold?: number;interval?
ts
optional interval?: number;losHearingThreshold?
ts
optional losHearingThreshold?: number;offset?
ts
optional offset?: readonly [number, number, number];Translation in the parent's space.
Inherited from
onlySensePlayers?
ts
optional onlySensePlayers?: boolean;peripheralAngle?
ts
optional peripheralAngle?: number;rotation?
ts
optional rotation?: Quat;Local quaternion, default identity.
Inherited from
scale?
ts
optional scale?: readonly [number, number, number];Local per-axis scale, default one.
Inherited from
sightRadius?
ts
optional sightRadius?: number;Methods
onHearNoise()?
ts
optional onHearNoise(
self,
instigator,
location,
loudness,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle |
instigator | number |
location | Readonly<Vec3> |
loudness | number |
ctx | GameContext |
Returns
void
onSeePawn()?
ts
optional onSeePawn(
self,
pawn,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle |
pawn | number |
ctx | GameContext |
Returns
void
SetAnimCmd
Play or cross-fade an animation clip on one layer.
Properties
clip
ts
clip: string;entity
ts
entity: number;fadeMs
ts
fadeMs: number;looping
ts
looping: boolean;speed
ts
speed: number;weight
ts
weight: number;SetAssetCmd
Attach or detach an entity's renderable.
Properties
asset?
ts
optional asset?: number;entity
ts
entity: number;SetBodyEnabledCmd
Enable or disable a body in the broad phase.
Properties
body
ts
body: number;enabled
ts
enabled: boolean;SetBodyTransformCmd
Move a body directly.
Properties
body
ts
body: number;position
ts
position: Vec3;rotation
ts
rotation: Quat;teleport
ts
teleport: boolean;SetBodyVelocityCmd
Overwrite a body's velocities. undefined leaves one untouched.
Properties
angular?
ts
optional angular?: Vec3;body
ts
body: number;linear?
ts
optional linear?: Vec3;SetBusFxCmd
set-bus-fx payload.
Example
ts
`const value: SetBusFxCmd = {bus: 'sfx', preset: 'dry', reverb: undefined, lowpassHz: undefined, highpassHz: undefined, compressor: undefined, fadeMs: 0};`Properties
bus
ts
bus: AudioBus;Mixer bus.
compressor?
ts
optional compressor?: boolean;Optional compression switch.
fadeMs
ts
fadeMs: number;Ramp duration in milliseconds.
highpassHz?
ts
optional highpassHz?: number;Optional high-pass cutoff in Hz.
lowpassHz?
ts
optional lowpassHz?: number;Optional low-pass cutoff in Hz.
preset
ts
preset: FxPreset;Base effect preset.
reverb?
ts
optional reverb?: number;Optional wet level.
SetCharacterMotionCmd
How the movement system moves a character (see character.motion).
Properties
carry
ts
carry: boolean;Whether the take carries the walker.
entity
ts
entity: number;naturalness
ts
naturalness: number;on
ts
on: boolean;Whether the movement system moves this character at all.
responsiveness
ts
responsiveness: number;0..1; negative keeps what it has.
set?
ts
optional set?: string;'own', 'shared' or a name the page gave its bridge; absent keeps the set it has.
stop?
ts
optional stop?: StopStyle;Which kind of stop it makes when it runs and is asked to stand: 'gradual' (it slows and stands upright) or 'hard' (it brakes). Absent keeps what it has.
SetCharacterStateCmd
Drive a character's locomotion state machine.
Properties
entity
ts
entity: number;facing?
ts
optional facing?: number;Optional held world yaw in radians.
grounded
ts
grounded: boolean;state
ts
state: string;velocity
ts
velocity: Vec3;SetClipWeightsCmd
Set explicit per-clip weights on a character's body layer.
Properties
clips
ts
clips: readonly string[];entity
ts
entity: number;timeScale
ts
timeScale: number;weights
ts
weights: readonly number[] | Float32Array<ArrayBufferLike>;SetExpressionCmd
Set a character's facial expression coefficients.
Properties
entity
ts
entity: number;space
ts
space: ExpressionSpace;weights
ts
weights: readonly number[] | Float32Array<ArrayBufferLike>;SetJointMotorCmd
SetJointMotorCmd: radians and metres at the host boundary.
Example
ts
import type { SetJointMotorCmd } from 'gameable';
const value: SetJointMotorCmd = { joint: 1, axis: 0, mode: 'position', target: 1, maxForce: 10 };Properties
axis
ts
axis: number;joint
ts
joint: number;maxForce
ts
maxForce: number;mode
ts
mode: MotorMode;target
ts
target: number;SetListenerCmd
Place the audio listener.
Properties
position
ts
position: Vec3;rotation
ts
rotation: Quat;velocity
ts
velocity: Vec3;SetMaterialParamCmd
Set one material uniform.
Properties
entity
ts
entity: number;name
ts
name: string;value
ts
value: MaterialValue;SetMusicLayerCmd
set-music-layer payload.
Example
ts
`const value: SetMusicLayerCmd = {layer: 0, gain: 1, fadeMs: 0};`Properties
fadeMs
ts
fadeMs: number;Ramp duration in milliseconds.
gain
ts
gain: number;Linear gain.
layer
ts
layer: number;Stem index.
SetParentCmd
Reparent an entity in the scene graph.
Properties
entity
ts
entity: number;keepWorldTransform
ts
keepWorldTransform: boolean;parent?
ts
optional parent?: number;SetPlayerCameraCmd
The camera one player renders from.
Properties
camera
ts
camera: CameraState;player
ts
player: number;SetPlayerEntityCmd
Which entity a player controls. The authority sends it when it spawns definition.player for a join and on every PlayerHandle.possess; the host keeps the mapping (relevancy, "which entity is mine" on the client).
Properties
entity
ts
entity: number;player
ts
player: number;spawn?
ts
optional spawn?: number;Acknowledged camera reset generation; absent for legacy host commands.
SetPlayerHudCmd
One player's HUD model as JSON.
Properties
hud
ts
hud: string;player
ts
player: number;SetSoundOcclusionCmd
set-sound-occlusion payload.
Example
ts
`const value: SetSoundOcclusionCmd = {sound: 0, amount: 0, fadeMs: 0};`Properties
amount
ts
amount: number;Occlusion from 0 to 1.
fadeMs
ts
fadeMs: number;Ramp duration in milliseconds.
sound
ts
sound: number;Sound handle.
SetVehicleInputCmd
Normalized transient controls.
Example
ts
const command = { body: 1, controls, gripScale: 1 };Properties
body
ts
body: number;controls
ts
controls: VehicleInput;gripScale
ts
gripScale: number;Shape
Collision shape description carried by add-body.
Properties
asset?
ts
optional asset?: number;halfExtents
ts
halfExtents: Vec3;kind
ts
kind: ShapeKind;ShapeOptions
Collision and rigid body settings.
Example
ts
const options: ShapeOptions = { collision: 'block', body: 'dynamic' };Extends
Extended by
Properties
attach?
ts
optional attach?: string;Parent component name; defaults to root for non-root components.
Inherited from
body?
ts
optional body?: "static" | "dynamic" | "kinematic";Blocking body motion; defaults to static.
ccd?
ts
optional ccd?: boolean;Continuous collision detection for fast dynamic bodies.
collision?
ts
optional collision?:
| "none"
| "block"
| "Spectator"
| "overlap"
| CollisionSetup
| "NoCollision"
| "BlockAll"
| "OverlapAll"
| "BlockAllDynamic"
| "OverlapAllDynamic"
| "IgnoreOnlyPawn"
| "OverlapOnlyPawn"
| "Pawn"
| "CharacterMesh"
| "PhysicsActor"
| "Destructible"
| "InvisibleWall"
| "InvisibleWallDynamic"
| "Trigger"
| "Ragdoll"
| "Vehicle"
| "UI";Collision response; defaults to block.
dimensions?
ts
optional dimensions?: readonly string[];Spawn-time prop names supplying dimensions: ['halfExtents'] or ['radius', 'halfHeight'].
fit?
ts
optional fit?: "mesh" | "box" | "convex-hull";mesh() only: give the mesh a body fitted to its own model, built by the page from the model's geometry and scale once it loads: 'box' its bounds, 'convex-hull' its hull, 'mesh' its triangles (static only).
layer?
ts
optional layer?: CollisionLayers;Physics collision layer.
mask?
ts
optional mask?: CollisionLayers;Raw physics mask; cannot accompany a named/custom collision policy.
mass?
ts
optional mass?: number;Dynamic mass in kilograms.
offset?
ts
optional offset?: readonly [number, number, number];Translation in the parent's space.
Inherited from
reportHits?
ts
optional reportHits?: boolean;Request blocking contact callbacks.
rotation?
ts
optional rotation?: Quat;Local quaternion, default identity.
Inherited from
scale?
ts
optional scale?: readonly [number, number, number];Local per-axis scale, default one.
Inherited from
SidedSystem
A system that says where it runs.
'authority' runs on the room's authority and in a single-player (solo) game; 'client' runs on a player's page and in solo; 'both' runs everywhere. solo is its own authority and its own client, so it runs all three. A bare function is 'authority' once the game declares features.multiplayer, and 'both' otherwise, so a single-player game reads the same as it always did.
Example
ts
import { defineGame } from 'gameable';
export default defineGame({
features: { multiplayer: true },
systems: [
(ctx) => { ctx.net.send('tick', ctx.frame); }, // bare: the authority's
{ on: 'client', run: (ctx) => { ctx.hud.set({ ping: ctx.frame }); } },
],
});Properties
on
ts
on: "client" | "authority" | "both";Where it runs.
run
ts
run: Run;The system.
SideScrollCameraOptions
Side view bounds refer to camera centre, in metres.
Example
ts
const options: SideScrollCameraOptions = { minX: 0, maxX: 40 };Properties
deadZone?
ts
optional deadZone?: number;distance?
ts
optional distance?: number;height?
ts
optional height?: number;lead?
ts
optional lead?: number;maxX
ts
maxX: number;maxY?
ts
optional maxY?: number;minX
ts
minX: number;minY?
ts
optional minY?: number;smoothing?
ts
optional smoothing?: number;SlidingDoorProps
Local panel slide tuning. Zero travel selects panel width.
Example
ts
const props: Partial<SlidingDoorProps> = { panels: 2 };Extends
Extended by
Properties
action
ts
action: string;Inherited from
asset?
ts
optional asset?: string;Inherited from
autoCloseSeconds
ts
autoCloseSeconds: number;Inherited from
DoorCoreProps.autoCloseSeconds
closePrompt
ts
closePrompt: string;Inherited from
closeSound
ts
closeSound: string;Inherited from
colour
ts
colour: [number, number, number];Inherited from
consumeKey
ts
consumeKey: boolean;Inherited from
enabled
ts
enabled: boolean;Inherited from
facingDegrees
ts
facingDegrees: number;Inherited from
height
ts
height: number;Closed doorway height in metres.
Inherited from
lockedBy
ts
lockedBy: string;Inherited from
lockedMessage
ts
lockedMessage: string;Inherited from
lockedPrompt
ts
lockedPrompt: string;Inherited from
lockedSound
ts
lockedSound: string;Inherited from
look
ts
look: "none" | "wood" | "metal";Inherited from
once
ts
once: boolean;Inherited from
openPrompt
ts
openPrompt: string;Inherited from
openSound
ts
openSound: string;Inherited from
opensWhen
ts
opensWhen: string[];Inherited from
panels
ts
panels: 1 | 2;prompt
ts
prompt: string;Inherited from
range
ts
range: number;Inherited from
seconds
ts
seconds: number;Inherited from
slide
ts
slide: "left" | "right" | "up";startOpen
ts
startOpen: boolean;Inherited from
stayOpen
ts
stayOpen: boolean;Inherited from
thickness
ts
thickness: number;Leaf thickness in metres.
Inherited from
toggledBy
ts
toggledBy: "signal" | "proximity" | "interact";Inherited from
travel
ts
travel: number;width
ts
width: number;Closed doorway width in metres.
Inherited from
SnapshotPeek
What peekSnapshotHeader returns: the header's frame counter and the game's folded state (defineGame's parts, the actor rows among them), read without a runtime.
Properties
elapsed
ts
elapsed: number;Simulated seconds since init.
frame
ts
frame: number;The fixed-step counter when the snapshot was taken.
player
ts
player: number;The player entity, or 0.
user
ts
user: unknown;What defineGame({ snapshot }) folded in: { __gameableActors: 1, actors: { rows }, ... } or the game's own.
SoundEndedEvent
A playing sound stopped.
Properties
completed
ts
completed: boolean;sound
ts
sound: number;SpawnCharacterCmd
Instantiate a splat character bundle.
Properties
bundle
ts
bundle: number;entity
ts
entity: number;position
ts
position: Vec3;rotation
ts
rotation: Quat;SpawnCmd
Create an entity, optionally with a renderable asset.
Properties
asset?
ts
optional asset?: number;entity
ts
entity: number;name?
ts
optional name?: string;parent?
ts
optional parent?: number;position
ts
position: Vec3;rotation
ts
rotation: Quat;scale
ts
scale: Vec3;visible
ts
visible: boolean;SpawnerProps
Wave spawner level data. Points selects TargetPoint actors by tag; an empty tag uses the spawner transform.
Example
ts
const props: Partial<SpawnerProps> = {actorClass: 'Enemy', waves: [{count: 3,every: 1}],maxAlive: 2};Properties
actorClass
ts
actorClass: string;autoStart
ts
autoStart: boolean;maxAlive
ts
maxAlive: number;points
ts
points: string;waves
ts
waves: object[];count
ts
count: number;delay?
ts
optional delay?: number;every
ts
every: number;SpawnSpec
One entry of the declarative spawns list.
Properties
position
ts
position: readonly number[];Where, [x, y, z].
prefab
ts
prefab: PrefabDef;What to spawn.
rotation?
ts
optional rotation?: readonly number[];Rotation, [x, y, z, w]. Defaults to identity.
SplinePath
World-space distance queries over an authored local path.
Example
ts
const path: SplinePath = splineOf(actor, 'path');Properties
length
ts
readonly length: number;Methods
closestDistance()
ts
closestDistance(point): number;Parameters
| Parameter | Type |
|---|---|
point | Readonly<Vec3> |
Returns
number
directionAt()
ts
directionAt(distance, out): Vec3;Parameters
| Parameter | Type |
|---|---|
distance | number |
out | Vec3 |
Returns
pointAt()
ts
pointAt(distance, out): Vec3;Parameters
| Parameter | Type |
|---|---|
distance | number |
out | Vec3 |
Returns
SpotLightCmd
Guest spotlight settings. Local forward is -Z; camera attachment uses the active view.
Example
ts
const light: SpotLightCmd = { entity: 1, color: { x: 1, y: 1, z: 1 }, intensity: 20, radius: 12, angle: 30, penumbra: 0.4, cameraAttached: true, enabled: true };Properties
angle
ts
angle: number;cameraAttached
ts
cameraAttached: boolean;color
ts
color: object;x
ts
x: number;y
ts
y: number;z
ts
z: number;enabled
ts
enabled: boolean;entity
ts
entity: number;intensity
ts
intensity: number;penumbra
ts
penumbra: number;radius
ts
radius: number;StaminaOptions
Sprint energy tuning, in units and seconds.
Example
ts
const tuning: StaminaOptions = { maximum: 5, drain: 1, regen: 0.5 };Properties
drain?
ts
optional drain?: number;maximum?
ts
optional maximum?: number;recoveryDelay?
ts
optional recoveryDelay?: number;regen?
ts
optional regen?: number;StaminaState
Serializable component state; set requested while moving.
Example
ts
const energy: StaminaState = { value: 5, maximum: 5, requested: false, active: false, exhausted: false, delay: 0 };Properties
active
ts
active: boolean;delay
ts
delay: number;exhausted
ts
exhausted: boolean;maximum
ts
maximum: number;requested
ts
requested: boolean;value
ts
value: number;StartOptions
A persistent emitter's position or entity attachment, plus burst overrides.
Example
ts
import { vfx, type StartOptions } from 'gameable';
const options: StartOptions = { at: { x: 0, y: 1, z: 0 } };
const id = vfx.start('fire', options);
vfx.stop(id);Extends
Properties
at?
ts
optional at?: Vec3;World position, or offset when attached to an entity; defaults to zero.
direction?
ts
optional direction?: Vec3;Emission direction; absent uses the preset's own direction.
Inherited from
entity?
ts
optional entity?: number;Follow this entity.
intensity?
ts
optional intensity?: number;Count and brightness multiplier, default 1.
Inherited from
scale?
ts
optional scale?: number;Size multiplier, default 1.
Inherited from
tint?
ts
optional tint?: Vec3;Linear RGB override; values over 1 glow under bloom.
Inherited from
StemOptions
Stem playback options.
Example
ts
`music.stems(['drums', 'bass'], { gains: [1, 0] });`Extends
Properties
beatsPerBar?
ts
optional beatsPerBar?: number;Beats in each bar; defaults to four.
Inherited from
bpm?
ts
optional bpm?: number;Beats per minute; zero disables the clock.
Inherited from
fadeMs?
ts
optional fadeMs?: number;Crossfade duration.
Inherited from
firstBeat?
ts
optional firstBeat?: number;Seconds to beat zero.
Inherited from
gains?
ts
optional gains?: readonly number[];Initial gains; missing entries mean one.
loop?
ts
optional loop?: boolean;Loop playback.
Inherited from
start?
ts
optional start?: BeatQuantize;Starting grid; defaults to now.
Inherited from
volume?
ts
optional volume?: number;Linear gain.
Inherited from
StopSoundCmd
Stop a playing sound.
Properties
fadeMs
ts
fadeMs: number;sound
ts
sound: number;SweepHit
Blocking contact. Optional metadata preserves surface policy and distinct edge normals.
Example
ts
const hit: SweepHit = { time: 1, distance: 1, normal: {x:0,y:1,z:0}, point: {x:0,y:0,z:0}, entity: 1, startPenetrating: false, depth: 0 };Properties
canStepUp?
ts
optional canStepUp?: boolean;depth
ts
depth: number;distance
ts
distance: number;entity
ts
entity: number;impactNormal?
ts
optional impactNormal?: Vec3;isPawn?
ts
optional isPawn?: boolean;normal
ts
normal: Vec3;point
ts
point: Vec3;startPenetrating
ts
startPenetrating: boolean;time
ts
time: number;walkableFloorZ?
ts
optional walkableFloorZ?: number;ThingCmd
Something a game asks of a loose thing in a made world (gameable/world): push an impulse at its middle (newton-seconds), move the middle of its base to a point (at rest), reset it to where the package had it, or reset-all for every loose thing. Of a thing with moving parts: joint and drive. Of a thing with rider spots: ride sits a character on it, or takes whoever sits on it off. Of a thing in pieces: break lets its pieces go (named for one piece, that piece alone). The thing is named by its place in the world's list.
Properties
action
ts
action:
| "push"
| "joint"
| "move"
| "reset"
| "drive"
| "reset-all"
| "ride"
| "break";thing
ts
thing: number;The thing's place in the world's list; ignored by reset-all.
vector
ts
vector: Vec3;push: the impulse. move: the point. joint: x the joint's place in the thing's list of joints, y its value. drive: x steering to the right (-1 to 1), y the brakes (0 to 1), z the throttle (-1 to 1). ride: x the character's entity, 0 for getting off. Zero otherwise.
ThirdPersonClips
Optional authored clips; omit to use the animator's standard locomotion blend.
Properties
fall
ts
fall: string;idle
ts
idle: string;land
ts
land: string;rise
ts
rise: string;run
ts
run: string;walk
ts
walk: string;TileColliderOptions
Tile collider spawning configuration.
Example
ts
const options: TileColliderOptions = { collision: 'BlockAll', cellSize: 2 };Properties
cellSize?
ts
optional cellSize?: number;collision?
ts
optional collision?:
| "Spectator"
| CollisionSetup
| "NoCollision"
| "BlockAll"
| "OverlapAll"
| "BlockAllDynamic"
| "OverlapAllDynamic"
| "IgnoreOnlyPawn"
| "OverlapOnlyPawn"
| "Pawn"
| "CharacterMesh"
| "PhysicsActor"
| "Destructible"
| "InvisibleWall"
| "InvisibleWallDynamic"
| "Trigger"
| "Ragdoll"
| "Vehicle"
| "UI";TileCollisionBox
Merged tile collision box in world metres.
Example
ts
const boxes: TileCollisionBox[] = mergeTileColliders([{ x: 0, z: 0, height: 1 }]);Properties
center
ts
center: Vec3;halfExtents
ts
halfExtents: readonly [number, number, number];Timers
Fixed-step timer slots. Call reset from game init.
Example
ts
import { createTimers, type Timers } from 'gameable';
const timers: Timers = createTimers({ capacity: 4 });
timers.reset();Extends
Methods
active()
ts
active(timer): boolean;Whether the slot is counting down.
Parameters
| Parameter | Type |
|---|---|
timer | number |
Returns
boolean
cancel()
ts
cancel(timer): void;Cancel a slot and clear its progress.
Parameters
| Parameter | Type |
|---|---|
timer | number |
Returns
void
fired()
ts
fired(timer): boolean;True from firing until the next step, including after restart or cancel.
Parameters
| Parameter | Type |
|---|---|
timer | number |
Returns
boolean
progress()
ts
progress(timer): number;Elapsed fraction; completed one-shots retain one until cancelled.
Parameters
| Parameter | Type |
|---|---|
timer | number |
Returns
number
remaining()
ts
remaining(timer): number;Remaining seconds using the timestep captured at start.
Parameters
| Parameter | Type |
|---|---|
timer | number |
Returns
number
reset()
ts
reset(): void;Back to the state right after creation. Call from init.
Returns
void
Inherited from
restore()
ts
restore(state, options?): void;Read back what snapshot returned. Throws on a malformed state.
Parameters
| Parameter | Type |
|---|---|
state | unknown |
options? | { crossBuild?: boolean; } |
options.crossBuild? | boolean |
Returns
void
Inherited from
snapshot()
ts
snapshot(): unknown;Plain JSON-safe data for defineGame({ snapshot }).
Returns
unknown
Inherited from
start()
ts
start(
ctx,
timer,
seconds,
repeat?
): void;Start or restart a slot; duration is converted once using ctx.dt.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
timer | number |
seconds | number |
repeat? | boolean |
Returns
void
step()
ts
step(ctx): void;Advance all slots, then call onFire synchronously in ascending slot order.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
TopDownCamera
A deterministic camera rig. Do not also declare player.camera in defineGame.
Example
ts
const rig: TopDownCamera = createTopDownCamera(); rig.pan(2, 0);Properties
state
ts
readonly state: TopDownCameraState;Plain JSON pose, including saved follow bookkeeping.
Methods
focusOn()
ts
focusOn(point): void;Jump to a world point and stop following.
Parameters
| Parameter | Type |
|---|---|
point | Vec3 |
Returns
void
follow()
ts
follow(entity): void;Track a Transform; zero stops. Pan input breaks follow.
Parameters
| Parameter | Type |
|---|---|
entity | number |
Returns
void
pan()
ts
pan(dx, dz): void;Camera-relative metres; +dx is right, +dz is forward.
Parameters
| Parameter | Type |
|---|---|
dx | number |
dz | number |
Returns
void
rotate()
ts
rotate(dYaw): void;Add radians about +Y.
Parameters
| Parameter | Type |
|---|---|
dYaw | number |
Returns
void
update()
ts
update(ctx, dt): void;Read controls, clamp, and write the frame camera; call once per tick.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
dt | number |
Returns
void
zoom()
ts
zoom(factor): void;Multiply distance by a positive factor, clamped to limits.
Parameters
| Parameter | Type |
|---|---|
factor | number |
Returns
void
TopDownCameraOptions
Controls and limits for a perspective top-down rig.
Example
ts
const options: TopDownCameraOptions = { distance: 20, edgePan: true };Properties
bounds?
ts
optional bounds?: object;Focus limits in world x/z.
max
ts
max: [number, number];min
ts
min: [number, number];distance?
ts
optional distance?: number;Initial boom length, metres; default 14.
edgeMarginPx?
ts
optional edgeMarginPx?: number;Edge band width in pixels; default 24.
edgePan?
ts
optional edgePan?: boolean;Enable viewport edge panning; default false.
fovYDeg?
ts
optional fovYDeg?: number;Vertical field of view, degrees; default 45.
keys?
ts
optional keys?: object;Pan keys (arrows also work with defaults), and rotation keys.
down?
ts
optional down?: string;left?
ts
optional left?: string;right?
ts
optional right?: string;rotateLeft?
ts
optional rotateLeft?: string;rotateRight?
ts
optional rotateRight?: string;up?
ts
optional up?: string;maxDistance?
ts
optional maxDistance?: number;Maximum boom length, metres; default 40.
minDistance?
ts
optional minDistance?: number;Minimum boom length, metres; default 6.
panSpeed?
ts
optional panSpeed?: number;Metres/second at distance 10, scaled by distance; default 10.
pitch?
ts
optional pitch?: number;Tilt below the horizon, radians; default 55 degrees.
rotateStep?
ts
optional rotateStep?: number;Q/E rotation speed in radians/second; default PI/2.
zoomStep?
ts
optional zoomStep?: number;Fractional wheel zoom per line/notch; default 0.1.
TopDownCameraState
JSON camera pose; save this object and restore it with Object.assign(rig.state, saved).
Example
ts
const state: TopDownCameraState = createTopDownCamera().state;Properties
distance
ts
distance: number;Metres from focus to eye.
focus
ts
focus: Vec3;Ground point to look at.
fovYDeg
ts
fovYDeg: number;Vertical field of view, degrees.
pitch
ts
pitch: number;Radians below the horizon, in (0, PI/2].
yaw
ts
yaw: number;Radians about +Y; zero puts the eye on the +Z side.
TransformStore
Position, rotation (xyzw) and scale, one lane per component.
Properties
qw
ts
qw: Float32Array;qx
ts
qx: Float32Array;qy
ts
qy: Float32Array;qz
ts
qz: Float32Array;sx
ts
sx: Float32Array;sy
ts
sy: Float32Array;sz
ts
sz: Float32Array;x
ts
x: Float32Array;y
ts
y: Float32Array;z
ts
z: Float32Array;TrapDoorProps
Floor hatch dimensions: height is depth along local Z, thickness along local Y.
Example
ts
const props: Partial<TrapDoorProps> = { swingDegrees: 90 };Extends
Properties
action
ts
action: string;Inherited from
asset?
ts
optional asset?: string;Inherited from
autoCloseSeconds
ts
autoCloseSeconds: number;Inherited from
DoorCoreProps.autoCloseSeconds
closePrompt
ts
closePrompt: string;Inherited from
closeSound
ts
closeSound: string;Inherited from
colour
ts
colour: [number, number, number];Inherited from
consumeKey
ts
consumeKey: boolean;Inherited from
enabled
ts
enabled: boolean;Inherited from
facingDegrees
ts
facingDegrees: number;Inherited from
height
ts
height: number;Closed doorway height in metres.
Inherited from
lockedBy
ts
lockedBy: string;Inherited from
lockedMessage
ts
lockedMessage: string;Inherited from
lockedPrompt
ts
lockedPrompt: string;Inherited from
lockedSound
ts
lockedSound: string;Inherited from
look
ts
look: "none" | "wood" | "metal";Inherited from
once
ts
once: boolean;Inherited from
openPrompt
ts
openPrompt: string;Inherited from
openSound
ts
openSound: string;Inherited from
opensWhen
ts
opensWhen: string[];Inherited from
prompt
ts
prompt: string;Inherited from
range
ts
range: number;Inherited from
seconds
ts
seconds: number;Inherited from
startOpen
ts
startOpen: boolean;Inherited from
stayOpen
ts
stayOpen: boolean;Inherited from
swingDegrees
ts
swingDegrees: number;thickness
ts
thickness: number;Leaf thickness in metres.
Inherited from
toggledBy
ts
toggledBy: "signal" | "proximity" | "interact";Inherited from
width
ts
width: number;Closed doorway width in metres.
Inherited from
TriggerHandlers
Named trigger transitions, dispatched by the actor runtime's overlap events.
Example
ts
const handlers: TriggerHandlers = { enter: (other, ctx) => ctx.hud.set({ entered: true }) };Properties
enter?
ts
optional enter?: (other, ctx) => void;Runs once on entry; actors need overlaps:true, players are watched automatically.
Parameters
| Parameter | Type |
|---|---|
other | ActorOther |
ctx | GameContext |
Returns
void
exit?
ts
optional exit?: (other, ctx) => void;Runs once on exit, including watched entity removal.
Parameters
| Parameter | Type |
|---|---|
other | ActorOther |
ctx | GameContext |
Returns
void
Triggers
Guest-side point zones, independent of physics. Inside queries reflect the last step. All exits precede all enters, volume ascending then watch insertion order. Removing/unwatching fires exits in watch/volume order only when ctx is supplied.
Example
ts
import { createTriggers, type Triggers } from 'gameable';
const zones: Triggers = createTriggers({ capacity: 4, watchCapacity: 8 });
zones.addSphere(0, 0, 0, 2);Extends
Methods
addBox()
ts
addBox(
minX,
minY,
minZ,
maxX,
maxY,
maxZ
): number;Add inclusive bounds, returning the first free volume index.
Parameters
| Parameter | Type |
|---|---|
minX | number |
minY | number |
minZ | number |
maxX | number |
maxY | number |
maxZ | number |
Returns
number
addSphere()
ts
addSphere(
x,
y,
z,
radius
): number;Add an inclusive sphere; radius must be nonnegative.
Parameters
| Parameter | Type |
|---|---|
x | number |
y | number |
z | number |
radius | number |
Returns
number
count()
ts
count(volume): number;Number of watched entities last observed inside.
Parameters
| Parameter | Type |
|---|---|
volume | number |
Returns
number
enable()
ts
enable(volume, on): void;Disable/enable; exits from disabling are reported next step.
Parameters
| Parameter | Type |
|---|---|
volume | number |
on | boolean |
Returns
void
inside()
ts
inside(volume, entity): boolean;Last observed containment, including pending disabled-volume exits.
Parameters
| Parameter | Type |
|---|---|
volume | number |
entity | number |
Returns
boolean
moveTo()
ts
moveTo(
volume,
x,
y,
z
): void;Recenter a volume, preserving its size.
Parameters
| Parameter | Type |
|---|---|
volume | number |
x | number |
y | number |
z | number |
Returns
void
remove()
ts
remove(volume, ctx?): void;Free a volume, optionally reporting its exits in watch order.
Parameters
| Parameter | Type |
|---|---|
volume | number |
ctx? | GameContext |
Returns
void
reset()
ts
reset(): void;Back to the state right after creation. Call from init.
Returns
void
Inherited from
restore()
ts
restore(state, options?): void;Read back what snapshot returned. Throws on a malformed state.
Parameters
| Parameter | Type |
|---|---|
state | unknown |
options? | { crossBuild?: boolean; } |
options.crossBuild? | boolean |
Returns
void
Inherited from
snapshot()
ts
snapshot(): unknown;Plain JSON-safe data for defineGame({ snapshot }).
Returns
unknown
Inherited from
step()
ts
step(ctx): void;Test geometry, emit all exits then enters, and auto-unwatch deleted entities.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
unwatch()
ts
unwatch(entity, ctx?): void;Remove a watch, preserving the other watches' order.
Parameters
| Parameter | Type |
|---|---|
entity | number |
ctx? | GameContext |
Returns
void
watch()
ts
watch(entity): void;Watch once, in insertion order. Throws if full.
Parameters
| Parameter | Type |
|---|---|
entity | number |
Returns
void
Turns
Ascending seat order with phases and a fixed-step turn clock. A sole active seat passes back to itself and increments the round; no active seats leaves current() at -1. Reviving a seat does not start a stopped game: call start. Events are synchronous: round (when crossed), turn, phase; timeout precedes these. Skips are consumed once, in ascending traversal order. Eliminating the current seat ends its turn immediately using the ctx supplied to eliminate. No game context is retained between calls.
Example
ts
import { createTurns, type Turns } from 'gameable';
const turns: Turns = createTurns({ seats: 2, phases: ['draw', 'act'] });
turns.reset();Extends
Methods
active()
ts
active(seat): boolean;Whether this seat has not been eliminated.
Parameters
| Parameter | Type |
|---|---|
seat | number |
Returns
boolean
current()
ts
current(): number;Current seat, or -1 when none is taking a turn.
Returns
number
elapse()
ts
elapse(ctx, seconds): number;Consume sleeping wall time as steps; at most seats * 1000 timeouts, then restart the clock in full.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
seconds | number |
Returns
number
eliminate()
ts
eliminate(ctx, seat): void;Eliminate a seat, immediately ending its current turn with callbacks using ctx.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
seat | number |
Returns
void
endTurn()
ts
endTurn(ctx): void;Pass to the next eligible seat.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
isTurn()
ts
isTurn(seat): boolean;True if this active seat owns the current turn.
Parameters
| Parameter | Type |
|---|---|
seat | number |
Returns
boolean
nextPhase()
ts
nextPhase(ctx): void;Advance phase, ending the turn after the final phase.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
phase()
ts
phase(): number;Current phase index, or -1 when no turn is active.
Returns
number
phaseId()
ts
phaseId(): string;Current phase id, or the empty string when no turn is active.
Returns
string
remainingSeconds()
ts
remainingSeconds(): number;Remaining whole steps multiplied by the dt captured when this turn began.
Returns
number
reset()
ts
reset(): void;Back to the state right after creation. Call from init.
Returns
void
Inherited from
restore()
ts
restore(state, options?): void;Read back what snapshot returned. Throws on a malformed state.
Parameters
| Parameter | Type |
|---|---|
state | unknown |
options? | { crossBuild?: boolean; } |
options.crossBuild? | boolean |
Returns
void
Inherited from
revive()
ts
revive(seat): void;Make a seat eligible again.
Parameters
| Parameter | Type |
|---|---|
seat | number |
Returns
void
round()
ts
round(): number;Round number; zero before start.
Returns
number
skipNext()
ts
skipNext(seat): void;Skip the seat's next turn; repeated calls do not stack.
Parameters
| Parameter | Type |
|---|---|
seat | number |
Returns
void
snapshot()
ts
snapshot(): unknown;Plain JSON-safe data for defineGame({ snapshot }).
Returns
unknown
Inherited from
start()
ts
start(ctx, firstSeat?): void;Begin round one, preserving eliminated seats and pending skips.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
firstSeat? | number |
Returns
void
step()
ts
step(ctx): void;Count one step; timeout, then endTurn when the clock reaches zero.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
Tweens
Preallocated numeric lane animations. Reset clears animations, leaving lanes intact.
Example
ts
import { createTweens, type Tweens } from 'gameable';
const tweens: Tweens = createTweens({ capacity: 8 });
tweens.reset();Extends
Methods
active()
ts
active(tween): boolean;Whether a slot is running. Invalid slots throw RangeError.
Parameters
| Parameter | Type |
|---|---|
tween | number |
Returns
boolean
reset()
ts
reset(): void;Back to the state right after creation. Call from init.
Returns
void
Inherited from
restore()
ts
restore(state, options?): void;Read back what snapshot returned. Throws on a malformed state.
Parameters
| Parameter | Type |
|---|---|
state | unknown |
options? | { crossBuild?: boolean; } |
options.crossBuild? | boolean |
Returns
void
Inherited from
snapshot()
ts
snapshot(): unknown;Plain JSON-safe data for defineGame({ snapshot }).
Returns
unknown
Inherited from
start()
ts
start(
ctx,
lane,
index,
to,
seconds,
easing?,
options?
): number;Start at the current value or explicit from; replace the same target without onDone. A Transform-lane tween must be stepped inside a game system.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
lane | Float32Array |
index | number |
to | number |
seconds | number |
easing? | | "linear" | "quadIn" | "quadOut" | "quadInOut" | "cubicIn" | "cubicOut" | "cubicInOut" | "sineIn" | "sineOut" | "sineInOut" | "backOut" | "elasticOut" | "bounceOut" |
options? | { from?: number; loop?: "none" | "repeat" | "yoyo"; } |
options.from? | number |
options.loop? | "none" | "repeat" | "yoyo" |
Returns
number
step()
ts
step(ctx): void;Advance all slots, then call onDone synchronously in ascending slot order. Transform-lane tweens must be stepped inside a game system with a running guest.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
stop()
ts
stop(tween): void;Free one slot without onDone. Invalid slots throw RangeError.
Parameters
| Parameter | Type |
|---|---|
tween | number |
Returns
void
stopAll()
ts
stopAll(lane?, index?): void;Stop all, all on a lane, or one index on a lane.
Parameters
| Parameter | Type |
|---|---|
lane? | Float32Array<ArrayBufferLike> |
index? | number |
Returns
void
UiBar
A progress meter: health, a timer, loading.
Example
ts
import type { UiBar } from 'gameable';
const example: UiBar = { type: 'bar', value: 80, max: 100 };
console.log(example);Extends
Properties
anchor?
ts
optional anchor?: UiScreenAnchor | UiWorldAnchor;Top-level nodes only: where it sits. Defaults to center.
Inherited from
draggable?
ts
optional draggable?: boolean;This node can be picked up and dropped on a dropTarget. Needs an id.
Inherited from
dropTarget?
ts
optional dropTarget?: boolean;Draggables can be dropped here. Needs an id.
Inherited from
grow?
ts
optional grow?: boolean;Take the remaining space in the parent stack.
Inherited from
height?
ts
optional height?: number;Fixed height, CSS px.
Inherited from
hidden?
ts
optional hidden?: boolean;Leave the node out without removing it from the tree.
Inherited from
id?
ts
optional id?: string;The node's name. Required for anything that sends events (a button, a clickable card, a draggable, a drop target, an input), and it keeps a node's DOM (focus, scroll, a drag in progress) across ui.set calls. Unique within one model.
Inherited from
label?
ts
optional label?: string;A label above the track.
max
ts
max: number;modal?
ts
optional modal?: boolean;Top-level nodes only: dim the game behind it and take every pointer event.
Inherited from
offset?
ts
optional offset?: readonly [number, number];Top-level nodes only: extra shift from the anchor, CSS px [x, y].
Inherited from
padding?
ts
optional padding?: number;Inner padding, CSS px.
Inherited from
tone?
ts
optional tone?: "accent" | "danger";Defaults to accent; turns pink at or below a third unless tone is set.
type
ts
type: "bar";value
ts
value: number;width?
ts
optional width?: number;Fixed width, CSS px.
Inherited from
UiButton
A pressable button. Sends click, focus and blur.
Example
ts
import type { UiButton } from 'gameable';
const example: UiButton = { type: 'button', id: 'play', text: 'Play' };
console.log(example);Extends
Properties
anchor?
ts
optional anchor?: UiScreenAnchor | UiWorldAnchor;Top-level nodes only: where it sits. Defaults to center.
Inherited from
disabled?
ts
optional disabled?: boolean;draggable?
ts
optional draggable?: boolean;This node can be picked up and dropped on a dropTarget. Needs an id.
Inherited from
dropTarget?
ts
optional dropTarget?: boolean;Draggables can be dropped here. Needs an id.
Inherited from
grow?
ts
optional grow?: boolean;Take the remaining space in the parent stack.
Inherited from
height?
ts
optional height?: number;Fixed height, CSS px.
Inherited from
hidden?
ts
optional hidden?: boolean;Leave the node out without removing it from the tree.
Inherited from
id
ts
id: string;The node's name. Required for anything that sends events (a button, a clickable card, a draggable, a drop target, an input), and it keeps a node's DOM (focus, scroll, a drag in progress) across ui.set calls. Unique within one model.
Overrides
modal?
ts
optional modal?: boolean;Top-level nodes only: dim the game behind it and take every pointer event.
Inherited from
offset?
ts
optional offset?: readonly [number, number];Top-level nodes only: extra shift from the anchor, CSS px [x, y].
Inherited from
padding?
ts
optional padding?: number;Inner padding, CSS px.
Inherited from
selected?
ts
optional selected?: boolean;Drawn as chosen (mint ring), e.g. the picked answer.
text
ts
text: string;type
ts
type: "button";variant?
ts
optional variant?: "ghost" | "danger" | "primary" | "secondary";Defaults to secondary. primary is the mint call to action.
width?
ts
optional width?: number;Fixed width, CSS px.
Inherited from
UiCard
A card: a surface with an optional title and body, or children. With an id it is clickable; with draggable it can be picked up.
Example
ts
import type { UiCard } from 'gameable';
const example: UiCard = { type: 'card', title: 'Ace', draggable: true, id: 'ace' };
console.log(example);Extends
Properties
align?
ts
optional align?: "end" | "start" | "center" | "stretch";Cross-axis alignment. Defaults to stretch.
Inherited from
anchor?
ts
optional anchor?: UiScreenAnchor | UiWorldAnchor;Top-level nodes only: where it sits. Defaults to center.
Inherited from
body?
ts
optional body?: string;children?
ts
optional children?: readonly UiNode[];direction?
ts
optional direction?: "row" | "column";Main axis. Defaults to column.
Inherited from
disabled?
ts
optional disabled?: boolean;draggable?
ts
optional draggable?: boolean;This node can be picked up and dropped on a dropTarget. Needs an id.
Inherited from
dropTarget?
ts
optional dropTarget?: boolean;Draggables can be dropped here. Needs an id.
Inherited from
gap?
ts
optional gap?: number;Space between children, CSS px. Defaults to the theme's gap.
Inherited from
grow?
ts
optional grow?: boolean;Take the remaining space in the parent stack.
Inherited from
height?
ts
optional height?: number;Fixed height, CSS px.
Inherited from
hidden?
ts
optional hidden?: boolean;Leave the node out without removing it from the tree.
Inherited from
id?
ts
optional id?: string;The node's name. Required for anything that sends events (a button, a clickable card, a draggable, a drop target, an input), and it keeps a node's DOM (focus, scroll, a drag in progress) across ui.set calls. Unique within one model.
Inherited from
justify?
ts
optional justify?: "end" | "start" | "center" | "between";Main-axis distribution. Defaults to start.
Inherited from
modal?
ts
optional modal?: boolean;Top-level nodes only: dim the game behind it and take every pointer event.
Inherited from
offset?
ts
optional offset?: readonly [number, number];Top-level nodes only: extra shift from the anchor, CSS px [x, y].
Inherited from
padding?
ts
optional padding?: number;Inner padding, CSS px.
Inherited from
selected?
ts
optional selected?: boolean;title?
ts
optional title?: string;tone?
ts
optional tone?: "default" | "accent" | "danger";Tint the card: accent mint, danger pink.
type
ts
type: "card";width?
ts
optional width?: number;Fixed width, CSS px.
Inherited from
wrap?
ts
optional wrap?: boolean;Wrap onto more lines when the row is full.
Inherited from
UiEvent
One UI event, as the guest receives it. Mirrors WIT ui-event.
Example
ts
import type { UiEvent } from 'gameable';
const example: UiEvent = { kind: 'click', id: 'play', target: '', value: '', x: 0, y: 0 };
console.log(example);Properties
id
ts
id: string;The node's id: the button clicked, the card dragged, the input edited.
kind
ts
kind: UiEventKind;target
ts
target: string;For drop: the drop target's id. Empty otherwise.
value
ts
value: string;For change and submit: the field's text. Empty otherwise.
x
ts
x: number;Pointer position, CSS px from the game view's top-left; 0 for keyboard.
y
ts
y: number;Pointer position, CSS px from the game view's top-left; 0 for keyboard.
UiGrid
A grid of equal columns, filled row by row.
Example
ts
import type { UiGrid } from 'gameable';
const example: UiGrid = { type: 'grid', columns: 2, children: [] };
console.log(example);Extends
Properties
anchor?
ts
optional anchor?: UiScreenAnchor | UiWorldAnchor;Top-level nodes only: where it sits. Defaults to center.
Inherited from
children
ts
children: readonly UiNode[];columns
ts
columns: number;Number of columns.
draggable?
ts
optional draggable?: boolean;This node can be picked up and dropped on a dropTarget. Needs an id.
Inherited from
dropTarget?
ts
optional dropTarget?: boolean;Draggables can be dropped here. Needs an id.
Inherited from
gap?
ts
optional gap?: number;Space between cells, CSS px.
grow?
ts
optional grow?: boolean;Take the remaining space in the parent stack.
Inherited from
height?
ts
optional height?: number;Fixed height, CSS px.
Inherited from
hidden?
ts
optional hidden?: boolean;Leave the node out without removing it from the tree.
Inherited from
id?
ts
optional id?: string;The node's name. Required for anything that sends events (a button, a clickable card, a draggable, a drop target, an input), and it keeps a node's DOM (focus, scroll, a drag in progress) across ui.set calls. Unique within one model.
Inherited from
modal?
ts
optional modal?: boolean;Top-level nodes only: dim the game behind it and take every pointer event.
Inherited from
offset?
ts
optional offset?: readonly [number, number];Top-level nodes only: extra shift from the anchor, CSS px [x, y].
Inherited from
padding?
ts
optional padding?: number;Inner padding, CSS px.
Inherited from
type
ts
type: "grid";width?
ts
optional width?: number;Fixed width, CSS px.
Inherited from
UiInput
A one-line text field. Sends change on every edit and submit on Enter.
Example
ts
import type { UiInput } from 'gameable';
const example: UiInput = { type: 'input', id: 'name', placeholder: 'Your name' };
console.log(example);Extends
Properties
anchor?
ts
optional anchor?: UiScreenAnchor | UiWorldAnchor;Top-level nodes only: where it sits. Defaults to center.
Inherited from
draggable?
ts
optional draggable?: boolean;This node can be picked up and dropped on a dropTarget. Needs an id.
Inherited from
dropTarget?
ts
optional dropTarget?: boolean;Draggables can be dropped here. Needs an id.
Inherited from
grow?
ts
optional grow?: boolean;Take the remaining space in the parent stack.
Inherited from
height?
ts
optional height?: number;Fixed height, CSS px.
Inherited from
hidden?
ts
optional hidden?: boolean;Leave the node out without removing it from the tree.
Inherited from
id
ts
id: string;The node's name. Required for anything that sends events (a button, a clickable card, a draggable, a drop target, an input), and it keeps a node's DOM (focus, scroll, a drag in progress) across ui.set calls. Unique within one model.
Overrides
maxLength?
ts
optional maxLength?: number;modal?
ts
optional modal?: boolean;Top-level nodes only: dim the game behind it and take every pointer event.
Inherited from
offset?
ts
optional offset?: readonly [number, number];Top-level nodes only: extra shift from the anchor, CSS px [x, y].
Inherited from
padding?
ts
optional padding?: number;Inner padding, CSS px.
Inherited from
placeholder?
ts
optional placeholder?: string;Shown until the player types; the field keeps what they type.
type
ts
type: "input";value?
ts
optional value?: string;Replace what is in the field. Leave it unset to keep what the player typed.
width?
ts
optional width?: number;Fixed width, CSS px.
Inherited from
UiLayout
How children of a container are laid out.
Example
ts
import type { UiLayout } from 'gameable';
const example: UiLayout = { direction: 'row', gap: 8 };
console.log(example);Extended by
Properties
align?
ts
optional align?: "end" | "start" | "center" | "stretch";Cross-axis alignment. Defaults to stretch.
direction?
ts
optional direction?: "row" | "column";Main axis. Defaults to column.
gap?
ts
optional gap?: number;Space between children, CSS px. Defaults to the theme's gap.
justify?
ts
optional justify?: "end" | "start" | "center" | "between";Main-axis distribution. Defaults to start.
wrap?
ts
optional wrap?: boolean;Wrap onto more lines when the row is full.
UiList
A vertical scrolling list.
Example
ts
import type { UiList } from 'gameable';
const example: UiList = { type: 'list', children: [], maxHeight: 300 };
console.log(example);Extends
Properties
anchor?
ts
optional anchor?: UiScreenAnchor | UiWorldAnchor;Top-level nodes only: where it sits. Defaults to center.
Inherited from
children
ts
children: readonly UiNode[];draggable?
ts
optional draggable?: boolean;This node can be picked up and dropped on a dropTarget. Needs an id.
Inherited from
dropTarget?
ts
optional dropTarget?: boolean;Draggables can be dropped here. Needs an id.
Inherited from
gap?
ts
optional gap?: number;grow?
ts
optional grow?: boolean;Take the remaining space in the parent stack.
Inherited from
height?
ts
optional height?: number;Fixed height, CSS px.
Inherited from
hidden?
ts
optional hidden?: boolean;Leave the node out without removing it from the tree.
Inherited from
id?
ts
optional id?: string;The node's name. Required for anything that sends events (a button, a clickable card, a draggable, a drop target, an input), and it keeps a node's DOM (focus, scroll, a drag in progress) across ui.set calls. Unique within one model.
Inherited from
maxHeight?
ts
optional maxHeight?: number;Scroll past this height, CSS px.
modal?
ts
optional modal?: boolean;Top-level nodes only: dim the game behind it and take every pointer event.
Inherited from
offset?
ts
optional offset?: readonly [number, number];Top-level nodes only: extra shift from the anchor, CSS px [x, y].
Inherited from
padding?
ts
optional padding?: number;Inner padding, CSS px.
Inherited from
type
ts
type: "list";width?
ts
optional width?: number;Fixed width, CSS px.
Inherited from
UiModel
What frame-output.ui carries, as JSON.
Example
ts
import type { UiModel } from 'gameable';
const example: UiModel = { nodes: [{ type: 'text', text: 'Ready' }] };
console.log(example);Properties
nodes
ts
nodes: readonly UiNode[];Top-level nodes, drawn in order (later on top).
theme?
ts
optional theme?: UiTheme;UiNodeBase
Fields every node may carry.
Example
ts
import type { UiNodeBase } from 'gameable';
const example: UiNodeBase = { id: 'menu', anchor: 'center' };
console.log(example);Extended by
Properties
anchor?
ts
optional anchor?: UiScreenAnchor | UiWorldAnchor;Top-level nodes only: where it sits. Defaults to center.
draggable?
ts
optional draggable?: boolean;This node can be picked up and dropped on a dropTarget. Needs an id.
dropTarget?
ts
optional dropTarget?: boolean;Draggables can be dropped here. Needs an id.
grow?
ts
optional grow?: boolean;Take the remaining space in the parent stack.
height?
ts
optional height?: number;Fixed height, CSS px.
hidden?
ts
optional hidden?: boolean;Leave the node out without removing it from the tree.
id?
ts
optional id?: string;The node's name. Required for anything that sends events (a button, a clickable card, a draggable, a drop target, an input), and it keeps a node's DOM (focus, scroll, a drag in progress) across ui.set calls. Unique within one model.
modal?
ts
optional modal?: boolean;Top-level nodes only: dim the game behind it and take every pointer event.
offset?
ts
optional offset?: readonly [number, number];Top-level nodes only: extra shift from the anchor, CSS px [x, y].
padding?
ts
optional padding?: number;Inner padding, CSS px.
width?
ts
optional width?: number;Fixed width, CSS px.
UiPanel
A surface (glass card) holding a stack: menus, dialogs, side panels.
Example
ts
import type { UiPanel } from 'gameable';
const example: UiPanel = { type: 'panel', title: 'Menu', children: [] };
console.log(example);Extends
Properties
align?
ts
optional align?: "end" | "start" | "center" | "stretch";Cross-axis alignment. Defaults to stretch.
Inherited from
anchor?
ts
optional anchor?: UiScreenAnchor | UiWorldAnchor;Top-level nodes only: where it sits. Defaults to center.
Inherited from
children?
ts
optional children?: readonly UiNode[];direction?
ts
optional direction?: "row" | "column";Main axis. Defaults to column.
Inherited from
draggable?
ts
optional draggable?: boolean;This node can be picked up and dropped on a dropTarget. Needs an id.
Inherited from
dropTarget?
ts
optional dropTarget?: boolean;Draggables can be dropped here. Needs an id.
Inherited from
gap?
ts
optional gap?: number;Space between children, CSS px. Defaults to the theme's gap.
Inherited from
grow?
ts
optional grow?: boolean;Take the remaining space in the parent stack.
Inherited from
height?
ts
optional height?: number;Fixed height, CSS px.
Inherited from
hidden?
ts
optional hidden?: boolean;Leave the node out without removing it from the tree.
Inherited from
id?
ts
optional id?: string;The node's name. Required for anything that sends events (a button, a clickable card, a draggable, a drop target, an input), and it keeps a node's DOM (focus, scroll, a drag in progress) across ui.set calls. Unique within one model.
Inherited from
justify?
ts
optional justify?: "end" | "start" | "center" | "between";Main-axis distribution. Defaults to start.
Inherited from
modal?
ts
optional modal?: boolean;Top-level nodes only: dim the game behind it and take every pointer event.
Inherited from
offset?
ts
optional offset?: readonly [number, number];Top-level nodes only: extra shift from the anchor, CSS px [x, y].
Inherited from
padding?
ts
optional padding?: number;Inner padding, CSS px.
Inherited from
title?
ts
optional title?: string;A title line at the top.
type
ts
type: "panel";width?
ts
optional width?: number;Fixed width, CSS px.
Inherited from
wrap?
ts
optional wrap?: boolean;Wrap onto more lines when the row is full.
Inherited from
UiStack
A transparent stack of children: the basic layout box.
Example
ts
import type { UiStack } from 'gameable';
const example: UiStack = { type: 'stack', children: [] };
console.log(example);Extends
Properties
align?
ts
optional align?: "end" | "start" | "center" | "stretch";Cross-axis alignment. Defaults to stretch.
Inherited from
anchor?
ts
optional anchor?: UiScreenAnchor | UiWorldAnchor;Top-level nodes only: where it sits. Defaults to center.
Inherited from
children
ts
children: readonly UiNode[];direction?
ts
optional direction?: "row" | "column";Main axis. Defaults to column.
Inherited from
draggable?
ts
optional draggable?: boolean;This node can be picked up and dropped on a dropTarget. Needs an id.
Inherited from
dropTarget?
ts
optional dropTarget?: boolean;Draggables can be dropped here. Needs an id.
Inherited from
gap?
ts
optional gap?: number;Space between children, CSS px. Defaults to the theme's gap.
Inherited from
grow?
ts
optional grow?: boolean;Take the remaining space in the parent stack.
Inherited from
height?
ts
optional height?: number;Fixed height, CSS px.
Inherited from
hidden?
ts
optional hidden?: boolean;Leave the node out without removing it from the tree.
Inherited from
id?
ts
optional id?: string;The node's name. Required for anything that sends events (a button, a clickable card, a draggable, a drop target, an input), and it keeps a node's DOM (focus, scroll, a drag in progress) across ui.set calls. Unique within one model.
Inherited from
justify?
ts
optional justify?: "end" | "start" | "center" | "between";Main-axis distribution. Defaults to start.
Inherited from
modal?
ts
optional modal?: boolean;Top-level nodes only: dim the game behind it and take every pointer event.
Inherited from
offset?
ts
optional offset?: readonly [number, number];Top-level nodes only: extra shift from the anchor, CSS px [x, y].
Inherited from
padding?
ts
optional padding?: number;Inner padding, CSS px.
Inherited from
type
ts
type: "stack";width?
ts
optional width?: number;Fixed width, CSS px.
Inherited from
wrap?
ts
optional wrap?: boolean;Wrap onto more lines when the row is full.
Inherited from
UiText
A line or paragraph of text.
Example
ts
import type { UiText } from 'gameable';
const example: UiText = { type: 'text', text: 'Ready' };
console.log(example);Extends
Properties
align?
ts
optional align?: "end" | "start" | "center";anchor?
ts
optional anchor?: UiScreenAnchor | UiWorldAnchor;Top-level nodes only: where it sits. Defaults to center.
Inherited from
draggable?
ts
optional draggable?: boolean;This node can be picked up and dropped on a dropTarget. Needs an id.
Inherited from
dropTarget?
ts
optional dropTarget?: boolean;Draggables can be dropped here. Needs an id.
Inherited from
grow?
ts
optional grow?: boolean;Take the remaining space in the parent stack.
Inherited from
height?
ts
optional height?: number;Fixed height, CSS px.
Inherited from
hidden?
ts
optional hidden?: boolean;Leave the node out without removing it from the tree.
Inherited from
id?
ts
optional id?: string;The node's name. Required for anything that sends events (a button, a clickable card, a draggable, a drop target, an input), and it keeps a node's DOM (focus, scroll, a drag in progress) across ui.set calls. Unique within one model.
Inherited from
modal?
ts
optional modal?: boolean;Top-level nodes only: dim the game behind it and take every pointer event.
Inherited from
offset?
ts
optional offset?: readonly [number, number];Top-level nodes only: extra shift from the anchor, CSS px [x, y].
Inherited from
padding?
ts
optional padding?: number;Inner padding, CSS px.
Inherited from
size?
ts
optional size?: "display" | "sm" | "md" | "lg" | "xl";Defaults to md. display is the big centred "You win" size.
text
ts
text: string | number;tone?
ts
optional tone?: "default" | "muted" | "accent" | "danger";Defaults to default. accent is mint, danger is pink.
type
ts
type: "text";width?
ts
optional width?: number;Fixed width, CSS px.
Inherited from
UiTheme
Theme tokens. Every field is optional; what is left out is the Gameable look (STYLE.md). Colours are CSS colour strings.
Example
ts
import type { UiTheme } from 'gameable';
const example: UiTheme = { scale: 1.2, gap: 8 };
console.log(example);Properties
accent?
ts
optional accent?: string;The accent: primary buttons, selection, progress.
backdrop?
ts
optional backdrop?: string;Behind a modal.
border?
ts
optional border?: string;Hairlines and borders.
danger?
ts
optional danger?: string;Errors, danger buttons, low bars, the focus ring.
font?
ts
optional font?: string;CSS font-family.
gap?
ts
optional gap?: number;Default gap between children, CSS px.
muted?
ts
optional muted?: string;Secondary text, labels.
onAccent?
ts
optional onAccent?: string;Text on an accent background.
radius?
ts
optional radius?: number;Card and panel corner radius, CSS px.
scale?
ts
optional scale?: number;Multiplies every size; 1 is the default.
surface?
ts
optional surface?: string;Panels and cards.
surfaceRaised?
ts
optional surfaceRaised?: string;Secondary buttons, tracks, inputs.
text?
ts
optional text?: string;Primary text.
UiWorldAnchor
Pin a top-level node to a point in the 3D world: over an entity, or at a fixed position. The node's bottom-centre sits on the projected point, and it hides while the point is behind the camera.
Example
ts
import type { UiWorldAnchor } from 'gameable';
const example: UiWorldAnchor = { entity: 1, offset: [0, 2, 0] };
console.log(example);Properties
entity?
ts
optional entity?: number;Follow this entity's position.
offset?
ts
optional offset?: readonly [number, number, number];Added to the point before projecting, world metres (e.g. [0, 2, 0] above a head).
position?
ts
optional position?: readonly [number, number, number];A fixed world position, metres. Ignored when entity is set.
ValidateLevelOptions
What validateLevel takes besides the document.
Extended by
Properties
catalog?
ts
optional catalog?: ReadonlyMap<string, ActorClass<object>>;Detached declarations for static tools; bypasses the live registry and deprecation logging.
classes?
ts
optional classes?: readonly string[] | "any";The game's own classes (defineActor in its source), for a reader that has not loaded the game's module, such as a tool on Node: a listed class passes as known, with its props unchecked. 'any' accepts every well-formed class name; prefer the list when the names are at hand.
Vec3
A 3-component vector.
Extended by
Properties
x
ts
x: number;y
ts
y: number;z
ts
z: number;VehicleBindings
Key bindings saved with the controller. Set controller.state.frozen or pawn.state.frozen to park.
Example
ts
bindVehicleInput(controller, { brake: 'Control' });Properties
brake?
ts
optional brake?: string;forward?
ts
optional forward?: string;handbrake?
ts
optional handbrake?: string;left?
ts
optional left?: string;reverse?
ts
optional reverse?: string;right?
ts
optional right?: string;VehicleGripVolumeProps
Spherical oil area lifetime and tyre recovery, in seconds.
Example
ts
const props: VehicleGripVolumeProps = { radius: 3, duration: 8, gripScale: 0.15, recovery: 1 };Properties
duration
ts
duration: number;gripScale
ts
gripScale: number;radius
ts
radius: number;recovery
ts
recovery: number;VehicleInput
Normalized control intent; throttle/steer [-1,1], brakes [0,1].
Example
ts
const input: VehicleInput = { throttle: 1, steer: 0, brake: 0, handbrake: 0 };Properties
brake
ts
brake: number;handbrake
ts
handbrake: number;steer
ts
steer: number;throttle
ts
throttle: number;VehicleSettings
SI settings; steerAngle is degrees and steerRate degrees/second. Curves map absolute speed (m/s) and dimensionless slip to multipliers. downforce is N/(m/s)^2; uprightAssist is maximum N m; airControl is [0,1]. antiRoll is the host axle load transfer stiffness in N/m.
Example
ts
import { physics, type VehicleSettings } from 'gameable';
function attach(body: number, settings: VehicleSettings): void {
physics.vehicle.create(body, settings);
}Properties
acceleration
ts
acceleration: number;airControl
ts
airControl: number;antiRoll
ts
antiRoll: number;brakeDeceleration
ts
brakeDeceleration: number;downforce
ts
downforce: number;driftRecovery
ts
driftRecovery: number;gripBySlip
ts
gripBySlip: VehicleCurve;halfExtents
ts
halfExtents: readonly [number, number, number];mass
ts
mass: number;maxSpeed
ts
maxSpeed: number;rearHandbrakeGrip
ts
rearHandbrakeGrip: number;reverseAsBrake
ts
reverseAsBrake: boolean;reverseSpeed
ts
reverseSpeed: number;rollingDrag
ts
rollingDrag: number;steerAngle
ts
steerAngle: number;steeringBySpeed
ts
steeringBySpeed: VehicleCurve;steerRate
ts
steerRate: number;uprightAssist
ts
uprightAssist: number;wheels
ts
wheels: readonly [VehicleWheel, VehicleWheel, VehicleWheel, VehicleWheel];VehicleState
Borrowed mutable state; speed is signed m/s, steer is radians. supportBits uses bits 0..3 in settings wheel order.
Example
ts
const state: VehicleState = { speed: 0, supportBits: 0, steer: 0,
reversing: false, braking: false, wheels: Array.from({ length: 4 },
() => ({ compression: 0, spin: 0, slip: 0, grip: 1 })) };Properties
braking
ts
braking: boolean;reversing
ts
reversing: boolean;speed
ts
speed: number;steer
ts
steer: number;supportBits
ts
supportBits: number;wheels
ts
wheels: VehicleWheelState[];VehicleWheel
Wheel geometry in metres, frequency in Hz, and dimensionless damping. Mount coordinates use chassis-local axes; handbrake marks the rear axle.
Example
ts
const wheel: VehicleWheel = { mount: [-0.8, 0, 1.3], radius: 0.34,
restLength: 0.4, travel: 0.3, springHz: 2, dampingRatio: 0.8,
steer: true, driven: true, handbrake: false };Properties
dampingRatio
ts
dampingRatio: number;driven
ts
driven: boolean;handbrake
ts
handbrake: boolean;mount
ts
mount: readonly [number, number, number];radius
ts
radius: number;restLength
ts
restLength: number;springHz
ts
springHz: number;steer
ts
steer: boolean;travel
ts
travel: number;VehicleWheelState
Persistent wheel telemetry and grip recovery history; spin is radians.
Example
ts
const wheel: VehicleWheelState = { compression: 0, spin: 0, slip: 0, grip: 1 };Properties
compression
ts
compression: number;grip
ts
grip: number;slip
ts
slip: number;spin
ts
spin: number;VelocityStore
Linear and angular velocity in metres and radians per second.
Properties
ax
ts
ax: Float32Array;ay
ts
ay: Float32Array;az
ts
az: Float32Array;x
ts
x: Float32Array;y
ts
y: Float32Array;z
ts
z: Float32Array;VfxOptions
Options for particle effects and the page's base look.
Example
ts
import type { VfxOptions } from 'gameable';
const options: VfxOptions = { post: { bloom: 0.5 } };Properties
post?
ts
optional post?: PostSettings;Base look applied before the guest runs, also received by late joiners.
Viewport
View dimensions in the screen point's units.
Example
ts
const view: Viewport = { width: 800, height: 600 };Properties
height
ts
height: number;width
ts
width: number;WalkCharacterToCmd
Walk a character to a spot (see character.walkTo).
Properties
entity
ts
entity: number;facing?
ts
optional facing?: number;The facing to arrive with, radians about +Y (0 faces +Z); absent: as it arrives.
pace
ts
pace: number;Metres a second; 0 is the set's own walk.
quick
ts
quick: boolean;The shortest stops and turns the set has, instead of unhurried ones.
start?
ts
optional start?: "moving";How it is begun: 'moving', the game says the body is under way already. Absent: as the character's takes have the body, as ever.
stop?
ts
optional stop?: StopStyle;Which kind of stop this one walk ends with: 'gradual' (it slows and stands upright) or 'hard' (it brakes). Absent: the character's own; a quick walk that states none stops as a quick walk always did.
target
ts
target: Vec3;The spot, world space, on the floor.
WalkJumpModule
Walking system and declarative player configuration.
Example
ts
import type { WalkJumpModule } from 'gameable';
const inspect = (walk: WalkJumpModule) => walk.player.camera;
console.log(inspect);Extends
Properties
init
ts
init: (ctx) => void;Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
Inherited from
player
ts
readonly player: PlayerSpec;system
ts
system: (ctx) => void;Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
Inherited from
WalkJumpModuleOptions
Existing third-person controls with an invisible prediction capsule.
Example
ts
import type { WalkJumpModuleOptions } from 'gameable';
const inspect = (options: WalkJumpModuleOptions) => options.walkSpeed;
console.log(inspect);Properties
body
ts
body: BodySpec;camera
ts
camera: object;camera
ts
camera: "thirdPerson";distance
ts
distance: number;height
ts
height: number;sensitivity
ts
sensitivity: number;cameraMaxPitch
ts
cameraMaxPitch: number;cameraMinPitch
ts
cameraMinPitch: number;cameraPitch
ts
cameraPitch: number;characters
ts
characters: readonly string[];jumpSpeed
ts
jumpSpeed: number;prediction
ts
prediction: "own-body";runSpeed
ts
runSpeed: number;scheme
ts
scheme: "third-person";spawns
ts
spawns: readonly readonly number[][];walkSpeed
ts
walkSpeed: number;Waves
Timed waves. A zero delay spawns on the first step; positive delays and intervals count whole steps. Capacity holds the clock, including the delay. Clear fires on the step observing no survivors after all attempts; the next wave starts on the following step. Spawn indices ascend from zero, including failed spawns. stop discards tracking without despawning entities or events.
Example
ts
import { createWaves, type Waves } from 'gameable';
const waves: Waves = createWaves({ waves: [{ count: 3, every: 1 }], onSpawn: () => 0 });
waves.reset();Extends
Methods
alive()
ts
alive(): number;Number of tracked surviving entities.
Returns
number
finished()
ts
finished(): boolean;True only after the final clear, until reset/start/stop.
Returns
boolean
killed()
ts
killed(entity): boolean;Remove a tracked nonzero entity; returns whether found.
Parameters
| Parameter | Type |
|---|---|
entity | number |
Returns
boolean
reset()
ts
reset(): void;Back to the state right after creation. Call from init.
Returns
void
Inherited from
restore()
ts
restore(state, options?): void;Read back what snapshot returned. Throws on a malformed state.
Parameters
| Parameter | Type |
|---|---|
state | unknown |
options? | { crossBuild?: boolean; } |
options.crossBuild? | boolean |
Returns
void
Inherited from
snapshot()
ts
snapshot(): unknown;Plain JSON-safe data for defineGame({ snapshot }).
Returns
unknown
Inherited from
spawned()
ts
spawned(): number;Attempts in this wave.
Returns
number
start()
ts
start(ctx): void;Restart at wave zero, discarding previous tracking. Empty lists finish immediately.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
step()
ts
step(ctx): void;Advance one fixed step.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
stop()
ts
stop(): void;Halt and discard tracking without callbacks.
Returns
void
wave()
ts
wave(): number;Current index, or -1 before start and after stop.
Returns
number
WaypointMovementComponent
Reusable path component with per-actor controls.
Example
ts
const movement: WaypointMovementComponent = waypointMovement({ points: [{x: 2,y: 0,z: 0}], speed: 1, mode: 'once' });Extends
Properties
asset?
ts
optional asset?: string;Manifest asset id for a mesh.
Inherited from
attach?
ts
optional attach?: string;Parent component name; defaults to root for non-root components.
Inherited from
body?
ts
optional body?: "static" | "dynamic" | "kinematic";Blocking body motion; defaults to static.
Inherited from
ccd?
ts
optional ccd?: boolean;Continuous collision detection for fast dynamic bodies.
Inherited from
collision?
ts
optional collision?:
| "none"
| "block"
| "Spectator"
| "overlap"
| CollisionSetup
| "NoCollision"
| "BlockAll"
| "OverlapAll"
| "BlockAllDynamic"
| "OverlapAllDynamic"
| "IgnoreOnlyPawn"
| "OverlapOnlyPawn"
| "Pawn"
| "CharacterMesh"
| "PhysicsActor"
| "Destructible"
| "InvisibleWall"
| "InvisibleWallDynamic"
| "Trigger"
| "Ragdoll"
| "Vehicle"
| "UI";Collision response; defaults to block.
Inherited from
dimensions?
ts
optional dimensions?: readonly string[];Spawn-time prop names supplying dimensions: ['halfExtents'] or ['radius', 'halfHeight'].
Inherited from
dims?
ts
optional dims?: readonly number[];Primitive dimensions in metres.
Inherited from
fit?
ts
optional fit?: "mesh" | "box" | "convex-hull";mesh() only: give the mesh a body fitted to its own model, built by the page from the model's geometry and scale once it loads: 'box' its bounds, 'convex-hull' its hull, 'mesh' its triangles (static only).
Inherited from
kind
ts
kind: "mesh" | "character" | "box" | "sphere" | "capsule" | "scene";Component family.
Inherited from
layer?
ts
optional layer?: CollisionLayers;Physics collision layer.
Inherited from
mask?
ts
optional mask?: CollisionLayers;Raw physics mask; cannot accompany a named/custom collision policy.
Inherited from
mass?
ts
optional mass?: number;Dynamic mass in kilograms.
Inherited from
offset?
ts
optional offset?: readonly [number, number, number];Translation in the parent's space.
Inherited from
reportHits?
ts
optional reportHits?: boolean;Request blocking contact callbacks.
Inherited from
rotation?
ts
optional rotation?: Quat;Local quaternion, default identity.
Inherited from
scale?
ts
optional scale?: readonly [number, number, number];Local per-axis scale, default one.
Inherited from
Methods
create()?
ts
optional create(
self,
ctx,
name
): void;Initialize JSON-safe component state during authority spawn.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle |
ctx | GameContext |
name | string |
Returns
void
Inherited from
destroy()?
ts
optional destroy(
self,
ctx,
name
): void;Release component bookkeeping on authority destruction, before entities are despawned.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle |
ctx | GameContext |
name | string |
Returns
void
Inherited from
handle()
ts
handle(actor): WaypointMovementHandle;Parameters
| Parameter | Type |
|---|---|
actor | ActorHandle |
Returns
step()?
ts
optional step(
self,
ctx,
name
): void;Advance on each authority fixed step, before the actor tick.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle |
ctx | GameContext |
name | string |
Returns
void
Inherited from
WaypointMovementHandle
Controls one actor's interpolation, including after snapshot restore.
Example
ts
movement.handle(platform).pause();Methods
pause()
ts
pause(): void;Returns
void
play()
ts
play(): void;Returns
void
reverse()
ts
reverse(): void;Returns
void
WaypointMovementOptions
Relative path configuration. Seconds covers the complete path, including spawn to point zero.
Example
ts
const path: WaypointMovementOptions = { points: [{ x: 0, y: 2, z: 0 }], seconds: 2, mode: 'pingPong' };Extended by
Properties
mode
ts
mode: "loop" | "once" | "pingPong";points
ts
points: readonly (readonly [number, number, number] | Vec3)[];seconds?
ts
optional seconds?: number;speed?
ts
optional speed?: number;startPaused?
ts
optional startPaused?: boolean;waitSeconds?
ts
optional waitSeconds?: number;WheeledVehicleProps
Handling overrides and manifest visual ids; empty ids use chassis debug geometry.
Example
ts
const props: WheeledVehicleProps = { handling: 'drift', asset: 'car', wheelAsset: 'wheel' };Extends
Properties
acceleration?
ts
optional acceleration?: number | null;Inherited from
airControl?
ts
optional airControl?: number | null;Inherited from
antiRoll?
ts
optional antiRoll?: number | null;Inherited from
asset?
ts
optional asset?: string;brakeDeceleration?
ts
optional brakeDeceleration?: number | null;Inherited from
VehicleSettings.brakeDeceleration
collision?
ts
optional collision?: "Vehicle" | null;Inherited from
ts
VehicleOptions.collisiondownforce?
ts
optional downforce?: number | null;Inherited from
driftRecovery?
ts
optional driftRecovery?: number | null;Inherited from
gripBySlip?
ts
optional gripBySlip?: VehicleCurve | null;Inherited from
halfExtents?
ts
optional halfExtents?: readonly [number, number, number] | null;Inherited from
handling?
ts
optional handling?: "drift" | "arcade" | "grippy";Inherited from
ts
VehicleOptions.handlingmass?
ts
optional mass?: number | null;Inherited from
maxSpeed?
ts
optional maxSpeed?: number | null;Inherited from
rearHandbrakeGrip?
ts
optional rearHandbrakeGrip?: number | null;Inherited from
VehicleSettings.rearHandbrakeGrip
reverseAsBrake?
ts
optional reverseAsBrake?: boolean | null;Inherited from
VehicleSettings.reverseAsBrake
reverseSpeed?
ts
optional reverseSpeed?: number | null;Inherited from
rollingDrag?
ts
optional rollingDrag?: number | null;Inherited from
steerAngle?
ts
optional steerAngle?: number | null;Inherited from
steeringBySpeed?
ts
optional steeringBySpeed?: VehicleCurve | null;Inherited from
VehicleSettings.steeringBySpeed
steerRate?
ts
optional steerRate?: number | null;Inherited from
uprightAssist?
ts
optional uprightAssist?: number | null;Inherited from
wheelAsset?
ts
optional wheelAsset?: string;wheels?
ts
optional wheels?:
| readonly [VehicleWheel, VehicleWheel, VehicleWheel, VehicleWheel]
| null;Inherited from
WorldEvent
What a made world tells the game: loaded (the list of things, as JSON in text), hit (a loose thing took a real knock: where, and how hard from 0 to 1), moved (a loose thing is somewhere new: the middle of its base and its turn), unloaded, and joint (a joint of a thing with moving parts stands somewhere new: position.x its place in the thing's list of joints, strength its value).
Properties
kind
ts
kind: "joint" | "hit" | "broken" | "loaded" | "moved" | "unloaded" | "mended";As above, and for a thing in pieces: broken (text the places in the list of the pieces that came off, with commas; strength 1 when nothing of it holds together) and mended.
position
ts
position: Vec3;hit: where the thing was when knocked. moved: the middle of its base now. joint: x is which joint.
rotation
ts
rotation: Quat;moved: how the thing is turned now.
strength
ts
strength: number;hit: how hard, 0 to 1. joint: the joint's value.
text
ts
text: string;loaded: the world's list as JSON (readWorldList). Empty otherwise.
thing
ts
thing: number;The thing's place in the world's list; 0 for loaded and unloaded.
WorldJoint
One joint of a thing with moving parts, as a game sees it.
Properties
at
ts
at: Vec3;A point on its axis, in the thing's own frame at rest.
axis
ts
axis: Vec3;Its axis, of length 1: a positive value turns right-handed about it, or slides along it.
free
ts
free: boolean;True for a joint with no limits (a wheel on its axle).
id
ts
id: string;The joint's name in the package, for example steering.
kind
ts
kind: "slide" | "hinge" | "break";A hinge turns (degrees); a slide moves (metres); a break holds two pieces until the thing breaks.
max
ts
max: number;The most its value may be; 0 for a joint that turns freely.
min
ts
min: number;The least its value may be; 0 for a joint that turns freely.
rest
ts
rest: number;The value the thing is drawn at when nothing is asked.
value
ts
value: number;Where it stands now (kept up to date by the joint event for a joint with limits).
WorldList
A world as a game sees it: the list handed over by the loaded event.
Properties
about
ts
about: string;One or two plain sentences about it.
bounds
ts
bounds:
| {
max: Vec3;
min: Vec3;
}
| null;The place's box, when the package gives one.
eyeHeight
ts
eyeHeight: number;The height of a standing person's eyes above the ground, metres.
id
ts
id: string;The package's id.
kind
ts
kind: "object" | "room" | "open";room: walls all round. open: a field, a street. object: no place, a thing by itself on a level floor.
name
ts
name: string;The world's name, for a page.
spawn
ts
spawn: WorldStand;Where the player starts, on the ground.
things
ts
things: WorldThing[];Every thing, loose or fixed, in the package's order.
version
ts
version: 1;The list's own format; 1 today.
walk
ts
walk: WorldWalk;How far the player may walk.
WorldSpec
World-level settings.
Properties
gravity?
ts
optional gravity?: number | readonly number[];Gravity (m/s²) for entities with Velocity but no RigidBody; bodies take the physics world's.
maxEntities?
ts
optional maxEntities?: number;Entity ceiling. Sizes the built-in arrays. Default 4096.
WorldSpot
A named place where a rider meets a thing (seat, gripLeft, gripRight, footLeft, footRight), in the thing's own frame at rest (metres, the origin at the middle of its base, its front along +z, its left +x). It moves with the part it is on: spotOf says where it is now.
Properties
forward
ts
forward: Vec3;The way a character there faces (a grip: the way the knuckles point).
joints
ts
joints: number[];The joints that move it, by their place in the thing's list of joints, the nearest to the spot first.
name
ts
name: string;The spot's name in the package.
position
ts
position: Vec3;Where, at rest.
up
ts
up: Vec3;Up at the spot.
WorldSpotNow
Where a rider's spot is now, in the world: what spotOf fills.
Properties
forward
ts
forward: Vec3;The way a character there faces.
position
ts
position: Vec3;Where.
up
ts
up: Vec3;Up at the spot.
WorldStand
A place to stand: a point on the ground and which way to face.
Extends
Properties
facing
ts
facing: number;Degrees about y, as a turn of a figure whose front is +z: 0 looks along +z, 90 along +x.
x
ts
x: number;Inherited from
y
ts
y: number;Inherited from
z
ts
z: number;Inherited from
WorldThing
One thing in a world: its own object (loose) or part of the place (fixed).
Properties
about
ts
about: string;One sentence about it.
away?
ts
optional away?: boolean;True while it is not in the world: a piece that has not come off its thing, and a thing all of whose pieces have. find and near pass over it.
body
ts
body: number;The host's physics body for it, or 0 when it has none.
drives
ts
drives: boolean;True for a thing that can be driven (things.drive).
id
ts
id: string;The package's id for it, for example steamer-trunk.
index
ts
index: number;Its place in the list; what world-event and the world command name it by.
joints
ts
joints: WorldJoint[];Its joints, when it has moving parts; a joint's place here is what the joint command names.
kind
ts
kind: string;One plain noun, for example chest.
label
ts
label: string;What a person calls it, for example steamer trunk.
max
ts
max: Vec3;The high corner of its box, now.
min
ts
min: Vec3;The low corner of its box, now, along the world's axes.
moved
ts
moved: boolean;True once it has moved from where the package put it.
pieceOf?
ts
optional pieceOf?: number;For one piece of a thing in pieces: that thing's place in the list. Left out otherwise.
pieces?
ts
optional pieces?: number[];For a thing in pieces: its pieces' places in the list (things.breakApart). Left out otherwise.
position
ts
position: Vec3;The middle of its base, now, in metres.
rests
ts
rests: string;What it rests on: floor, on:<thing id>, hanging or wall.
rider
ts
rider: WorldSpot[];Where a rider meets it (things.getOn), when the package names such spots; else empty.
rotation
ts
rotation: Quat;How it is turned, now.
size
ts
size: Vec3;Width (x), height (y) and depth (z), in metres.
stand
ts
stand: WorldStand | null;Where the package says to stand to use it, or null when it says nothing.
state
ts
state: "fixed" | "loose";loose: its own object, which may move. fixed: part of the place.
WorldWalk
How far the player may walk.
Properties
centre
ts
centre: Vec3;The circle's middle (radius only).
fadeFrom
ts
fadeFrom: number;From here outward the player slows (radius only).
radius
ts
radius: number;Past this the player goes no further (radius only).
shape
ts
shape: "radius" | "inside-collision";inside-collision: the walls stop the player. radius: a circle with a soft edge.
Type Aliases
ActionDecl
ts
type ActionDecl =
| {
devices?: readonly ("keyboard" | "gamepad" | "touch")[];
gamepad?: readonly number[];
keys?: readonly string[];
touch?: "tap" | "hold" | "doubleTap" | `button:${string}`;
}
| {
axis2: readonly [string, string, string, string];
gamepadAxes?: readonly [number, number];
stick?: "left" | "right";
};A button or two-axis action, using the host action map's axis order and standard pad indices.
Union Members
Type Literal
ts
{
devices?: readonly ("keyboard" | "gamepad" | "touch")[];
gamepad?: readonly number[];
keys?: readonly string[];
touch?: "tap" | "hold" | "doubleTap" | `button:${string}`;
}Type Literal
ts
{
axis2: readonly [string, string, string, string];
gamepadAxes?: readonly [number, number];
stick?: "left" | "right";
}axis2
ts
axis2: readonly [string, string, string, string];Keys for [-X, +X, -Y, +Y], matching the host action map.
gamepadAxes?
ts
optional gamepadAxes?: readonly [number, number];stick?
ts
optional stick?: "left" | "right";Example
ts
import type { ActionDecl } from 'gameable';
const fire: ActionDecl = { keys: ['LMB'], gamepad: [7], touch: 'tap' };ActorOther
ts
type ActorOther = ActorHandle | number;The other participant in an overlap or blocking contact; players use entity ids.
Example
ts
const other: ActorOther = 1;AgentState
ts
type AgentState = typeof AgentState[keyof typeof AgentState];One of AgentState.
AIControllerSpec
ts
type AIControllerSpec<P> = Omit<ActorSpec<AIControllerProps & P>, "components"> & object;Typed extension callback independent of the controller's movement component.
Type Declaration
components?
ts
optional components?: ActorSpec<AIControllerProps & P>["components"];Optional: a controller that declares none gets a plain scene() root.
onMoveCompleted()?
ts
optional onMoveCompleted(
self,
result,
ctx
): void;Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<AIControllerProps & P> |
result | "success" | "aborted" |
ctx | GameContext |
Returns
void
Type Parameters
| Type Parameter | Default type |
|---|---|
P extends object | object |
Example
ts
const spec: AIControllerSpec = { components: { root: scene() }, onMoveCompleted(self, result) {} };AssetId
ts
type AssetId = number;Manifest asset handle, resolved from a string id.
AssetKind
ts
type AssetKind = "splat" | "gltf" | "character" | "audio" | "collider" | "data" | "video";Manifest asset family.
AudioBus
ts
type AudioBus = "master" | "music" | "sfx" | "voice" | "ui";Audio mixer bus.
BeatQuantize
ts
type BeatQuantize = "now" | "beat" | "bar";Scheduling grid.
Example
ts
`audio.playOnBeat('kick', { quantize: 'beat' });`BodyId
ts
type BodyId = number;Rigid body / character controller handle.
BodyKind
ts
type BodyKind = "fixed" | "kinematic" | "dynamic" | "character";Physics body class. fixed is what other engines call static.
BtCheck
ts
type BtCheck<C> = (ctx, entity) => boolean;A guard supplied by the game; keep it allocation-free.
Type Parameters
| Type Parameter |
|---|
C |
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | C | The game's context. |
entity | number | The entity being checked. |
Returns
boolean
Whether the guard passes.
Example
ts
import { type BtCheck } from 'gameable';
const awake: BtCheck<{ awake: boolean }> = (ctx) => ctx.awake;BtLeaf
ts
type BtLeaf<C> = (ctx, entity, dt) => BtStatus;An action supplied by the game; keep it allocation-free.
Type Parameters
| Type Parameter |
|---|
C |
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | C | The game's context. |
entity | number | The entity being ticked. |
dt | number | Fixed-step seconds. |
Returns
The action's current status.
Example
ts
import { BtStatus, type BtLeaf } from 'gameable';
const idle: BtLeaf<null> = () => BtStatus.Running;BtStatus
ts
type BtStatus = typeof BtStatus[keyof typeof BtStatus];A node's result.
Example
ts
import { BtStatus } from 'gameable';
const result: BtStatus = BtStatus.Success;CameraMode
ts
type CameraMode = "first-person" | "third-person" | "free" | "fixed";Camera rig family.
CircuitPoint
ts
type CircuitPoint = readonly [number, number, number];A world-space point.
Example
ts
const p: CircuitPoint = [0, 0, 0];CircuitStanding
ts
type CircuitStanding = Readonly<Omit<RaceProgress, "respawnPose">>;Public circuit row, ordered by place; no authority crossing or respawn internals.
Example
ts
const show = (row: CircuitStanding) => console.log(row.place, row.completedLaps);CollisionChannel
ts
type CollisionChannel =
| "worldStatic"
| "worldDynamic"
| "pawn"
| "visibility"
| "camera"
| "physicsBody"
| "vehicle"
| "destructible"
| "game0"
| "game1"
| "game2"
| "game3";Object and trace channels supported by the SDK.
Example
ts
const channel: CollisionChannel = 'pawn';CollisionEnabled
ts
type CollisionEnabled = "none" | "query" | "physics" | "queryAndPhysics";Query and simulation participation, independent of body mobility.
Example
ts
const enabled: CollisionEnabled = 'query';CollisionResponse
ts
type CollisionResponse = "ignore" | "overlap" | "block";Pair response, ordered ignore < overlap < block.
Example
ts
const response: CollisionResponse = 'block';CollisionResponses
ts
type CollisionResponses = Partial<Record<CollisionChannel, CollisionResponse>> & object;Sparse channel overrides with a required fallback.
Type Declaration
default
ts
readonly default: CollisionResponse;Example
ts
const responses: CollisionResponses = { default: 'block', pawn: 'overlap' };CollisionTraceFlag
ts
type CollisionTraceFlag =
| "useDefault"
| "simpleAndComplex"
| "simpleAsComplex"
| "complexAsSimple";Simple/complex collision routing modes.
Example
ts
const flag: CollisionTraceFlag = 'simpleAsComplex';Command
ts
type Command =
| {
tag: "add-vehicle";
val: AddVehicleCmd;
}
| {
tag: "set-vehicle-input";
val: SetVehicleInputCmd;
}
| {
tag: "reset-vehicle";
val: ResetVehicleCmd;
}
| {
tag: "remove-vehicle";
val: number;
}
| {
tag: "conversation";
val: ConversationCmd;
}
| {
tag: "spawn";
val: SpawnCmd;
}
| {
tag: "despawn";
val: Entity;
}
| {
tag: "set-asset";
val: SetAssetCmd;
}
| {
tag: "set-parent";
val: SetParentCmd;
}
| {
tag: "set-anim";
val: SetAnimCmd;
}
| {
tag: "set-material-param";
val: SetMaterialParamCmd;
}
| {
tag: "add-body";
val: AddBodyCmd;
}
| {
tag: "add-joint";
val: AddJointCmd;
}
| {
tag: "remove-joint";
val: JointId;
}
| {
tag: "set-joint-motor";
val: SetJointMotorCmd;
}
| {
tag: "remove-body";
val: BodyId;
}
| {
tag: "set-body-transform";
val: SetBodyTransformCmd;
}
| {
tag: "set-body-velocity";
val: SetBodyVelocityCmd;
}
| {
tag: "apply-impulse";
val: ApplyImpulseCmd;
}
| {
tag: "set-body-enabled";
val: SetBodyEnabledCmd;
}
| {
tag: "move-character";
val: MoveCharacterCmd;
}
| {
tag: "spawn-character";
val: SpawnCharacterCmd;
}
| {
tag: "set-character-state";
val: SetCharacterStateCmd;
}
| {
tag: "set-clip-weights";
val: SetClipWeightsCmd;
}
| {
tag: "set-expression";
val: SetExpressionCmd;
}
| {
tag: "look-at";
val: LookAtCmd;
}
| {
tag: "say";
val: SayCmd;
}
| {
tag: "hit-character";
val: HitCharacterCmd;
}
| {
tag: "recover-character";
val: Entity;
}
| {
tag: "set-character-motion";
val: SetCharacterMotionCmd;
}
| {
tag: "walk-character-to";
val: WalkCharacterToCmd;
}
| {
tag: "face-character";
val: FaceCharacterCmd;
}
| {
tag: "stop-character-walk";
val: Entity;
}
| {
tag: "do-character-action";
val: DoCharacterActionCmd;
}
| {
tag: "cancel-character-action";
val: Entity;
}
| {
tag: "play-sound";
val: PlaySoundCmd;
}
| {
tag: "stop-sound";
val: StopSoundCmd;
}
| {
tag: "play-music";
val: PlayMusicCmd;
}
| {
tag: "stop-music";
val: number;
}
| {
tag: "set-music-layer";
val: SetMusicLayerCmd;
}
| {
tag: "play-sound-on-beat";
val: PlaySoundOnBeatCmd;
}
| {
tag: "set-bus-fx";
val: SetBusFxCmd;
}
| {
tag: "set-sound-occlusion";
val: SetSoundOcclusionCmd;
}
| {
tag: "set-listener";
val: SetListenerCmd;
}
| {
tag: "load-asset";
val: LoadAssetCmd;
}
| {
tag: "set-pointer-lock";
val: boolean;
}
| {
tag: "set-time-scale";
val: number;
}
| {
tag: "pause-push";
val: string;
}
| {
tag: "pause-pop";
val: string;
}
| {
tag: "cutscene";
val: CutsceneCmd;
}
| {
tag: "thing";
val: ThingCmd;
}
| {
tag: "playtest";
val: PlaytestCmd;
}
| {
tag: "effect";
val: EffectCmd;
}
| {
tag: "set-post";
val: PostCmd;
}
| {
tag: "set-spot-light";
val: SpotLightCmd;
}
| {
tag: "fight-state";
val: FightStateCmd;
}
| {
tag: "fight-hit";
val: FightHitCmd;
}
| {
tag: "fight-fall";
val: FightFallCmd;
}
| {
tag: "fight-get-up";
val: FightGetUpCmd;
}
| {
tag: "fight-camera";
val: FightCameraCmd;
}
| NetCommand;Everything the guest can ask the host to do, applied front to back.
CommandTag
ts
type CommandTag = Command["tag"];Every Command['tag'], useful for exhaustive host-side switches.
ConstraintKind
ts
type ConstraintKind = "hinge" | "slider" | "point" | "fixed" | "distance";Supported joint families.
Example
ts
const kind: ConstraintKind = 'hinge';ContactPhase
ts
type ContactPhase = "begin" | "stay" | "end";Lifecycle phase of a contact.
CrowdMove
ts
type CrowdMove = "character" | "velocity";How Crowd.update hands each agent's velocity to the world.
DataSchema
ts
type DataSchema = Record<string, DataFieldSchema>;Required fields to validate; fields absent from the schema are allowed.
Example
ts
const schema: DataSchema = { hp: { type: 'number', description: 'Health.' } };DriveRequest
ts
type DriveRequest = Common &
| {
kind: "target";
target: AITarget;
}
| {
cornerSpeed: number;
distance: number;
kind: "line";
lateralOffset: number;
loop: boolean;
names: number[];
points: number[];
segment: number;
source: number;
}
| {
cooldown: number;
kind: "chase";
leadTime: number;
maxLead: number;
ram: number;
ramCooldown: number;
ramDistance: number;
target: AITarget;
};JSON-safe discriminated driving intent, including recovery and line progress.
Example
ts
const kind: DriveRequest['kind'] = 'line';EaseName
ts
type EaseName = keyof typeof ease;A built-in easing curve's name.
Example
ts
import { ease, type EaseName } from 'gameable';
const name: EaseName = 'sineIn';
console.log(ease[name](0.5));EffectAction
ts
type EffectAction = "play" | "move" | "stop";An emitter operation.
Example
ts
import type { EffectAction } from 'gameable';
const action: EffectAction = 'play';EffectId
ts
type EffectId = number;Guest-minted effect handle; 0 is a one-shot.
Example
ts
import type { EffectId } from 'gameable';
const effect: EffectId = 1;EndPlayReason
ts
type EndPlayReason = "destroyed" | "lifeSpan" | "killZ" | "levelUnload";Why an actor left play.
Example
ts
const reason: EndPlayReason = 'destroyed';Entity
ts
type Entity = number;ECS entity handle. 0 is reserved and means "none".
ErrorCode
ts
type ErrorCode =
| "init-failed"
| "tick-failed"
| "invalid-state"
| "unsupported"
| "asset-missing"
| "snapshot-version-mismatch"
| "internal";Machine-readable half of a GameError.
ExpressionSpace
ts
type ExpressionSpace = "arkit52" | "gnm" | "gnm68";Coordinate space for setExpression weights.
FeatureOptions
ts
type FeatureOptions = Readonly<Record<string, Readonly<Record<string, unknown>>>>;Declared features, normalised: every present feature has an options object.
FxPreset
ts
type FxPreset =
| "dry"
| "room"
| "hall"
| "cave"
| "underwater"
| "radio"
| "muffled"
| "arena";Bus effect preset.
Example
ts
`audio.fx('sfx', 'cave');`GameDefinition
ts
type GameDefinition = Readonly<GameSpec>;A validated game declaration.
GameEvent
ts
type GameEvent =
| {
tag: "pause-reasons";
val: string[];
}
| {
tag: "start";
val: {
reason: "player" | "capture" | "playtest";
};
}
| {
tag: "conversation-event";
val: ConversationEvent;
}
| {
tag: "asset-loaded";
val: AssetLoadedEvent;
}
| {
tag: "character-ready";
val: CharacterReadyEvent;
}
| {
tag: "sound-ended";
val: SoundEndedEvent;
}
| {
tag: "beat";
val: BeatEvent;
}
| {
tag: "music-track";
val: MusicTrackEvent;
}
| {
tag: "anim-event";
val: AnimEventData;
}
| {
tag: "resized";
val: ResizedEvent;
}
| {
tag: "cutscene-event";
val: CutsceneEvent;
}
| {
tag: "world-event";
val: WorldEvent;
}
| {
tag: "motion-event";
val: MotionEvent;
}
| NetEvent
| {
tag: "ui";
val: UiEvent;
}
| {
tag: "fight-set";
val: FightSetEvent;
}
| {
tag: "fight-contact";
val: FightContactEvent;
}
| {
tag: "fight-body";
val: FightBodyEvent;
};A host-side occurrence since the previous tick.
GridDirection
ts
type GridDirection =
| "north"
| "south"
| "east"
| "west"
| "northeast"
| "northwest"
| "southeast"
| "southwest";Compass direction; north is world -Z.
Example
ts
const dir: GridDirection = 'north';HitStrength
ts
type HitStrength =
| {
tag: "small";
}
| {
tag: "big";
}
| {
tag: "shot";
}
| {
tag: "big-shot";
}
| {
tag: "push";
val: number;
};How hard a blow lands on a character's physics body: small (a flinch and a recovery over about a second), big (a fall that stays down until recover-character), shot (a sharp blow with a flinch), big-shot (a sharp blow that floors), or a push of so many newton-seconds (40 staggers, 90 and over floors).
JointAxisMode
ts
type JointAxisMode = "free" | "locked" | "limited";JointAxisMode in the physics boundary.
Example
ts
import type { JointAxisMode } from 'gameable';
const value: JointAxisMode = 'limited';JointId
ts
type JointId = number;JointId in the physics boundary.
Example
ts
import type { JointId } from 'gameable';
const value: JointId = 1;JointKind
ts
type JointKind = "fixed" | "point" | "hinge" | "slider" | "distance" | "six-dof";JointKind in the physics boundary.
Example
ts
import type { JointKind } from 'gameable';
const value: JointKind = 'hinge';KeyName
ts
type KeyName = string;Any string this table accepts: a DOM code, a bare letter or digit, or one of the friendly aliases.
LevelEdit
ts
type LevelEdit =
| {
entry?: number;
name: string;
op: "set";
position?: Vec3Tuple;
props?: Record<string, unknown>;
rotation?: QuatTuple;
scale?: Vec3Tuple;
yaw?: number;
}
| {
class: string;
entry?: number;
name: string;
op: "reclass";
props?: Record<string, unknown>;
}
| {
entry?: number;
name: string;
op: "tags";
tags: readonly string[];
}
| {
entry?: number;
name: string;
op: "rename";
to: string;
}
| {
entry?: number;
name: string;
op: "remove";
}
| {
actor: LevelActor;
op: "add";
}
| {
op: "place";
place?: string;
};One change to a level, keyed by the actor's name (levelActorNames). entry is the index the editor saw; it is carried for a reader, never used to look the actor up, since the file may have changed under the editor.
Union Members
Type Literal
ts
{
entry?: number;
name: string;
op: "set";
position?: Vec3Tuple;
props?: Record<string, unknown>;
rotation?: QuatTuple;
scale?: Vec3Tuple;
yaw?: number;
}entry?
ts
optional entry?: number;name
ts
name: string;op
ts
op: "set";position?
ts
optional position?: Vec3Tuple;props?
ts
optional props?: Record<string, unknown>;Merged over the entry's props.
rotation?
ts
optional rotation?: QuatTuple;Writing it drops yaw.
scale?
ts
optional scale?: Vec3Tuple;yaw?
ts
optional yaw?: number;Degrees about +Y; writing it drops rotation.
Type Literal
ts
{
class: string;
entry?: number;
name: string;
op: "reclass";
props?: Record<string, unknown>;
}class
ts
class: string;entry?
ts
optional entry?: number;name
ts
name: string;op
ts
op: "reclass";props?
ts
optional props?: Record<string, unknown>;Merged over the props the new class keeps.
Type Literal
ts
{
entry?: number;
name: string;
op: "tags";
tags: readonly string[];
}Type Literal
ts
{
entry?: number;
name: string;
op: "rename";
to: string;
}Type Literal
ts
{
entry?: number;
name: string;
op: "remove";
}Type Literal
ts
{
actor: LevelActor;
op: "add";
}Type Literal
ts
{
op: "place";
place?: string;
}Example
ts
const edit: LevelEdit = { op: 'set', name: 'exit', position: [3, 1.2, -10.5] };LogLevel
ts
type LogLevel = "trace" | "debug" | "info" | "warn" | "error";Log severity accepted by env.log.
MatchState
ts
type MatchState = "waitingToStart" | "inProgress" | "waitingPostMatch";Match lifecycle.
Example
ts
const state: MatchState = 'waitingToStart';MaterialValue
ts
type MaterialValue =
| {
tag: "scalar";
val: number;
}
| {
tag: "boolean";
val: boolean;
}
| {
tag: "color";
val: Rgba;
}
| {
tag: "vector";
val: Vec3;
}
| {
tag: "texture";
val: AssetId;
};A material parameter value.
MessageCheck
ts
type MessageCheck<T> = (payload) => payload is T;The game's own type guard for a payload, already parsed from JSON. It must be pure: no wall time, no Math.random, no state, so the authority and every replay agree on what it drops.
Type Parameters
| Type Parameter |
|---|
T |
Parameters
| Parameter | Type |
|---|---|
payload | unknown |
Returns
payload is T
MotorMode
ts
type MotorMode = "off" | "velocity" | "position";MotorMode in the physics boundary.
Example
ts
import type { MotorMode } from 'gameable';
const value: MotorMode = 'position';NetCommand
ts
type NetCommand =
| {
tag: "send";
val: SendCmd;
}
| {
tag: "set-player-camera";
val: SetPlayerCameraCmd;
}
| {
tag: "set-player-hud";
val: SetPlayerHudCmd;
}
| {
tag: "save-player-data";
val: SavePlayerDataCmd;
}
| {
tag: "save-game-data";
val: SaveGameDataCmd;
}
| {
tag: "set-player-entity";
val: SetPlayerEntityCmd;
}
| {
tag: "exchange";
val: ExchangeCmd;
};The net and data members of the command variant.
NetEvent
ts
type NetEvent =
| {
tag: "player-joined";
val: PlayerJoinedEvent;
}
| {
tag: "player-left";
val: PlayerLeftEvent;
}
| {
tag: "message";
val: NetMessageEvent;
}
| {
tag: "exchange-result";
val: ExchangeResultEvent;
}
| {
tag: "game-data";
val: GameDataEvent;
};The net and data members of the event variant.
NetRole
ts
type NetRole = "solo" | "authority" | "client";Where a guest runs: alone (solo), as the room's authority, or as one player's client.
Example
ts
const role: NetRole = ctx.net.role;
if (role === 'client') showLatency();ParticleEffectOptions
ts
type ParticleEffectOptions = Omit<ComponentOptions, "scale"> & object;Emitter overrides; scale controls particles rather than the component transform.
Type Declaration
autoActivate?
ts
optional autoActivate?: boolean;intensity?
ts
optional intensity?: number;scale?
ts
optional scale?: number;tint?
ts
optional tint?: readonly [number, number, number];Example
ts
const options: ParticleEffectOptions = { autoActivate: false };PawnInput
ts
type PawnInput = GameContext["input"];A player's input, read like ctx.input.
PickupGive
ts
type PickupGive =
| {
heal: number;
}
| {
count: number;
item: string;
}
| {
score: number;
}
| "custom";JSON pickup reward; inventory owners are player seats, with seat 0 in solo.
Example
ts
const reward: PickupGive = { item: 'key', count: 1 };PlayerSpawn
ts
type PlayerSpawn =
| readonly number[]
| readonly readonly number[][]
| ((seat, ctx) => Vec3);Where definition.player spawns each seat: one point [x, y, z] for everyone, a list of points (seat i takes list[i % list.length]), or a function of the seat. A single-player game spawns seat 0.
The function runs on the authority at the seat's join, inside the step, so it must be deterministic: read only the seat, ctx.rules, ctx.rng and the world, never the clock or Math.random. It runs before ctx.players is updated for the step, so read the seat: the map still holds the previous step's players.
Example
ts
const corners: PlayerSpawn = [[-8, 0, -8], [8, 0, -8], [8, 0, 8], [-8, 0, 8]];
export default defineGame({ player: { prefab: Hero, spawn: corners } });ProfileName
ts
type ProfileName = keyof typeof profiles;Built-in collision profile names (deprecated redirects excluded).
Example
ts
const name: ProfileName = 'Pawn';ProjectileSpec
ts
type ProjectileSpec<P> = Omit<ActorSpec<ProjectileProps & P>, "components" | "props"> & object;Projectile defaults and definition-only impact callback. Hit coordinates are borrowed.
Type Declaration
components?
ts
optional components?: ActorSpec<ProjectileProps & P>["components"];props?
ts
optional props?: Partial<ProjectileProps> & P;onProjectileHit()?
ts
optional onProjectileHit(
self,
hit,
ctx,
stopped
): void;Runs once per accepted sweep hit, after damage and before terminal destruction.
Parameters
| Parameter | Type |
|---|---|
self | ActorHandle<ProjectileProps & P> |
hit | RayHit |
ctx | GameContext |
stopped | boolean |
Returns
void
Type Parameters
| Type Parameter | Default type |
|---|---|
P extends object | object |
Example
ts
const spec: ProjectileSpec = { props: { hitResponse: 'effect' }, onProjectileHit(self, hit, ctx, stopped) {} };ProjectionKind
ts
type ProjectionKind = "perspective" | "orthographic";Camera projection family.
QuatTuple
ts
type QuatTuple = readonly [number, number, number, number];A quaternion, xyzw.
ShapeKind
ts
type ShapeKind =
| "box"
| "sphere"
| "capsule"
| "cylinder"
| "plane"
| "convex-hull"
| "mesh"
| "height-field";Collision shape family.
SoundId
ts
type SoundId = number;Playing-sound handle.
StopStyle
ts
type StopStyle = "gradual" | "hard";Which kind of stop a running character asked to stand makes: 'gradual', it slows and stands upright; 'hard', it brakes. It says WHICH KIND of stop; arrive (see character.walkTo) says how soon it must be there. Read where the character's motion set has stops that state a kind (a run's, on the engine's shared set); a walk's stop and a sprint's stop are the same under both there.
System
ts
type System = (ctx) => void;A system: one plain function, run once per fixed step. In systems it may also be a SidedSystem, { run, on }, that says where it runs.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
ToneMapping
ts
type ToneMapping = "none" | "aces" | "agx" | "neutral";Supported post tone mapping operators.
Example
ts
import type { ToneMapping } from 'gameable';
const toneMapping: ToneMapping = 'aces';TransferDoc
ts
type TransferDoc = Record<string, unknown>;A player document as a transfer reads it: a plain object.
UiEventKind
ts
type UiEventKind =
| "click"
| "drag-start"
| "drop"
| "drag-cancel"
| "focus"
| "blur"
| "change"
| "submit";What the player did. Mirrors WIT ui-event-kind.
Example
ts
import type { UiEventKind } from 'gameable';
const example: UiEventKind = 'click';
console.log(example);UiNode
ts
type UiNode =
| UiStack
| UiGrid
| UiPanel
| UiText
| UiButton
| UiCard
| UiList
| UiBar
| UiInput;Any node.
Example
ts
import type { UiNode } from 'gameable';
const example: UiNode = { type: 'text', text: 'Ready' };
console.log(example);UiScreenAnchor
ts
type UiScreenAnchor =
| "center"
| "top"
| "bottom"
| "left"
| "right"
| "top-left"
| "top-right"
| "bottom-left"
| "bottom-right"
| "fill";Where a top-level node sits on the screen. fill covers the whole viewport.
Example
ts
import type { UiScreenAnchor } from 'gameable';
const example: UiScreenAnchor = 'top-right';
console.log(example);Vec3Tuple
ts
type Vec3Tuple = readonly [number, number, number];A position or a scale.
VehicleCurve
ts
type VehicleCurve = readonly readonly [number, number][];Piecewise linear [input, multiplier] points; x must strictly increase.
Example
ts
const curve: VehicleCurve = [[0, 1], [30, 0.5]];VehicleOptions
ts
type VehicleOptions = { [K in keyof VehicleSettings]?: VehicleSettings[K] | null } & object;Vehicle tuning with preset defaults.
Type Declaration
collision?
ts
optional collision?: "Vehicle" | null;handling?
ts
optional handling?: "arcade" | "grippy" | "drift";Example
ts
const options: VehicleOptions = { handling: 'drift', maxSpeed: 30 };VfxPreset
ts
type VfxPreset = "hit-sparks" | "explosion" | "smoke" | "fire" | "magic" | "dust" | "trail";Built-in particle presets.
Example
ts
import type { VfxPreset } from 'gameable';
const preset: VfxPreset = 'hit-sparks';WalkStart
ts
type WalkStart = "moving";How a walk to a spot is begun when the game knows more than the character's takes show: 'moving', the body is under way already (it comes out of a get-up, it was carried or thrown), so the walk is planned as of a body under way: no turn on the spot first, no one take from stand to stand, and a pace above the walk's needs room for its stop only, not for a start from standing. See character.walkTo.
Variables
Actor
ts
const Actor: Record<string, never> = {};Tag identifying actor roots.
Example
ts
addComponent(ctx.world, entity, Actor);actors
ts
const actors: object;Actor queries in spawn order. Returned arrays are borrowed runtime views.
Type Declaration
all()
ts
all(): readonly ActorHandle<object>[];All living actors, including pending beginPlay.
Returns
readonly ActorHandle<object>[]
A borrowed array in spawn order.
named()
ts
named(name): ActorHandle<object> | null;First living actor with this instance name, or null.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Instance name to match. |
Returns
ActorHandle<object> | null
The first matching actor, or null.
of()
ts
of(entity): ActorHandle<object> | null;Owning actor for a root or component entity, or null.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Root or component entity id. |
Returns
ActorHandle<object> | null
The owning actor, or null.
ofClass()
ts
ofClass<P>(cls): readonly ActorHandle<P>[];Actors whose class is exactly cls.
Type Parameters
| Type Parameter |
|---|
P extends object |
Parameters
| Parameter | Type | Description |
|---|---|---|
cls | ActorClass<P> | Registered actor class. |
Returns
readonly ActorHandle<P>[]
A borrowed array of matching actors.
withTag()
ts
withTag(tag): readonly ActorHandle<object>[];Actors carrying a tag, with no duplicates.
Parameters
| Parameter | Type | Description |
|---|---|---|
tag | string | Instance tag to match. |
Returns
readonly ActorHandle<object>[]
A borrowed array of matching actors.
Example
ts
const crates = actors.withTag('breakable');AgentState
ts
const AgentState: object;Where an agent is in its errand.
Type Declaration
Arrived
ts
readonly Arrived: 2 = 2;Idle
ts
readonly Idle: 0 = 0;Moving
ts
readonly Moving: 1 = 1;NoPath
ts
readonly NoPath: 3 = 3;AIController
ts
const AIController: ActorClass<AIControllerProps & object>;A controller with no player seat and a replaceable move-completion hook.
Example
ts
const ai = spawnActor(ctx, AIController, { position: { x: 0, y: 0, z: 0 } });AmbientSound
ts
const AmbientSound: ActorClass<AmbientProps>;A looping positional sound built on an audio component.
Example
ts
spawnActor(ctx, AmbientSound, { position: { x: 0, y: 0, z: 0 }, props: { sound: 'wind' } });audio
ts
const audio: object;The audio facade.
Type Declaration
fx()
ts
fx(
bus,
preset,
options?
): void;Set bus effects.
Parameters
| Parameter | Type | Description |
|---|---|---|
bus | AudioBus | Mixer bus. |
preset | FxPreset | Base preset. |
options? | FxOptions | Overrides and fade. |
Returns
void
Example
ts
`audio.fx('sfx', 'cave');`listener()
ts
listener(position, rotation): void;Place the audio listener.
Parameters
| Parameter | Type | Description |
|---|---|---|
position | Vec3 | Listener position. |
rotation | Quat | Listener rotation, xyzw. |
Returns
void
Nothing.
occlude()
ts
occlude(
sound,
amount,
fadeMs?
): void;Muffle a sound.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
sound | number | undefined | Sound handle. |
amount | number | undefined | Occlusion from zero to one. |
fadeMs | number | 0 | Ramp duration. |
Returns
void
Example
ts
`audio.occlude(1, 0.8, 120);`play()
ts
play(asset, options?): number;Start a sound.
Parameters
| Parameter | Type | Description |
|---|---|---|
asset | string | number | Manifest string id or asset handle. |
options? | PlayOptions | Attachment, gain, pitch, looping and bus. |
Returns
number
The guest-minted sound handle, or 0 when the asset is unknown.
playOnBeat()
ts
playOnBeat(asset, options?): number;Schedule a sound on the music grid.
Parameters
| Parameter | Type | Description |
|---|---|---|
asset | string | number | Manifest id or handle. |
options? | PlayOnBeatOptions | Grid and mixer options. |
Returns
number
Sound handle or zero for an unknown asset.
Example
ts
`audio.playOnBeat('kick', { subdivision: 2 });`stop()
ts
stop(sound, fadeMs?): void;Stop a playing sound.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
sound | number | undefined | A handle from play. |
fadeMs | number | 0 | Fade-out in milliseconds; 0 stops immediately. |
Returns
void
Nothing.
Example
ts
import { audio } from 'gameable';
const id = audio.play('shot', { entity: player, volume: 0.8 });
audio.stop(id, 50);AudioVolume
ts
const AudioVolume: ActorClass<AudioVolumeProps>;A solo pawn's box reverb region; rooms skip it because authority has no single listener. This module exclusively owns audio.fx for every bus named by an AudioVolume: game code must leave those buses' effects to volumes. Priority wins; equal priority uses spawn order.
Example
ts
spawnActor(ctx, AudioVolume, { position: { x: 0, y: 0, z: 0 }, props: { reverb: 'hall' } });AUTHORITY_SENDER
ts
const AUTHORITY_SENDER: 4294967295 = 0xffffffff;The sender id of a message from the authority itself. Room seats start at 0, so the authority is not 0: this is past every player id and still a u32 (the WIT's message-event.player). Keep ids unsigned: in an Int32Array this reads back as -1.
Example
ts
import { AUTHORITY_SENDER } from 'gameable';
const fromServer = (from: number): boolean => from === AUTHORITY_SENDER;AutomaticDoor
ts
const AutomaticDoor: ActorClass<AutomaticDoorProps>;Two metal panels that split for nearby players and wait after they leave. Locked arrivals receive one notice and onLocked per entry, without an E prompt.
Example
ts
spawnActor(ctx, AutomaticDoor, { position: { x: 0, y: 1.05, z: 0 } });BlockingVolume
ts
const BlockingVolume: ActorClass<{
halfExtents: number[];
}>;Invisible fixed box; dimensions are half extents in metres, read at spawn.
Example
ts
spawnActor(ctx, BlockingVolume, { position: { x: 0, y: 1, z: 4 }, props: { halfExtents: [4, 1, 0.2] } });BODY_KINDS
ts
const BODY_KINDS: readonly ["fixed", "kinematic", "dynamic", "character"];Physics body classes, in the index order RigidBody.kind stores.
BODY_STRIDE
ts
const BODY_STRIDE: 15 = 15;Floats per row of frame-input.bodies.
bt
ts
const bt: object;Pure builders: only descriptions are allocated; no runtime state or randomness.
Type Declaration
action()
ts
action<C>(run): BtNode<C>;Run a game action.
Type Parameters
| Type Parameter |
|---|
C |
Parameters
| Parameter | Type | Description |
|---|---|---|
run | BtLeaf<C> | The game's action. |
Returns
BtNode<C>
An action description.
condition()
ts
condition<C>(check): BtNode<C>;Turn a boolean guard into success or failure.
Type Parameters
| Type Parameter |
|---|
C |
Parameters
| Parameter | Type | Description |
|---|---|---|
check | BtCheck<C> | The game's guard. |
Returns
BtNode<C>
A condition description.
not()
ts
not<C>(child): BtNode<C>;Swap success and failure, leaving running unchanged.
Type Parameters
| Type Parameter |
|---|
C |
Parameters
| Parameter | Type | Description |
|---|---|---|
child | BtNode<C> | The node to invert. |
Returns
BtNode<C>
An inversion description.
selector()
ts
selector<C>(...children): BtNode<C>;Recheck children from the start; the first non-failure wins.
Type Parameters
| Type Parameter |
|---|
C |
Parameters
| Parameter | Type | Description |
|---|---|---|
...children | BtNode<C>[] | Children in priority order. |
Returns
BtNode<C>
A selector description.
sequence()
ts
sequence<C>(...children): BtNode<C>;Recheck children from the start; stop at the first non-success.
Type Parameters
| Type Parameter |
|---|
C |
Parameters
| Parameter | Type | Description |
|---|---|---|
...children | BtNode<C>[] | Children in execution order. |
Returns
BtNode<C>
A sequence description.
sequenceWithMemory()
ts
sequenceWithMemory<C>(...children): BtNode<C>;Resume at the running child, skipping previously successful children.
Type Parameters
| Type Parameter |
|---|
C |
Parameters
| Parameter | Type | Description |
|---|---|---|
...children | BtNode<C>[] | Children in execution order. |
Returns
BtNode<C>
A sequence with memory description.
wait()
ts
wait<C>(seconds): BtNode<C>;Accumulate this entity's dt until the duration is reached.
Type Parameters
| Type Parameter |
|---|
C |
Parameters
| Parameter | Type | Description |
|---|---|---|
seconds | number | The duration, in seconds. |
Returns
BtNode<C>
A wait description, restarting after completion or interruption.
Returns
Stateless nodes for compiling with createBehaviorTree.
Example
ts
import { bt, BtStatus, createBehaviorTree } from 'gameable';
const root = bt.sequence(bt.wait<null>(1), bt.action<null>(() => BtStatus.Success));
const tree = createBehaviorTree(root);
tree.tick(null, 0, 1 / 60);BtStatus
ts
const BtStatus: object;Results returned by a behaviour tree node.
Type Declaration
Failure
ts
readonly Failure: 2 = 2;Running
ts
readonly Running: 3 = 3;Success
ts
readonly Success: 1 = 1;Returns
The success, failure and running status constants.
Example
ts
import { BtStatus } from 'gameable';
const chase = () => BtStatus.Running;
chase();BUILTIN_COMPONENT_NAMES
ts
const BUILTIN_COMPONENT_NAMES: readonly ["Transform", "Renderable", "RigidBody", "Character", "Velocity", "Health", "Player", "Enemy", "Pickup", "Actor"];Names matching BUILTIN_COMPONENTS, used in snapshot headers.
BUILTIN_COMPONENTS
ts
const BUILTIN_COMPONENTS: readonly [TransformStore, RenderableStore, RigidBodyStore, CharacterStore, VelocityStore, HealthStore, Record<string, never>, Record<string, never>, Record<string, never>, Record<string, never>];Every built-in component, in the fixed order snapshot serialises them.
camera
ts
const camera: object;The camera facade: writes the frame's camera.
Type Declaration
look
Get Signature
ts
get look(): object;Accumulated look angles, in radians. Mutate to snap the view.
Returns
object
The live look state.
pitch
ts
pitch: number;sensitivity
ts
sensitivity: number;yaw
ts
yaw: number;state
Get Signature
ts
get state(): CameraState;Returns
fight()
ts
fight(shot): void;The fight camera (the fight kit's script door), run on the host: from the side, between the two fighters, pulled back as they part, raised when one flies, never still, inside the ropes; a wide shot on a knockdown, in close on the winner. Say it every step while it is on; the camera is yours again with on: false.
Parameters
| Parameter | Type | Description |
|---|---|---|
shot | FightShotOptions | The two fighters and the moment. |
Returns
void
Nothing.
firstPerson()
ts
firstPerson(entity, options?): void;Mount the camera at an entity's eyes.
Yaw and pitch come from the built-in look accumulator, which integrates input.mouse.dx/dy once per tick.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity to mount on. |
options? | FirstPersonOptions | Eye height and field of view. |
Returns
void
Nothing.
follow()
ts
follow(entity, options?): void;Put the camera on a spring arm behind an entity.
The host owns the arm and its collision; the guest only states the intent. position is the orbit pivot and rotation the direction the player is looking, so a host with no rig still ends up somewhere sensible.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity to follow. |
options? | FollowOptions | Boom length, height offset, field of view and orbit angles. |
Returns
void
Nothing.
lookAt()
ts
lookAt(point): void;Aim the camera at a world point, overriding its rotation.
Parameters
| Parameter | Type | Description |
|---|---|---|
point | Vec3 | null | The point to look at, or null to use the rotation again. |
Returns
void
Nothing.
set()
ts
set(
position,
rotation,
fovYDeg?
): void;Place the camera explicitly, detaching it from any entity.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
position | Vec3 | undefined | Eye position. |
rotation | Quat | undefined | Eye rotation, xyzw. |
fovYDeg | number | 60 | Vertical field of view in degrees. Default 60. |
Returns
void
Nothing.
Example
ts
import { camera } from 'gameable';
camera.firstPerson(player, { eyeHeight: 1.7 });CameraActor
ts
const CameraActor: ActorClass<{
activateOnStart: boolean;
fov: number;
}>;A placeable camera. The active actor writes its transform every actor step, suppressing the built-in player camera through camera.set's cameraWritten flag. Later game systems can override that frame's view. Activation survives snapshots.
Example
ts
const view = spawnActor(ctx, CameraActor, { position: { x: 0, y: 2, z: 5 },
props: { fov: 55, activateOnStart: true } });
activateCamera(ctx, view);character
ts
const character: object;The character facade.
Type Declaration
bundleOf()
ts
bundleOf(entity): number;The character bundle handle attached to an entity, or 0.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity id. |
Returns
number
The bundle asset handle.
cancelAction()
ts
cancelAction(entity): void;Take an action's request back (it cannot be taken back between its gathering and its landing).
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
Returns
void
Nothing.
do()
ts
do(
entity,
action,
object?,
plain?
): void;Ask a character to do an action of its motion set (a hurdle, a jump, a sit), at an object when the action needs one. What follows comes as motion-events in ctx.events: started, contact, release (with the point and its velocity, for a thing let go), landed, done, or failed with its reason.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity with a Character component. |
action | string | undefined | The action's name in the set. |
object? | Readonly<ActionObject> | undefined | The thing it is done at, as the game has it; left out for an action without one. |
plain? | boolean | false | The plain way, for a comparison: the take simply started, nothing fitted. |
Returns
void
Nothing.
Example
ts
character.do(hero, 'hurdle', { id: bar, position: barAt, yaw: 0, height: 0.6, width: 1.2, depth: 0.05 });face()
ts
face(
entity,
facing,
arrive?
): void;Turn a character on the spot to face a way, by its set's own turns. The motion-event arrived named 'face' says when it faces there.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity with a Character component. |
facing | number | undefined | Radians about +Y (0 faces +Z). |
arrive | "easy" | "quick" | 'easy' | 'easy' (the default: an unhurried turn) or 'quick' (the quickest the set has). |
Returns
void
Nothing.
Example
ts
character.face(guide, Math.PI / 2);fight()
ts
fight(entity, state?): void;The fight kit's script door: what this fighter's body is doing this step. The host's fight driver makes the pose on the character's own body from the fight pack (the page's bridge names the set) and lays it on the bones after the character's own clips: the base take under the state, the stance or the crouch, the guard, the look, the strike by the pack's id and its frame pulled to its aim, the posture, the lean, the planted feet. Say it every step. Where the fighter stands is its entity's transform: set the position (x, up, z) and the rotation (the yaw, facing * PI / 2 + turn) yourself. The host answers with motion-events in ctx.events: down (a thrown body came to rest, kind landed) and risen (the get-up finished, kind done), each with point where the body is and facing the yaw it faces: put the entity there. Name the other fighter (target) and the strike is aimed at its body and met against it: a fight-contact event says where. The pack's own table of moves comes once as a fight-set event (its fight block, JSON text).
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
state | FightStateOptions | null | What the body is doing; every field optional. null ends the fight on this body (a round's reset): the clips have it again, and the next call starts afresh, standing. |
Returns
void
Nothing.
Example
ts
character.fight(me, { base: { name: 'fight_idle_bounce', loop: true, fade: 10 }, facing: 1, bounce: 0.7 });
character.fight(me, { base: null, strike: { id: 'jab', frame, aim: theirHead } });fightFall()
ts
fightFall(
entity,
velocity,
spin?,
turn?,
kick?
): void;A fighter thrown into the fight kit's rag-doll: it flies at velocity (metres a second, world), turning at spin, falls, bounces, slides and comes to rest; the entity follows the body; the motion-event down says when it lies still and where. Then character.fightGetUp.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity with a Character component. |
velocity | Vec3 | undefined | Metres a second, world. |
spin | number | 2 | Radians a second about the axis across the blow's line (0.4 to 3 reads as a knockdown). |
turn | number | 0 | The blow's line's angle on the floor (0 along x). |
kick | boolean | false | The body is thrown already (a hit in the air): the blow is blended into its flight. |
Returns
void
Nothing.
fightGetUp()
ts
fightGetUp(entity, quick?): void;A fighter up off the floor: the get-up take chosen by how the body lies (on its back the spring-up, or the kip-up when quick; face down the stomach get-up), facing the way the head points. Keep saying character.fight with grounded: false while it rises; the motion-event risen says when it stands, where, and which way (facing, a yaw).
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity with a Character component. |
quick | boolean | false | The kip-up. |
Returns
void
Nothing.
fightHit()
ts
fightHit(entity, hit): void;A blow on a fighter on the fight kit's door: the push on its joints, the stagger and the reaction take, as the fight pack's own blows do. Your rules decide the damage and the stun; this is the body's answer.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
hit | FightHitOptions | The blow. |
Returns
void
Nothing.
hit()
ts
hit(entity, blow): void;A blow. Every exported character has a physics body (its parts on the engine's physics); the nearest part to at takes the blow along direction, and the body reacts for real: a small hit flinches and recovers over about a second, a big one falls onto the floor and stays down until character.recover, a shot is sharper, a push shoves. Use this before writing a reaction of your own.
What happened comes back as anim-events on the clip ragdoll: hit, fell (the body came to rest on the floor), recovered.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
blow | { at: Vec3; direction?: Vec3; strength: number | "small" | "big" | "shot" | "big-shot"; } | Where it lands (at, world), which way it travels (direction, world; omitted: from the character's front) and how hard (strength: 'small', 'big', 'shot', 'big-shot', or a push's newton-seconds: 40 staggers, 90 and over floors). |
blow.at | Vec3 | - |
blow.direction? | Vec3 | - |
blow.strength | number | "small" | "big" | "shot" | "big-shot" | - |
Returns
void
Nothing.
Example
ts
character.hit(enemy, { at: swordTip, direction: swing, strength: 'small' });
character.hit(enemy, { at: swordTip, direction: swing, strength: 'big' }); // downlookAt()
ts
lookAt(
entity,
target,
weight?
): void;Aim the head and eyes at a world point.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity with a Character component. |
target | Vec3 | null | undefined | The point, or null to release and return to the idle. |
weight | number | 1 | Blend weight in 0..1. Default 1. |
Returns
void
Nothing.
motion()
ts
motion(entity, options?): void;How the movement system moves a character. A character with a motion set (its package's own, else the engine's shared one) is moved by whole takes of a performer matched to the velocity given to character.setState: its starts, stops and turns are the performer's own, its feet are held where they land. That is the default; this call changes it for one character: off, another set, whether the take carries the walker, the two dials, and which kind of stop it makes from a run. What is left out stays as it is.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
options | CharacterMotionOptions | What to change. |
Returns
void
Nothing.
Example
ts
character.motion(hero, { responsiveness: 0.9 }); // a snappier hero
character.motion(guard, { on: false }); // this one by the clips' blend, as before
character.motion(hero, { stop: 'hard' }); // from a run it brakes, instead of slowing to a standrecover()
ts
recover(entity): void;Back into the animation: a character that is down (or reacting) blends back over about a second, where it stood. Move the entity to where the body lies first (anim-event fell; the head and root joints read where it lies) to have it get up there.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
Returns
void
Nothing.
say()
ts
say(
entity,
text,
voice?,
visemes?
): void;Speak a line.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
text | string | Subtitle text; the host decides whether to show it. |
voice? | string | number | Manifest string id or handle of a voice line. |
visemes? | string | Viseme track as JSON, matching the bundle's space. |
Returns
void
Nothing.
setClipWeights()
ts
setClipWeights(
entity,
clips,
weights,
timeScale?
): void;Set explicit per-clip weights on the body layer.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity with a Character component. |
clips | readonly string[] | undefined | Clip names. |
weights | readonly number[] | Float32Array<ArrayBufferLike> | undefined | Positional weights; must be the same length as clips. |
timeScale | number | 1 | Playback rate for the whole layer. Default 1. |
Returns
void
Nothing.
setExpression()
ts
setExpression(
entity,
space,
weights
): void;Set facial expression coefficients.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
space | ExpressionSpace | Coordinate space: 52 ARKit, 387 GNM, or the 68-float view. |
weights | readonly number[] | Float32Array<ArrayBufferLike> | Coefficients; length must match the space. |
Returns
void
Nothing.
setState()
ts
setState(
entity,
state,
vx,
vy,
vz,
grounded?,
facing?
): void;Drive the locomotion state machine.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity with a Character component. |
state | string | undefined | State name, for example `'idle' |
vx | number | undefined | World-space velocity x, drives the locomotion blend. |
vy | number | undefined | World-space velocity y. |
vz | number | undefined | World-space velocity z. |
grounded | boolean | true | Whether the character is on the ground. |
facing? | number | undefined | Optional held world yaw in radians; permits backpedalling without turning. |
Returns
void
Nothing.
stopWalk()
ts
stopWalk(entity): void;Give up a walk to a spot: the character stops where it is, as its takes stop.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
Returns
void
Nothing.
walkTo()
ts
walkTo(
entity,
target,
how?
): void;Send a character to a spot: it turns, walks or runs there and arrives facing the way asked. The motion-event arrived (in ctx.events) says it got there; failed says why not; started and then done, both named stop, say when its stop begins and when it no longer travels; limited says once that the speed it is given (amount) is not the one asked. A velocity given to character.setState while it walks takes over.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a Character component. |
target | Vec3 | The spot, world space, on the floor. |
how | { arrive?: "easy" | "quick"; facing?: number; pace?: number; start?: "moving"; stop?: StopStyle; } | The facing to arrive with (facing, radians about +Y, 0 faces +Z; left out: as it arrives), the pace (pace, metres a second; left out: the set's own walk; above the speeds its walk covers it runs, when its set has a run and the spot is far enough to run to), how it stops (arrive: 'easy', the default, the takes' unhurried stops; 'quick', the shortest stops and turns the set has) and which kind of stop this one walk ends with (stop: 'gradual', it slows and stands upright; 'hard', it brakes; left out: the character's own, see character.motion). arrive says how soon it must be there, stop says which kind of stop; a 'quick' walk that states no stop stops as a quick walk always did. A kind is read on a run's stops: a walk's stop and a sprint's stop are the same under both on the engine's shared set. And how it is begun (start: 'moving', the game says the body is under way already: it comes out of a get-up, it was carried or thrown; the walk is then planned as of a body under way: no turn on the spot first, no start from standing; left out: as its takes have the body). |
how.arrive? | "easy" | "quick" | - |
how.facing? | number | - |
how.pace? | number | - |
how.start? | "moving" | - |
how.stop? | StopStyle | - |
Returns
void
Nothing.
Example
ts
character.walkTo(guide, { x: 2, y: 0, z: -3 }, { facing: Math.PI });
character.walkTo(rider, bikeSide, { pace: 3.4 }); // a run's pace: it runs there
character.walkTo(rider, bikeSide, { pace: 3.4, stop: 'hard' }); // and brakes at the spot
character.walkTo(rider, bikeSide, { pace: 3.4, start: 'moving' }); // out of a get-up: no turn on the spot firstExample
ts
import { character } from 'gameable';
character.setState(npc, 'walk', 0, 0, 1.4, true);
character.lookAt(npc, { x: 0, y: 1.6, z: 0 });Character
ts
const Character: CharacterStore;Splat character bundle attached to an entity.
CharacterActor
ts
const CharacterActor: ActorClass<{
animation: string;
character: string;
}>;An NPC character controller and splat bundle that stands and animates. An empty animation keeps the bundle's idle; a named clip uses the body layer. Initial props select the bundle and clip. No movement is requested.
Example
ts
spawnActor(ctx, CharacterActor, { position: { x: 0, y: 0, z: 0 },
props: { character: 'guide', animation: 'idle' } });CharacterPawn
ts
const CharacterPawn: ActorClass<{
character: string;
jumpZVelocity: number;
maxWalkSpeed: number;
orientRotationToMovement: boolean;
rotationRate: number;
}>;A possessable character bundle rooted in the guest movement capsule. Controllers supply addMovementInput and jump; setDesiredRotation holds a facing.
Example
ts
const fighter = spawnActor(ctx, CharacterPawn, {
position: { x: 0, y: 1, z: 0 },
props: { character: 'fighter', orientRotationToMovement: false },
});
setDesiredRotation(fighter.entity, Math.PI / 2);CheckpointVolume
ts
const CheckpointVolume: ActorClass<CheckpointProps>;Player checkpoint box. The point goes to the world group's respawn store, which respawnPlayer and KillHeight read.
Example
ts
spawnActor(ctx, CheckpointVolume, {position: {x: 3,y: 1,z: 0}, props: {order: 2}});conversation
ts
const conversation: object;Guest interview controls.
Type Declaration
command()
ts
command(
entity,
action,
character?,
text?
): void;Queue one control using the reusable command pool.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Interview entity. |
action | | "end" | "start" | "ask" | "interrupt" | "microphone-on" | "microphone-off" | undefined | Lifecycle or question action. |
character | string | '' | Host-configured id. |
text | string | '' | Question, if any. |
Returns
void
story()
ts
story(text): ConversationStory | null;Read a story event's text (the snapshot JSON). Null for anything that is not a version-1 snapshot.
Parameters
| Parameter | Type | Description |
|---|---|---|
text | string | The event's text. |
Returns
ConversationStory | null
The story, or null.
Example
ts
import { conversation } from 'gameable';
const story = conversation.story('{"schemaVersion":1,"revision":2,"currentPhase":"gate","completedObjectives":["told-truth"],"playerState":{},"transitionCause":""}');
const believed = story?.completedObjectives.includes('told-truth') ?? false;Example
ts
import { conversation } from "gameable";
conversation.command(npc, "start", "steward");cutscene
ts
const cutscene: object;The cutscene facade.
Type Declaration
play()
ts
play(asset, options?): number;Play a clip over the stage.
Parameters
| Parameter | Type | Description |
|---|---|---|
asset | string | number | Manifest id of a video entry, or its handle. |
options? | CutscenePlayOptions | Fades, skip, pause. |
Returns
number
The asset handle (the one a cutscene-event will name), or 0 when the id is unknown.
preload()
ts
preload(asset): number;Fetch a clip ahead of time so play starts the moment it is called.
Parameters
| Parameter | Type | Description |
|---|---|---|
asset | string | number | Manifest id of a video entry, or its handle. |
Returns
number
The asset handle, or 0 when the id is unknown.
skip()
ts
skip(): void;End the clip playing now (it comes back as skipped).
Returns
void
Nothing.
Example
ts
import { cutscene } from 'gameable';
cutscene.preload('kael-falls'); // when the fight starts
cutscene.play('kael-falls', { fadeIn: 300, skippable: true }); // when the boss falls
// later, in the events: { tag: 'cutscene-event', val: { asset, kind: 'ended' | 'skipped' | 'failed', seconds } }DamageVolume
ts
const DamageVolume: ActorClass<{
damagePerSecond: number;
enabled: boolean;
halfExtents: number[];
interval: number;
type: string;
}>;Interval damage: one interval's damage on entry, then every interval seconds. Disabled volumes pause damage; enabling starts a fresh interval with an immediate hit.
Example
ts
spawnActor(ctx, DamageVolume, { position: { x: 0, y: 0, z: 0 }, props: { damagePerSecond: 10, type: 'fire' } });DEFAULT_CHARACTER_MOVEMENT
ts
const DEFAULT_CHARACTER_MOVEMENT: Readonly<CharacterMovementSettings>;Movement defaults in metres; gravity=-9.81 and terminal=55 set acceleration and fall-speed limits. Capsule halfHeight measures half the cylinder, excluding its hemispherical caps (total half-height is 0.88).
Example
ts
const speed = DEFAULT_CHARACTER_MOVEMENT.maxWalkSpeed; // 6 m/sDEFAULT_MAX_ENTITIES
ts
const DEFAULT_MAX_ENTITIES: 4096 = 4096;Default entity ceiling. Every built-in component array is this long.
DEFAULT_MAX_PLAYERS
ts
const DEFAULT_MAX_PLAYERS: 16 = 16;The highest player id a guest makes a slot for when net.maxPlayers is not in game-config.options.
Example
ts
import { DEFAULT_MAX_PLAYERS } from 'gameable';
const options = JSON.stringify({ net: { maxPlayers: DEFAULT_MAX_PLAYERS * 2 } });DEFAULT_ROOM_SEATS
ts
const DEFAULT_ROOM_SEATS: 8 = 8;Seats in a room when the game declares features.multiplayer without a maxPlayers.
Example
ts
import { DEFAULT_ROOM_SEATS, defineGame, roomSeats } from 'gameable';
const game = defineGame({ features: { multiplayer: true } });
roomSeats(game) === DEFAULT_ROOM_SEATS; // truedefaultDriveTuning
ts
const defaultDriveTuning: Readonly<DriveTuning>;Default arcade pursuit tuning. Recovery stops after three reverse attempts.
Example
ts
const tuning = { ...defaultDriveTuning, stuckSeconds: 4 };DirectionalLight
ts
const DirectionalLight: ActorClass<{
color: number[];
intensity: number;
}>;Placeable light placeholder until the host accepts guest light commands. Emits one warning per instance at beginPlay and preserves authored props.
Example
ts
spawnActor(ctx, DirectionalLight, { position: { x: 0, y: 2, z: 0 } });Door
ts
const Door: ActorClass<DoorProps>;Interactable kinematic door. A successful unlock remains unlocked, including after auto-close.
Example
ts
spawnActor(ctx, Door, {position: {x: 0,y: 1,z: 4}, props: {openYaw: 90, seconds: 1}});DoubleDoor
ts
const DoubleDoor: ActorClass<DoubleDoorProps>;Two half-width wood leaves hinged on their outer edges, swinging away together.
Example
ts
spawnActor(ctx, DoubleDoor, { position: { x: 0, y: 1.05, z: 0 } });ease
ts
const ease: object;Standard easings.net curves. Inputs are clamped; back and elastic may overshoot. Every curve returns exactly zero and one at its endpoints.
Type Declaration
backOut()
ts
readonly backOut(t): number;Parameters
| Parameter | Type |
|---|---|
t | number |
Returns
number
bounceOut()
ts
readonly bounceOut(t): number;Parameters
| Parameter | Type |
|---|---|
t | number |
Returns
number
cubicIn()
ts
readonly cubicIn(t): number;Parameters
| Parameter | Type |
|---|---|
t | number |
Returns
number
cubicInOut()
ts
readonly cubicInOut(t): number;Parameters
| Parameter | Type |
|---|---|
t | number |
Returns
number
cubicOut()
ts
readonly cubicOut(t): number;Parameters
| Parameter | Type |
|---|---|
t | number |
Returns
number
elasticOut()
ts
readonly elasticOut(t): number;Parameters
| Parameter | Type |
|---|---|
t | number |
Returns
number
linear()
ts
readonly linear(t): number;Parameters
| Parameter | Type |
|---|---|
t | number |
Returns
number
quadIn()
ts
readonly quadIn(t): number;Parameters
| Parameter | Type |
|---|---|
t | number |
Returns
number
quadInOut()
ts
readonly quadInOut(t): number;Parameters
| Parameter | Type |
|---|---|
t | number |
Returns
number
quadOut()
ts
readonly quadOut(t): number;Parameters
| Parameter | Type |
|---|---|
t | number |
Returns
number
sineIn()
ts
readonly sineIn(t): number;Parameters
| Parameter | Type |
|---|---|
t | number |
Returns
number
sineInOut()
ts
readonly sineInOut(t): number;Parameters
| Parameter | Type |
|---|---|
t | number |
Returns
number
sineOut()
ts
readonly sineOut(t): number;Parameters
| Parameter | Type |
|---|---|
t | number |
Returns
number
Example
ts
import { ease } from 'gameable';
console.log(ease.quadIn(0.5)); // 0.25Enemy
ts
const Enemy: Record<string, never> = {};Tag: a hostile entity.
EXPRESSION_DIMS
ts
const EXPRESSION_DIMS: Readonly<Record<ExpressionSpace, number>>;Coefficient counts each expression space expects.
FlyingPawn
ts
const FlyingPawn: ActorClass<{
collision: boolean;
maxSpeed: number;
}>;A flying pawn with an optional blocking kinematic sphere.
Example
ts
const pawn = spawnActor(ctx, FlyingPawn, { position: { x: 0, y: 1, z: 0 } });ForceField
ts
const ForceField: ActorClass<ForceFieldProps>;World actor applying radial force, with an optional first-step impulse.
Example
ts
spawnActor(ctx, ForceField, { position: { x: 0, y: 0, z: 0 }, props: { fireOnBeginPlay: true } });GameMode
ts
const GameMode: ActorClass<GameModeProps>;Authority match rules, login, scoring and respawning for existing player bodies.
Example
ts
spawnActor(ctx, GameMode, { position, props: { matchTime: 120 } });GameState
ts
const GameState: ActorClass<GameStateProps>;Public match state maintained by GameMode.
Example
ts
const remaining = gameState()?.props.remaining;Gate
ts
const Gate: ActorClass<GateProps>;A barred portcullis on one kinematic body, rising into the ceiling on signals.
Example
ts
spawnActor(ctx, Gate, { position: { x: 0, y: 1.5, z: 0 }, props: { opensWhen: ['switch'] } });Health
ts
const Health: HealthStore;Hit points.
HeightFog
ts
const HeightFog: ActorClass<{
fogColor: readonly [number, number, number];
fogDensity: number;
}>;Exponential fog through the shared post composer; the host has no height falloff. Declare features: { vfx: true }. Do not also call ctx.vfx.post when using fog or volumes. Room authorities skip it.
Example
ts
spawnActor(ctx, HeightFog, { position: { x: 0, y: 0, z: 0 } });HingedDoor
ts
const HingedDoor: ActorClass<HingedDoorProps>;A painted kinematic leaf swinging around its edge.
Example
ts
spawnActor(ctx, HingedDoor, { position: { x: 0, y: 1.05, z: 0 } });hud
ts
const hud: object;The HUD facade: writes the frame's HUD.
Type Declaration
clear()
ts
clear(): void;Drop the HUD: emit an empty model this frame.
Idempotent — calling it every frame emits {} once, exactly like set.
Returns
void
Nothing.
invalidate()
ts
invalidate(): void;Forget what the host has seen, so the next set emits even if the model did not change. Use it after the host reloaded its overlay.
On its own it sends nothing: the next set does. To send an empty model now, call clear().
Returns
void
Nothing.
set()
ts
set(model): boolean;Set the HUD model for this frame.
Nested plain objects are compared by value four levels down, so a model rebuilt inline every frame is recognised as unchanged. Arrays and class instances are compared by identity: keep those out of the model, or build them once and mutate nothing.
Parameters
| Parameter | Type | Description |
|---|---|---|
model | Record<string, unknown> | A JSON-serialisable object. |
Returns
boolean
True when the model changed and JSON will cross this frame.
Example
ts
import { hud } from 'gameable';
hud.set({ health: 100, ammo: 30 }); // emitted once
hud.set({ health: 100, ammo: 30 }); // unchanged, nothing crossesinput
ts
const input: object;The keyboard, mouse and gamepad facade: the local player's input. That is frame-input.input in a single-player game and on the authority, and the local player's slot of frame-input.players on a client.
Type Declaration
touch
ts
touch: object;Fingers on a touch screen, as the host's touch layer packs them: the first finger is the pointer (mouse), a tap is pressed('Tap'), and the thumb sticks, the pinch and the turn are here.
touch.active
Get Signature
ts
get active(): boolean;Is a finger on the screen? (The touch pad is connected.)
Returns
boolean
True while any finger is down.
touch.pinch
Get Signature
ts
get pinch(): number;Two fingers' pinch this step, as a scale factor: over 1 the fingers moved apart (zoom in), under 1 together, exactly 1 with no pinch.
Returns
number
The scale factor.
touch.turn
Get Signature
ts
get turn(): number;Two fingers' turn this step, in radians, counter-clockwise on the screen positive.
Returns
number
The turn.
touch.stick()
ts
stick(side): Axis2;A thumb stick's push.
Parameters
| Parameter | Type | Description |
|---|---|---|
side | "left" | "right" | The left stick (movement) or the right one (the camera). |
Returns
A pooled { x, y }, -1..1, y up the screen positive. Never retain it.
control
Get Signature
ts
get control(): Readonly<NonNullable<InputState["control"]>>;Received page control for this frame. Owned by the SDK; read during the tick.
Returns
Readonly<NonNullable<InputState["control"]>>
The control state received with this input sequence.
focused
Get Signature
ts
get focused(): boolean;Does the canvas have focus? Treat input as neutral when it does not.
Returns
boolean
True while the canvas is focused.
mods
Get Signature
ts
get mods(): InputMods;Keyboard modifier state.
Returns
The modifiers for this frame.
mouse
Get Signature
ts
get mouse(): MouseState;Pointer position, per-frame delta, wheel and button bitsets.
Returns
The mouse state for this frame. Owned by the SDK; never retain it.
action()
ts
action(name): ActionState;Read a declared button into pooled storage. Unknown names throw.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Declared button action name. |
Returns
Pooled button state; read immediately.
axis2()
ts
axis2(
negX,
posX?,
negY?,
posY?,
stick?
): Axis2;Pass a declared axis action name alone, or four keys. A two-axis reading built from four keys, plus a thumb stick on a touch screen: the left one by default, so axis2('A', 'D', 'S', 'W') moves on a phone with no other binding. Pass 'right' for a camera axis, 'none' for keys only. With the left stick and opposing WASD/arrow movement pairs, uses combined movement (both key sets, left touch and first physical pad, radial deadzone and unit-circle clamp), with each binding's requested sign. Page control supplies that same movement when present. Other bindings read only their four keys and the requested touch stick.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
negX | string | undefined | Declared axis name, or key driving x negative, e.g. 'A'. |
posX? | string | undefined | Key that drives x positive, for example 'D'. |
negY? | string | undefined | Key that drives y negative, for example 'S'. |
posY? | string | undefined | Key that drives y positive, for example 'W'. |
stick? | StickSide | 'left' | Which thumb stick to add, 'left' by default. |
Returns
A pooled { x, y } with components in -1..1. Never retain it.
gamepad()
ts
gamepad(index):
| {
axes: ArrayLike<number>;
buttons: number;
connected: boolean;
index: number;
pressed: number;
released: number;
}
| null;One connected gamepad.
Parameters
| Parameter | Type | Description |
|---|---|---|
index | number | Navigator gamepad index. |
Returns
| { axes: ArrayLike<number>; buttons: number; connected: boolean; index: number; pressed: number; released: number; } | null
The gamepad, or null when nothing is connected at that index. Owned by the SDK; never retain it.
isDown()
ts
isDown(key): boolean;Is the key held this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
key | string | A DOM code ('KeyW'), a bare letter/digit ('W', '1') or an alias ('Shift', 'Esc'). |
Returns
boolean
True while the key is down.
mouseDown()
ts
mouseDown(button): boolean;Is a mouse button held?
Parameters
| Parameter | Type | Description |
|---|---|---|
button | number | A MOUSE_BUTTONS value, or a raw bit mask. |
Returns
boolean
True while the button is down.
mousePressed()
ts
mousePressed(button): boolean;Did a mouse button go down this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
button | number | A MOUSE_BUTTONS value, or a raw bit mask. |
Returns
boolean
True on the frame the button went down.
mouseReleased()
ts
mouseReleased(button): boolean;Did a mouse button come up this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
button | number | A MOUSE_BUTTONS value, or a raw bit mask. |
Returns
boolean
True on the frame the button came up.
pressed()
ts
pressed(key): boolean;Did the key go down this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
key | string | A key name. |
Returns
boolean
True on the frame the key went down.
released()
ts
released(key): boolean;Did the key come up this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
key | string | A key name. |
Returns
boolean
True on the frame the key came up.
Example
ts
import { input } from 'gameable';
const move = input.axis2('A', 'D', 'S', 'W'); // x = strafe, y = forward
if (input.pressed('Space')) jump();
if (input.mouseDown(1)) fire();Interactable
ts
const Interactable: ActorClass<InteractableProps>;Ready interaction point; derive a class with onInteract for game-specific behavior.
Example
ts
const Switch = defineActor('Switch', {...Interactable.spec, onInteract(self, who, ctx) { self.props.enabled = false; }});IS_COMPONENT_GUEST
ts
const IS_COMPONENT_GUEST: boolean;True when this realm looks like the QuickJS component guest rather than V8.
Decided once, before anything is polyfilled: a realm with neither console nor TextEncoder is componentize-qjs. It is the only realm whose Math.random the prelude is allowed to replace — patching the global in V8 would reach vitest, Vite and the host application too.
JumpPad
ts
const JumpPad: ActorClass<JumpPadProps>;Launch an entering character body or entity carrying Velocity. Player movement systems must preserve external launches.
Example
ts
spawnActor(ctx, JumpPad, {position: {x: 0,y: 0,z: 0}, props: {launch: [0,15,0]}});KEY_BITS
ts
const KEY_BITS: 256 = 256;Number of key bits the WIT key-state bitsets can carry.
KEY_COUNT
ts
const KEY_COUNT: number = KEY_NAMES.length;Number of key names currently assigned.
KEY_NAMES
ts
const KEY_NAMES: readonly string[];Every key name in index order. The array index is the bit index.
Do not reorder; append only.
KEY_WORDS
ts
const KEY_WORDS: number;Number of u32 words in one key-state bitset.
KillVolume
ts
const KillVolume: ActorClass<{
halfExtents: number[];
}>;Recover vehicles through their circuit or spawn policy, respawn players, destroy other actors.
Example
ts
spawnActor(ctx, KillVolume, { position: { x: 0, y: -10, z: 0 }, props: { halfExtents: [100, 1, 100] } });LAYER_KEYS
ts
const LAYER_KEYS: readonly ["defaultLayer", "staticGeometry", "player", "enemy", "projectile", "pickup", "trigger", "character", "debris", "water", "user0", "user1", "user2", "user3", "user4", "user5"];Every WIT collision-layers member, in declaration order.
Bit i of the physics module's numeric layer/mask is member i of this list. It is a contract between the guest, which writes the flags record, and the host, which folds it into a bitmask — so both sides import this one list rather than keeping a copy each.
Example
ts
import { LAYER_KEYS } from 'gameable';
const bit = LAYER_KEYS.indexOf('enemy'); // 3LevelDoor
ts
const LevelDoor: ActorClass<LevelDoorProps>;A kit door that loads a level and places the party at its arrival marker. Travel runs after actor steps; onTravel can clear or redirect toLevel first.
Example
ts
spawnActor(ctx, LevelDoor, { position: { x: 0, y: 1.05, z: 0 }, props: { toLevel: 'cave' } });levels
ts
const levels: LevelsFacade;The levels facade, ctx.levels.
Example
ts
import { defineGame, levels } from 'gameable';
export default defineGame({
levels: { start: startLevel, cave: caveLevel },
systems: [(ctx) => { if (ctx.input.pressed('KeyN')) levels.load(ctx, 'cave'); }],
});LevelSettings
ts
const LevelSettings: ActorClass<{
killHeight: number | false | null;
}>;Level-wide settings. Place at most one LevelSettings actor per level.
Example
ts
spawnActor(ctx, LevelSettings, { position: { x: 0, y: 0, z: 0 }, props: { killHeight: -100 } });Lever
ts
const Lever: ActorClass<LeverProps>;An interactable signal source with a moving, draw-only handle.
Example
ts
spawnActor(ctx, Lever, { position: { x: 0, y: 1, z: 0 }, name: 'lever1' });MAIN_LEVEL
ts
const MAIN_LEVEL: "main" = 'main';The name a bare defineGame({ level }) is declared under.
MeshActor
ts
const MeshActor: ActorClass<{
asset: string;
collision: "none" | "block";
halfExtents: [number, number, number];
scale: [number, number, number];
tint: [number, number, number];
}>;A prop mesh with optional fixed box collision. Collider dimensions are authored half extents in world metres; the guest manifest exposes no collider geometry. Scale affects the mesh only. Props configure the initial components at spawn.
Example
ts
spawnActor(ctx, MeshActor, { position: { x: 0, y: 0, z: 0 },
props: { asset: 'crate', collision: 'block', halfExtents: [1, 1, 1] } });MOUSE_BUTTONS
ts
const MOUSE_BUTTONS: Readonly<{
BACK: 8;
FORWARD: 16;
LEFT: 1;
MIDDLE: 4;
RIGHT: 2;
}>;Mouse button bit positions, matching mouse-state.buttons.
MovingPlatform
ts
const MovingPlatform: ActorClass<MovingPlatformProps>;Kinematic box moved by the reusable path component. Teleports supply no ground velocity; translation carries supported player feet explicitly, like race movers.
Example
ts
spawnActor(ctx, MovingPlatform, {position: {x: 0,y: 0,z: 0}});music
ts
const music: object;Music and the guest's beat clock.
Type Declaration
bar
Get Signature
ts
get bar(): number;Last heard bar number.
Returns
number
beat
Get Signature
ts
get beat(): number;Last heard beat number.
Returns
number
beatInBar
Get Signature
ts
get beatInBar(): number;Last heard beat within the bar.
Returns
number
beatsPerBar
Get Signature
ts
get beatsPerBar(): number;Beats per bar of the last playback request.
Returns
number
bpm
Get Signature
ts
get bpm(): number;Tempo of the last playback request.
Returns
number
layer()
ts
layer(
index,
gain,
fadeMs?
): void;Change a stem gain.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
index | number | undefined | Stem index. |
gain | number | undefined | Linear gain. |
fadeMs | number | 0 | Ramp duration. |
Returns
void
nearestBeat()
ts
nearestBeat(): number;The number of the beat nearest to now, as heard: the beat offsetMs() measures from. A press just before beat 12 gives 12, just after it also 12, so a chart of beat numbers is judged with nearestBeat() === note and Math.abs(offsetMs()).
Returns
number
The beat number, or NaN before a beat or without a tempo.
Example
ts
import { music } from 'gameable';
if (music.nearestBeat() === 12 && Math.abs(music.offsetMs()) <= 45) console.log('perfect');offsetMs()
ts
offsetMs(): number;Signed milliseconds since the nearest beat; negative when it is still ahead.
Returns
number
Offset, or NaN before a beat or without a tempo.
play()
ts
play(assets, options?): void;Stream a track or playlist.
Parameters
| Parameter | Type | Description |
|---|---|---|
assets | string | number | readonly (string | number)[] | Manifest ids or handles. |
options? | MusicOptions | Playback options. |
Returns
void
stems()
ts
stems(assets, options?): void;Play synchronized stems.
Parameters
| Parameter | Type | Description |
|---|---|---|
assets | readonly (string | number)[] | Manifest ids or handles. |
options? | StemOptions | Playback options and gains. |
Returns
void
stop()
ts
stop(fadeMs?): void;Stop music.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
fadeMs | number | 0 | Fade duration. |
Returns
void
Example
ts
import { music } from 'gameable';
music.play('theme', { bpm: 120 });
music.layer(1, 0.5, 200);NavigationBounds
ts
const NavigationBounds: ActorClass<NavigationBoundsProps>;Axis-aligned navigation bounds. Multiple volumes build one grid over their union; the first volume supplies agent tuning and build mode. Physics baking retries for ten seconds before falling back to flat ground. Bounds are rebuilt on spawn/destruction.
Example
ts
spawnActor(ctx, NavigationBounds, { position: { x: 0, y: 0, z: 0 }, props: { build: 'flat' } });NavigationLink
ts
const NavigationLink: ActorClass<NavigationLinkProps>;Adds an off-grid connection while alive. Both endpoint cells must be walkable. Bounds rebuilds and save/restore re-register the link in the new shared grid.
Example
ts
spawnActor(ctx, NavigationLink, { position: { x: -2, y: 0, z: 0 }, props: { end: [4, 0, 0] } });NavigationModifier
ts
const NavigationModifier: ActorClass<NavigationModifierProps>;Blocks or weights its XZ footprint in the shared navigation grid while alive.
Example
ts
spawnActor(ctx, NavigationModifier, { position: { x: 2, y: 0, z: 0 } });NO_SEAT
ts
const NO_SEAT: -1 = -1;The seat of a controller that belongs to no player (an AI controller).
PACKAGE
ts
const PACKAGE: "@gameable/sdk";Package identity marker.
Example
ts
import { PACKAGE } from 'gameable';
console.log(PACKAGE); // 'gameable'ParticleEffect
ts
const ParticleEffect: ActorClass<ParticleEffectProps>;Persistent ParticleEffect preset; activate/deactivate with the component helpers. Declare features: { vfx: true }. Emitter handles live in snapshot-safe component state.
Example
ts
spawnActor(ctx, ParticleEffect, { position: { x: 0, y: 0, z: 0 }, props: { preset: 'smoke' } });physics
ts
const physics: object;Physics queries and body commands.
Type Declaration
ALL_LAYERS
ts
ALL_LAYERS: CollisionLayers;Every collision layer, for queries that should hit anything.
vehicle
ts
vehicle: object;Host arcade handling on guest body handles.
vehicle.create()
ts
create(
body,
settings,
initialState?
): Readonly<VehicleState>;Attach once to an existing dynamic body. State is borrowed until removal.
Parameters
| Parameter | Type |
|---|---|
body | number |
settings | VehicleSettings |
initialState? | Readonly<VehicleState> |
Returns
Readonly<VehicleState>
Example
ts
physics.vehicle.create(body, settings);vehicle.remove()
ts
remove(body): void;Remove handling; the chassis remains alive. Safe to repeat.
Parameters
| Parameter | Type |
|---|---|
body | number |
Returns
void
Example
ts
physics.vehicle.remove(body);vehicle.reset()
ts
reset(
body,
position,
rotation
): void;Teleport and clear motion, controls and handling history.
Parameters
| Parameter | Type |
|---|---|
body | number |
position | Vec3 |
rotation | Quat |
Returns
void
Example
ts
physics.vehicle.reset(body, position, rotation);vehicle.setInput()
ts
setInput(
body,
controls,
gripScale?
): void;Submit transient controls; omitted steps use the host parking brake.
Parameters
| Parameter | Type | Default value |
|---|---|---|
body | number | undefined |
controls | Readonly<VehicleInput> | undefined |
gripScale | number | 1 |
Returns
void
Example
ts
physics.vehicle.setInput(body, controls, 0.5);vehicle.state()
ts
state(body): Readonly<VehicleState> | undefined;Borrow the last post-step state without allocating.
Parameters
| Parameter | Type |
|---|---|
body | number |
Returns
Readonly<VehicleState> | undefined
Example
ts
const speed = physics.vehicle.state(body)?.speed;applyImpulse()
ts
applyImpulse(
entity,
x,
y,
z,
atX?,
atY?,
atZ?
): void;Apply a one-shot impulse.
With no application point the impulse acts at the centre of mass. Give one — all three coordinates — to apply it off-centre and impart spin.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a body. |
x | number | Impulse x, newton-seconds. |
y | number | Impulse y. |
z | number | Impulse z. |
atX? | number | World-space application point x, or omit for the centre of mass. |
atY? | number | Application point y. |
atZ? | number | Application point z. |
Returns
void
Nothing.
boxCast()
ts
boxCast(
position,
halfExtents,
rotation,
direction,
maxDistance,
mask?,
ignoreEntity?
): RayHit | null;Cast a box with a quaternion orientation.
Parameters
| Parameter | Type | Description |
|---|---|---|
position | Vec3 | World-space query centre. |
halfExtents | Vec3 | Box half-size in metres. |
rotation | Quat | Unit quaternion orientation. |
direction | Vec3 | Sweep direction; need not be normalised. |
maxDistance | number | Maximum travel in metres. |
mask? | CollisionLayers | Layers to consider, or every layer when omitted. |
ignoreEntity? | number | Entity to skip. |
Returns
RayHit | null
The closest hit, or null on a miss; hit.distance is the shape travel in metres.
Example
ts
import { defineGame, physics } from 'gameable';
export default defineGame({
init() {
const position = { x: 0, y: 1, z: 0 };
const rotation = { x: 0, y: 0, z: 0, w: 1 };
const forward = { x: 0, y: 0, z: 1 };
const halfExtents = { x: 0.5, y: 0.5, z: 0.5 };
const hit = physics.boxCast(position, halfExtents, rotation, forward, 1);
console.log('can the crate be pushed forward one metre?', hit === null);
},
});capsuleCast()
ts
capsuleCast(
position,
radius,
halfHeight,
rotation,
direction,
maxDistance,
mask?,
ignoreEntity?
): RayHit | null;Cast a capsule; halfHeight is half its straight segment.
Parameters
| Parameter | Type | Description |
|---|---|---|
position | Vec3 | World-space query centre. |
radius | number | Radius in metres. |
halfHeight | number | Half the straight capsule segment in metres. |
rotation | Quat | Unit quaternion orientation. |
direction | Vec3 | Sweep direction; need not be normalised. |
maxDistance | number | Maximum travel in metres. |
mask? | CollisionLayers | Layers to consider, or every layer when omitted. |
ignoreEntity? | number | Entity to skip. |
Returns
RayHit | null
The closest hit, or null on a miss; hit.distance is the shape travel in metres.
Example
ts
import { defineGame, physics } from 'gameable';
export default defineGame({
init() {
const position = { x: 0, y: 1, z: 0 };
const rotation = { x: 0, y: 0, z: 0, w: 1 };
const forward = { x: 0, y: 0, z: 1 };
const hit = physics.capsuleCast(position, 0.3, 0.6, rotation, forward, 0.4);
console.log('can the character step here?', hit === null);
},
});distance()
ts
distance(
a,
b,
options
): number;Create a distance joint. Bodyless entities return 0; b=0 anchors to the world. With no limits, this is a rigid rod that keeps its initial length. Set min/max in metres to constrain a rope or rod length.
Parameters
| Parameter | Type | Description |
|---|---|---|
a | number | First entity, with a physics body. |
b | number | Second entity, or 0 to join to the world. |
options | { anchor: Vec3; anchorB?: Vec3; max?: number; min?: number; spring?: JointSpring; } | Joint or motor settings. |
options.anchor | Vec3 | World-space anchor at creation. |
options.anchorB? | Vec3 | World-space second distance-joint end. |
options.max? | number | Upper linear limit in metres. |
options.min? | number | Lower linear limit in metres. |
options.spring? | JointSpring | Limit frequency in Hz and damping ratio. |
Returns
number
The joint id, or 0 when either entity has no body (b = 0 means the world).
Example
ts
import { defineGame, physics, prefab } from 'gameable';
const Weight = prefab({ body: { shape: 'sphere', kind: 'dynamic' } });
export default defineGame({
init(ctx) {
const weight = ctx.spawn(Weight, { x: 0, y: 1, z: 0 });
// No limits: a rigid rod that keeps its initial 3 metre length.
physics.distance(weight, 0, {
anchor: { x: 0, y: 1, z: 0 },
anchorB: { x: 0, y: 4, z: 0 },
});
},
});fixed()
ts
fixed(
a,
b,
options?
): number;Create a fixed joint. Bodyless entities return 0; b=0 anchors to the world.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
a | number | undefined | First entity, with a physics body. |
b | number | undefined | Second entity, or 0 to join to the world. |
options | { anchor?: Vec3; } | EMPTY_JOINT_OPTIONS | Joint or motor settings. |
options.anchor? | Vec3 | undefined | World-space anchor at creation. |
Returns
number
The joint id, or 0 when either entity has no body (b = 0 means the world).
Example
ts
import { defineGame, physics, prefab } from 'gameable';
const Crate = prefab({ body: { shape: 'box', kind: 'dynamic' } });
export default defineGame({
init(ctx) {
const crateA = ctx.spawn(Crate, { x: 0, y: 1, z: 0 });
const crateB = ctx.spawn(Crate, { x: 1.1, y: 1, z: 0 });
physics.fixed(crateA, crateB); // Weld the two crates together.
},
});hinge()
ts
hinge(
a,
b,
options
): number;Create a hinge joint. Bodyless entities return 0; b=0 anchors to the world.
Values and targets measure how far entity a has moved relative to entity b (or the world). Slider positive is along +axis; hinge positive follows the right-hand rule about +axis. Rotation values and rotational position targets are degrees; angular velocity targets are degrees per second.
Parameters
| Parameter | Type | Description |
|---|---|---|
a | number | First entity, with a physics body. |
b | number | Second entity, or 0 to join to the world. |
options | { anchor: Vec3; axis: Vec3; friction?: number; maxDeg?: number; minDeg?: number; spring?: JointSpring; } | Joint or motor settings. |
options.anchor | Vec3 | World-space anchor at creation. |
options.axis | Vec3 | World-space axis; positive motion follows +axis. |
options.friction? | number | Maximum friction torque in N·m. |
options.maxDeg? | number | Upper angular limit in degrees. |
options.minDeg? | number | Lower angular limit in degrees. |
options.spring? | JointSpring | Limit frequency in Hz and damping ratio. |
Returns
number
The joint id, or 0 when either entity has no body (b = 0 means the world).
Example
ts
import { defineGame, physics, prefab } from 'gameable';
const Door = prefab({ body: { shape: 'box', dims: [0.5, 1, 0.05], kind: 'dynamic' } });
export default defineGame({
init(ctx) {
const door = ctx.spawn(Door, { x: 0.5, y: 1, z: 0 });
physics.hinge(door, 0, {
anchor: { x: 0, y: 1, z: 0 },
axis: { x: 0, y: 1, z: 0 },
minDeg: -90,
maxDeg: 90,
});
},
});isGrounded()
ts
isGrounded(entity): boolean;Actual walkable ground contact from the last host physics step. No host call. Unknown, steep and unsupported contacts return false, even at a jump apex.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Character entity. |
Returns
boolean
Whether the character is supported by walkable ground.
jointValue()
ts
jointValue(id, axis?): number | null;Read a joint coordinate, degrees for rotation, metres for translation or distance length. Distance returns the current unsigned length; unavailable coordinates return null.
Values and targets measure how far entity a has moved relative to entity b (or the world). Slider positive is along +axis; hinge positive follows the right-hand rule about +axis. Rotation values and rotational position targets are degrees; angular velocity targets are degrees per second.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
id | number | undefined | Guest-minted joint handle. |
axis | number | 0 | Joint axis: 0 for one-axis joints, 0 through 5 for six-dof. |
Returns
number | null
The coordinate in degrees for rotation or metres for translation/length, or null when unavailable.
Example
ts
import { defineGame, physics, prefab } from 'gameable';
const Lever = prefab({ body: { shape: 'box', kind: 'dynamic' } });
let leverJoint = 0;
export default defineGame({
init(ctx) {
const lever = ctx.spawn(Lever, { x: 0, y: 1, z: 0 });
leverJoint = physics.hinge(lever, 0, {
anchor: { x: 0, y: 1, z: 0 },
axis: { x: 1, y: 0, z: 0 },
minDeg: -90,
maxDeg: 90,
});
},
systems: [
() => {
const angle = physics.jointValue(leverJoint);
const isLeverDown = angle !== null && angle < -80;
if (isLeverDown) console.log('lever down');
},
],
});moveCharacter()
ts
moveCharacter(
entity,
vx,
vy,
vz,
jump?,
crouch?,
maxSlopeDeg?
): void;Drive a character body for this step.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity whose body was created with kind: 'character'. |
vx | number | undefined | Desired world-space velocity x, metres per second. |
vy | number | undefined | Desired world-space velocity y. |
vz | number | undefined | Desired world-space velocity z. |
jump | boolean | false | Request a jump this step. |
crouch | boolean | false | Request a crouch this step. |
maxSlopeDeg | number | 45 | Maximum walkable slope. |
Returns
void
Nothing.
overlapBox()
ts
overlapBox(
position,
halfExtents,
rotation,
maxResults?,
mask?,
ignoreEntity?
): readonly OverlapHit[];Overlap a box.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
position | Vec3 | undefined | World-space query centre. |
halfExtents | Vec3 | undefined | Box half-size in metres. |
rotation | Quat | undefined | Unit quaternion orientation. |
maxResults | number | 16 | Maximum number of hits. |
mask? | CollisionLayers | undefined | Layers to consider, or every layer when omitted. |
ignoreEntity? | number | undefined | Entity to skip. |
Returns
readonly OverlapHit[]
The overlapping hits, nearest first; an empty list when nothing overlaps.
Example
ts
import { defineGame, physics } from 'gameable';
export default defineGame({
init() {
const position = { x: 0, y: 1, z: 0 };
const rotation = { x: 0, y: 0, z: 0, w: 1 };
const halfExtents = { x: 2, y: 1, z: 2 };
const hits = physics.overlapBox(position, halfExtents, rotation);
console.log(
'bodies in this area',
hits.map((hit) => hit.entity),
);
},
});overlapCapsule()
ts
overlapCapsule(
position,
radius,
halfHeight,
rotation,
maxResults?,
mask?,
ignoreEntity?
): readonly OverlapHit[];Overlap a capsule.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
position | Vec3 | undefined | World-space query centre. |
radius | number | undefined | Radius in metres. |
halfHeight | number | undefined | Half the straight capsule segment in metres. |
rotation | Quat | undefined | Unit quaternion orientation. |
maxResults | number | 16 | Maximum number of hits. |
mask? | CollisionLayers | undefined | Layers to consider, or every layer when omitted. |
ignoreEntity? | number | undefined | Entity to skip. |
Returns
readonly OverlapHit[]
The overlapping hits, nearest first; an empty list when nothing overlaps.
Example
ts
import { defineGame, physics } from 'gameable';
export default defineGame({
init() {
const position = { x: 0, y: 1, z: 0 };
const rotation = { x: 0, y: 0, z: 0, w: 1 };
const hits = physics.overlapCapsule(position, 2, 1, rotation);
console.log(
'bodies in this area',
hits.map((hit) => hit.entity),
);
},
});overlapShape()
ts
overlapShape(
shape,
position,
rotation,
maxResults?,
mask?,
ignoreEntity?
): readonly OverlapHit[];Overlap a primitive shape.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
shape | QueryShape | undefined | Primitive shape and its dimensions in metres. |
position | Vec3 | undefined | World-space query centre. |
rotation | Quat | undefined | Unit quaternion orientation. |
maxResults | number | 16 | Maximum number of hits. |
mask? | CollisionLayers | undefined | Layers to consider, or every layer when omitted. |
ignoreEntity? | number | undefined | Entity to skip. |
Returns
readonly OverlapHit[]
Hits nearest first, with the deepest contact point on each other body and real penetration depth (bounds centre and zero depth if no contact is available).
Example
ts
import { defineGame, physics } from 'gameable';
export default defineGame({
init() {
const position = { x: 0, y: 1, z: 0 };
const rotation = { x: 0, y: 0, z: 0, w: 1 };
const shape = { kind: 'cylinder', halfExtents: { x: 2, y: 1, z: 0 } } as const;
const hits = physics.overlapShape(shape, position, rotation);
console.log(
'bodies in this area',
hits.map((hit) => hit.entity),
);
},
});overlapSphere()
ts
overlapSphere(
center,
radius,
maxResults?,
mask?,
ignoreEntity?
): readonly OverlapHit[];Bodies overlapping a sphere, nearest first.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
center | Vec3 | undefined | Sphere centre. |
radius | number | undefined | Sphere radius in metres. |
maxResults | number | 16 | Cap on returned hits. |
mask? | CollisionLayers | undefined | Layers to consider; defaults to every layer. |
ignoreEntity? | number | undefined | Entity to skip. |
Returns
readonly OverlapHit[]
The overlapping bodies.
point()
ts
point(
a,
b,
options
): number;Create a point joint. Bodyless entities return 0; b=0 anchors to the world.
Parameters
| Parameter | Type | Description |
|---|---|---|
a | number | First entity, with a physics body. |
b | number | Second entity, or 0 to join to the world. |
options | { anchor: Vec3; } | Joint or motor settings. |
options.anchor | Vec3 | World-space anchor at creation. |
Returns
number
The joint id, or 0 when either entity has no body (b = 0 means the world).
Example
ts
import { defineGame, physics, prefab } from 'gameable';
const Lamp = prefab({ body: { shape: 'sphere', kind: 'dynamic' } });
export default defineGame({
init(ctx) {
const lamp = ctx.spawn(Lamp, { x: 0, y: 3, z: 0 });
physics.point(lamp, 0, { anchor: { x: 0, y: 4, z: 0 } });
},
});raycast()
ts
raycast(
origin,
direction,
maxDistance,
mask?,
ignoreEntity?,
ignoreBody?
): RayHit | null;Closest hit along a ray.
Parameters
| Parameter | Type | Description |
|---|---|---|
origin | Vec3 | World-space ray origin. |
direction | Vec3 | Ray direction; need not be normalised. |
maxDistance | number | Maximum distance in metres. |
mask? | CollisionLayers | Layers to consider; defaults to every layer. |
ignoreEntity? | number | Entity to skip, usually the caster. |
ignoreBody? | number | Additional body to skip, such as a projectile while ignoring its owner entity. |
Returns
RayHit | null
The hit, or null on a miss. The hit object comes from the host and is freshly allocated: this call is not allocation-free.
raycastBatch()
ts
raycastBatch(rays): readonly (RayHit | null | undefined)[];Many rays in one round trip. Result index i matches rays[i].
Parameters
| Parameter | Type | Description |
|---|---|---|
rays | readonly object[] | The rays. Build them once and mutate them in place. |
Returns
readonly (RayHit | null | undefined)[]
One result per ray; undefined or null entries are misses.
removeJoint()
ts
removeJoint(id): void;Remove a joint.
Parameters
| Parameter | Type | Description |
|---|---|---|
id | number | Guest-minted joint handle. |
Returns
void
Nothing.
Example
ts
import { defineGame, physics, prefab } from 'gameable';
const Crate = prefab({ body: { shape: 'box', kind: 'dynamic' } });
export default defineGame({
init(ctx) {
const crate = ctx.spawn(Crate, { x: 0, y: 1, z: 0 });
const weld = physics.fixed(crate, 0);
physics.removeJoint(weld);
},
});setEnabled()
ts
setEnabled(entity, enabled): void;Enable or disable a body in the broad phase.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a body. |
enabled | boolean | Whether the body participates. |
Returns
void
Nothing.
setMotor()
ts
setMotor(id, options): void;Set a motor; rotational targets use degrees or degrees per second.
Values and targets measure how far entity a has moved relative to entity b (or the world). Slider positive is along +axis; hinge positive follows the right-hand rule about +axis. Rotation values and rotational position targets are degrees; angular velocity targets are degrees per second.
Parameters
| Parameter | Type | Description |
|---|---|---|
id | number | Guest-minted joint handle. |
options | { axis?: number; maxForce?: number; mode: MotorMode; target: number; } | Joint or motor settings. |
options.axis? | number | Motor axis index: 0 for hinge/slider, 0..5 for six-dof. |
options.maxForce? | number | Force limit in N or torque limit in N·m; omitted or 0 means 100, too weak to lift anything heavy (a 20 kg lift needs over 196 N). |
options.mode | MotorMode | Off, velocity, or position control. |
options.target | number | Metres or degrees; per second for velocity mode. |
Returns
void
Nothing.
Example
ts
import { defineGame, physics, prefab } from 'gameable';
const Body = prefab({ body: { shape: 'box', kind: 'dynamic' } });
export default defineGame({
init(ctx) {
const door = ctx.spawn(Body, { x: 0.5, y: 1, z: 0 });
const doorJoint = physics.hinge(door, 0, {
anchor: { x: 0, y: 1, z: 0 },
axis: { x: 0, y: 1, z: 0 },
minDeg: -90,
maxDeg: 90,
});
physics.setMotor(doorJoint, { mode: 'position', target: 90 });
const lift = ctx.spawn(Body, { x: 3, y: 1, z: 0 });
const liftJoint = physics.slider(lift, 0, {
anchor: { x: 3, y: 1, z: 0 },
axis: { x: 0, y: 1, z: 0 },
min: 0,
max: 5,
});
physics.setMotor(liftJoint, { mode: 'velocity', target: 1 }); // 1 m/s upward.
},
});setVelocity()
ts
setVelocity(
entity,
x,
y,
z,
ax?,
ay?,
az?
): void;Overwrite a body's velocity.
Angular velocity is left alone unless all three angular components are given.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a body. |
x | number | Linear velocity x. |
y | number | Linear velocity y. |
z | number | Linear velocity z. |
ax? | number | Angular velocity x, radians per second. |
ay? | number | Angular velocity y. |
az? | number | Angular velocity z. |
Returns
void
Nothing.
shapeCast()
ts
shapeCast(
shape,
position,
rotation,
direction,
maxDistance,
mask?,
ignoreEntity?
): RayHit | null;Cast a primitive shape along a direction.
Parameters
| Parameter | Type | Description |
|---|---|---|
shape | QueryShape | Primitive shape and its dimensions in metres. |
position | Vec3 | World-space query centre. |
rotation | Quat | Unit quaternion orientation. |
direction | Vec3 | Sweep direction; need not be normalised. |
maxDistance | number | Maximum travel in metres. |
mask? | CollisionLayers | Layers to consider, or every layer when omitted. |
ignoreEntity? | number | Entity to skip. |
Returns
RayHit | null
The closest hit, or null on a miss; hit.distance is the shape travel in metres.
Example
ts
import { defineGame, physics } from 'gameable';
export default defineGame({
init() {
const position = { x: 0, y: 1, z: 0 };
const rotation = { x: 0, y: 0, z: 0, w: 1 };
const forward = { x: 0, y: 0, z: 1 };
const shape = { kind: 'cylinder', halfExtents: { x: 0.4, y: 0.5, z: 0 } } as const;
const hit = physics.shapeCast(shape, position, rotation, forward, 2);
console.log('travel before contact', hit?.distance);
},
});sixDof()
ts
sixDof(
a,
b,
options
): number;Create a sixDof joint. Bodyless entities return 0; b=0 anchors to the world.
Parameters
| Parameter | Type | Description |
|---|---|---|
a | number | First entity, with a physics body. |
b | number | Second entity, or 0 to join to the world. |
options | { anchor: Vec3; axes: readonly [JointAxis, JointAxis, JointAxis, JointAxis, JointAxis, JointAxis]; } | Joint or motor settings. |
options.anchor | Vec3 | World-space anchor at creation. |
options.axes | readonly [JointAxis, JointAxis, JointAxis, JointAxis, JointAxis, JointAxis] | Six axis settings: tx, ty, tz, rx, ry, rz; rotational limits in degrees. |
Returns
number
The joint id, or 0 when either entity has no body (b = 0 means the world).
Example
ts
import { defineGame, physics, prefab } from 'gameable';
const Hook = prefab({ body: { shape: 'box', kind: 'dynamic' } });
const locked = { mode: 'locked', min: 0, max: 0 } as const;
const free = { mode: 'free', min: 0, max: 0 } as const;
export default defineGame({
init(ctx) {
const hook = ctx.spawn(Hook, { x: 0, y: 3, z: 0 });
physics.sixDof(hook, 0, {
anchor: { x: 0, y: 3, z: 0 },
axes: [locked, locked, locked, free, free, free],
});
},
});slider()
ts
slider(
a,
b,
options
): number;Create a slider joint. Bodyless entities return 0; b=0 anchors to the world.
Values and targets measure how far entity a has moved relative to entity b (or the world). Slider positive is along +axis; hinge positive follows the right-hand rule about +axis. Rotation values and rotational position targets are degrees; angular velocity targets are degrees per second.
Parameters
| Parameter | Type | Description |
|---|---|---|
a | number | First entity, with a physics body. |
b | number | Second entity, or 0 to join to the world. |
options | { anchor: Vec3; axis: Vec3; friction?: number; max?: number; min?: number; spring?: JointSpring; } | Joint or motor settings. |
options.anchor | Vec3 | World-space anchor at creation. |
options.axis | Vec3 | World-space axis; positive motion follows +axis. |
options.friction? | number | Maximum friction force in N. |
options.max? | number | Upper linear limit in metres. |
options.min? | number | Lower linear limit in metres. |
options.spring? | JointSpring | Limit frequency in Hz and damping ratio. |
Returns
number
The joint id, or 0 when either entity has no body (b = 0 means the world).
Example
ts
import { defineGame, physics, prefab } from 'gameable';
const Drawer = prefab({ body: { shape: 'box', kind: 'dynamic' } });
export default defineGame({
init(ctx) {
const drawer = ctx.spawn(Drawer, { x: 0, y: 1, z: 0 });
physics.slider(drawer, 0, {
anchor: { x: 0, y: 1, z: 0 },
axis: { x: 0, y: 0, z: 1 },
min: 0,
max: 0.6,
});
},
});sphereCast()
ts
sphereCast(
position,
radius,
direction,
maxDistance,
mask?,
ignoreEntity?
): RayHit | null;Cast a sphere.
Parameters
| Parameter | Type | Description |
|---|---|---|
position | Vec3 | World-space query centre. |
radius | number | Radius in metres. |
direction | Vec3 | Sweep direction; need not be normalised. |
maxDistance | number | Maximum travel in metres. |
mask? | CollisionLayers | Layers to consider, or every layer when omitted. |
ignoreEntity? | number | Entity to skip. |
Returns
RayHit | null
The closest hit, or null on a miss; hit.distance is the shape travel in metres.
Example
ts
import { defineGame, physics } from 'gameable';
export default defineGame({
init() {
const position = { x: 0, y: 1, z: 0 };
const forward = { x: 0, y: 0, z: 1 };
const hit = physics.sphereCast(position, 0.5, forward, 2);
console.log('will the ball fit through this passage?', hit === null);
},
});teleport()
ts
teleport(
entity,
x,
y,
z,
rotation?
): void;Teleport a body, clearing its velocities.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Entity with a body. |
x | number | Position x. |
y | number | Position y. |
z | number | Position z. |
rotation? | Quat | Optional facing; defaults to identity for existing callers. |
Returns
void
Nothing.
Example
ts
import { physics, Transform } from 'gameable';
const hit = physics.raycast(eye, forward, 100);
if (hit) console.log('hit entity', hit.entity, 'at', hit.distance);PhysicsJoint
ts
const PhysicsJoint: ActorClass<PhysicsJointProps>;Level-placed joint joining named actor roots; empty B anchors to the world.
Example
ts
spawnActor(ctx, PhysicsJoint, { position: { x: 1, y: 2, z: 0 }, props: { actorA: 'door' } });PhysicsVolume
ts
const PhysicsVolume: ActorClass<{
gravityScale: number;
halfExtents: number[];
priority: number;
terminalVelocity: number;
water: boolean;
}>;Highest-priority overlapping volume controls bodyless gravity and falling speed. Equal priorities use spawn order. Water halves requested character horizontal speed. Character gravity/buoyancy cannot be changed by the current guest-host protocol: Jolt owns airborne Y velocity and ignores requested Y until grounded. Gravity scale and terminal velocity therefore apply only to non-body Velocity entities.
Example
ts
spawnActor(ctx, PhysicsVolume, { position: { x: 0, y: 0, z: 0 }, props: { gravityScale: 0.2, priority: 1 } });Pickup
ts
const Pickup: Record<string, never> = {};Tag: something the player can pick up. The actor is exported separately as PickupActor.
PickupActor
ts
const PickupActor: ActorClass<PickupProps>;Player reward volume with optional spinning/bobbing mesh. Customize by spreading its spec and overriding onPickedUp.
The ECS marker is exported separately as Pickup.
Example
ts
spawnActor(ctx, PickupActor, { position: {x: 0,y: 1,z: 0}, props: {give: {score: 10}} });Player
ts
const Player: Record<string, never> = {};Tag: the entity the player controls.
PlayerController
ts
const PlayerController: ActorClass;A seated controller for an existing player body.
Example
ts
const controller = playerControllerOf(0);PlayerStart
ts
const PlayerStart: ActorClass<{
seat: number | null;
tag: string;
}>;Player spawn marker; yaw comes from its root transform. Seat null accepts any seat.
Example
ts
spawnActor(ctx, PlayerStart, { position: { x: 2, y: 0, z: 0 }, yaw: 90, props: { tag: 'red', seat: 0 } });PlayerState
ts
const PlayerState: ActorClass<PlayerStateProps>;A player's match statistics.
Example
ts
spawnActor(ctx, PlayerState, { position, props: { seat: 0 } });playtest
ts
const playtest: object;The playtest facade.
Call death where the game kills the player, win where it is won, goal with where the player is meant to go, checkpoint where they reach one, and hazard for what kills on touch (spikes, enemies). That is what lets the agent learn the game and the reports say where and why players die.
Type Declaration
checkpoint()
ts
checkpoint(position?, note?): void;The player reached a checkpoint. The playtest agent's next life, after a death, a fall or a timeout, starts at the last checkpoint rather than the run's start, facing as the player did.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
position | Vec3 | null | null | Where it is, or null for where the player stands. |
note | string | '' | Which one, or ''. |
Returns
void
damage()
ts
damage(amount, cause?): void;The player took damage.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
amount | number | undefined | How much. |
cause | string | '' | From what, or ''. |
Returns
void
death()
ts
death(cause?, position?): void;The player died.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
cause | string | '' | Why, in a few words: lava, fell, enemy:slime. |
position | Vec3 | null | null | Where, when it is not where the player stands. |
Returns
void
goal()
ts
goal(position, entity?): void;Where the player is meant to go next: the flag, the exit, the next checkpoint. Say it again when it moves on.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
position | Vec3 | null | undefined | Where, or null when there is no goal. |
entity | number | 0 | The goal's entity, when it is one, so its position is followed. |
Returns
void
hazard()
ts
hazard(
entity,
radius?,
position?
): void;Something that hurts or kills on any touch: spikes, lava, an enemy that cannot be stomped. The playtest's route goes around it, or jumps it when there is no way round, and the route pilot jumps one in its way. An enemy the player beats by landing on it is not one: the pilot stomps what is close ahead of its feet. Its body is followed, so a moving one is avoided where it is now; when the entity is gone, so is the hazard. Say it once, when it is spawned.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | The hazard's entity. |
radius | number | 0 | Metres around its middle to keep clear of; 0 for about its size (half a metre). |
position | Vec3 | null | null | Where it is, for an entity with no body; null to follow its body. |
Returns
void
mark()
ts
mark(
kind,
value?,
entity?,
position?,
note?
): void;A mark of the game's own kind.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
kind | string | undefined | A short word: jump-pad, secret. |
value | number | 0 | An amount, or 0. |
entity | number | 0 | The entity it concerns, or 0. |
position | Vec3 | null | null | Where, or null. |
note | string | '' | A few words, or ''. |
Returns
void
player()
ts
player(entity): void;The entity the player controls. A game whose declarative player block spawns it has this said for it; call it when the game spawns its own, or swaps the player to another.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | The player's entity. |
Returns
void
restart()
ts
restart(): void;The run starts over: the level reloaded, the round reset.
Returns
void
reward()
ts
reward(amount, note?): void;Something good happened: a coin, a kill, progress. The agent learns to seek it.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
amount | number | undefined | How good; 1 is a typical pickup. |
note | string | '' | What, or ''. |
Returns
void
win()
ts
win(note?): void;The game is won: the level is done, the race finished, the boss beaten.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
note | string | '' | What was won, or ''. |
Returns
void
Example
ts
import { defineGame, playtest } from 'gameable';
export default defineGame({
init() {
playtest.goal({ x: 0, y: 12, z: -40 });
},
systems: [
(ctx) => {
if (ctx.frame === 600) playtest.death('lava');
},
],
});PointLight
ts
const PointLight: ActorClass<{
color: number[];
intensity: number;
radius: number;
}>;Placeable light placeholder until the host accepts guest light commands. Emits one warning per instance at beginPlay and preserves authored props.
Example
ts
spawnActor(ctx, PointLight, { position: { x: 0, y: 2, z: 0 } });PostProcessVolume
ts
const PostProcessVolume: ActorClass<object & object>;Local post overrides inside a rotated box, or everywhere when unbound. Declare features: { vfx: true }. Null settings do not override earlier settings. V1 supports blendRadius=0 only. Do not also call ctx.vfx.post when using volumes. Room authorities skip composition because they have no single local view.
Example
ts
spawnActor(ctx, PostProcessVolume, { position: { x: 0, y: 0, z: 0 }, props: { bloom: 0.5 } });PressurePlate
ts
const PressurePlate: ActorClass<PressurePlateProps>;A floor plate supplying a signal while enough occupants stand in its top footprint.
Example
ts
spawnActor(ctx, PressurePlate, { position: { x: 0, y: 0, z: 0 }, name: 'plate1' });Projectile
ts
const Projectile: ActorClass<ProjectileProps & object>;Swept projectile with owner-attributed damage and a finite bounce budget.
Example
ts
spawnActor(ctx, Projectile, {position: muzzle, owner: shooter, props: {damage: 25}});Renderable
ts
const Renderable: RenderableStore;Renderable asset attached to an entity.
RigidBody
ts
const RigidBody: RigidBodyStore;Physics body attached to an entity.
score
ts
const score: object;Per-player score counter; owner is a seat index, never an entity id.
Type Declaration
add()
ts
add(seat, amount): void;Parameters
| Parameter | Type |
|---|---|
seat | number |
amount | number |
Returns
void
get()
ts
get(seat): number;Parameters
| Parameter | Type |
|---|---|
seat | number |
Returns
number
Example
ts
console.log(score.get(0));SHAPE_KINDS
ts
const SHAPE_KINDS: readonly ["box", "sphere", "capsule", "cylinder", "plane", "convex-hull", "mesh", "height-field"];Collision shapes, in the index order RigidBody.shape stores.
SlidingDoor
ts
const SlidingDoor: ActorClass<SlidingDoorProps>;One or two painted panels sliding in the closed door's local frame.
Example
ts
spawnActor(ctx, SlidingDoor, { position: { x: 0, y: 1.05, z: 0 }, props: { panels: 2 } });SNAPSHOT_VERSION
ts
const SNAPSHOT_VERSION: 3 = 3;Bumped whenever the byte layout changes. Mismatches refuse to restore.
SoftPlatform
ts
const SoftPlatform: ActorClass<{
asset: string;
scale: [number, number, number];
tint: [number, number, number];
}>;One-way surface for characterMovement capsules. Pass upward through the underside; downward movement lands on its top. Axis-aligned placement and scale only. Other body/controller types pass through it in either direction. Optional mesh scale affects only the look; the one-way surface keeps its authored dimensions.
Example
ts
spawnActor(ctx, SoftPlatform, { position: { x: 3, y: 2, z: 0 }, props: { asset: 'platform' } });Spawner
ts
const Spawner: ActorClass<SpawnerProps>;Spawn registered actor classes in gameplay waves; destruction counts as a kill on the next fixed step.
Example
ts
spawnActor(ctx, Spawner, {position: {x: 0,y: 0,z: 0},props: {actorClass: 'Enemy'}});Spectator
ts
const Spectator: ActorClass<{
maxSpeed: number;
}>;A flying spectator without collision or health to damage.
Example
ts
const pawn = spawnActor(ctx, Spectator, { position: { x: 0, y: 2, z: 0 } });SpotLight
ts
const SpotLight: ActorClass<{
angle: number;
cameraAttached: boolean;
color: number[];
enabled: boolean;
intensity: number;
penumbra: number;
radius: number;
}>;Rendered spotlight. Local forward is -Z; cameraAttached follows the active view. Toggle enabled or change props; settings are sent only when changed.
Example
ts
spawnActor(ctx, SpotLight, { position: { x: 0, y: 0, z: 0 }, props: { cameraAttached: true } });TAG_ORDINAL
ts
const TAG_ORDINAL: Record<CommandTag, number>;Every command tag mapped to its pool index.
Written out rather than derived so the compiler checks it: Record over the CommandTag union rejects both a missing tag and one that is not in the WIT variant. packages/wasm-host/src/apply.test.ts pins the same list from the host side.
Example
ts
import { TAG_ORDINAL } from 'gameable';
console.log(TAG_ORDINAL['set-time-scale']); // 24TargetPoint
ts
const TargetPoint: ActorClass<{
tag: string;
}>;Named destination with no collision or behaviour.
Example
ts
spawnActor(ctx, TargetPoint, { name: 'goal', position: { x: 0, y: 0, z: 4 }, props: { tag: 'route' } });things
ts
const things: object;The things facade: the made world the host loaded, as game code sees it.
The list arrives once (world-event, kind loaded) and is kept up to date as loose things move (moved); the questions answer from it with no call to the host. push, move and reset are commands the host applies to a loose thing's body. A knock arrives in ctx.events as a world-event of kind hit, with the thing's index, where, and how hard (0 to 1).
Type Declaration
all
Get Signature
ts
get all(): readonly WorldThing[];Every thing, loose or fixed; empty before a world has loaded.
Returns
readonly WorldThing[]
world
Get Signature
ts
get world(): WorldList | null;The world the things are in (its name, the start, the walk limit), or null before one has loaded.
Returns
WorldList | null
breakApart()
ts
breakApart(
thing,
x?,
y?,
z?
): void;Break a thing in pieces (thing.pieces): each piece becomes a body of its own where it stood, moving as the thing moved, and a piece the package marks fixed stays put. Given one piece (thing.pieceOf), that piece alone comes off. The broken event follows, and reset makes the thing whole again.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
thing | number | WorldThing | undefined | The thing, a piece of one, or the index of either. |
x | number | 0 | Metres a second added to each piece that comes off, x. |
y | number | 0 | The same, y. |
z | number | 0 | The same, z. |
Returns
void
Nothing; a thing that is not in pieces is left as it is.
drive()
ts
drive(
thing,
throttle,
right,
brake?
): void;Drive a thing that can be driven (thing.drives): the rider's wish, held until the next call. Send zeros to let go.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
thing | number | WorldThing | undefined | The thing, or its index. |
throttle | number | undefined | From -1 (back) to 1 (forward). |
right | number | undefined | Steering, from -1 (left) to 1 (right). |
brake | number | 0 | The brakes, from 0 to 1. |
Returns
void
Nothing.
find()
ts
find(words): WorldThing | null;The thing some words name ("the trunk"), or null.
Parameters
| Parameter | Type | Description |
|---|---|---|
words | string | What was said. |
Returns
WorldThing | null
The best match, or null.
findAll()
ts
findAll(words, out?): WorldThing[];Every thing that answers some words, the best first.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
words | string | undefined | What was said. |
out | WorldThing[] | [] | The array to fill. |
Returns
out.
getOff()
ts
getOff(thing): void;Whoever sits on a thing gets off: the character is back on its entity. Move the entity to where it should stand first (physics.teleport), beside the thing.
Parameters
| Parameter | Type | Description |
|---|---|---|
thing | number | WorldThing | The thing, or its index. |
Returns
void
Nothing.
getOn()
ts
getOn(thing, entity): void;Sit a character on a thing that has rider spots (thing.rider): its hips go on the seat, its hands are held to the grips as they turn, its feet to the rests, and it leans and moves with the thing. The host does it every frame from the character's own skeleton; the entity itself stays where it was (take its body out of the simulation with physics.setEnabled(entity, false) so the thing does not run into it).
Parameters
| Parameter | Type | Description |
|---|---|---|
thing | number | WorldThing | The thing, or its index. |
entity | number | The character's entity. |
Returns
void
Nothing; a thing with no rider spots is ignored.
joint()
ts
joint(
thing,
joint,
value
): void;Set one joint of a thing with moving parts: a lid opened, handlebars turned. The value is held to the joint's limits by the host.
Parameters
| Parameter | Type | Description |
|---|---|---|
thing | WorldThing | The thing. |
joint | string | number | The joint's name ('steering') or its place in thing.joints. |
value | number | Degrees for a hinge, metres for a slide. |
Returns
void
Nothing; a name the thing does not have is ignored.
limit()
ts
limit(
x,
z,
velocity
): void;Keep a walker inside the world's walk limit: changes velocity in place.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | number | Where the walker is, x. |
z | number | Where the walker is, z. |
velocity | Vec3 | The velocity asked for. |
Returns
void
Nothing.
move()
ts
move(
thing,
x,
y,
z
): void;Put a loose thing somewhere: the middle of its base at this point, at rest.
Parameters
| Parameter | Type | Description |
|---|---|---|
thing | number | WorldThing | The thing, or its index. |
x | number | Where, x. |
y | number | Where, y. |
z | number | Where, z. |
Returns
void
Nothing.
near()
ts
near(at, radius): readonly WorldThing[];What is near a point, the nearest first. The array is reused by the next call.
Parameters
| Parameter | Type | Description |
|---|---|---|
at | Vec3 | The point. |
radius | number | Metres. |
Returns
readonly WorldThing[]
The things within radius.
push()
ts
push(
thing,
x,
y,
z
): void;Shove a loose thing: an impulse at its middle, in newton-seconds.
Parameters
| Parameter | Type | Description |
|---|---|---|
thing | number | WorldThing | The thing, or its index. |
x | number | Impulse x. |
y | number | Impulse y. |
z | number | Impulse z. |
Returns
void
Nothing.
reset()
ts
reset(thing?): void;Put a loose thing back where the package had it; with no thing, all of them.
Parameters
| Parameter | Type | Description |
|---|---|---|
thing? | number | WorldThing | The thing, its index, or nothing for every loose thing. |
Returns
void
Nothing.
spot()
ts
spot(thing, name): WorldSpotNow | null;Where one of a thing's rider spots is now, in the world (seat, gripLeft, gripRight, footLeft, footRight): a grip turns with the handlebars. The record is reused by the next call.
Parameters
| Parameter | Type | Description |
|---|---|---|
thing | WorldThing | The thing. |
name | string | The spot's name. |
Returns
WorldSpotNow | null
The spot's place, the way it faces and its up; null when the thing has no such spot.
standFor()
ts
standFor(thing, from?): WorldStand;Where to stand to use a thing. The record is reused by the next call.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
thing | WorldThing | undefined | The thing. |
from | Vec3 | null | null | Where the asker is, to stand on the nearest side; omit for the package's own spot. |
Returns
The spot and the facing.
Example
ts
import { defineGame, things } from 'gameable';
export default defineGame({
update(ctx) {
for (const event of ctx.events) {
if (event.tag !== 'world-event') continue;
if (event.val.kind === 'loaded') {
const trunk = things.find('the trunk');
if (trunk) console.log('stand at', things.standFor(trunk));
} else if (event.val.kind === 'hit') {
console.log(things.all[event.val.thing]?.label, 'was knocked', event.val.strength);
}
}
},
});Transform
ts
const Transform: TransformStore;World transform of an entity. Position, rotation (xyzw), scale.
TRANSFORM_ALL
ts
const TRANSFORM_ALL: number;POSITION | ROTATION | SCALE, what a freshly spawned entity needs.
TRANSFORM_FLAGS
ts
const TRANSFORM_FLAGS: Readonly<{
DESTROYED: 32;
POSITION: 1;
ROTATION: 2;
SCALE: 4;
TELEPORT: 16;
VISIBLE: 8;
}>;Meaning of lane 1 of a transform row, matching WIT transform-flags.
TRANSFORM_STRIDE
ts
const TRANSFORM_STRIDE: 12 = 12;Floats per row of frame-output.transforms.
TrapDoor
ts
const TrapDoor: ActorClass<TrapDoorProps>;A flat wood hatch hinged at local -Z that swings down about local X. onPassed is never fired: doorway plane crossings are not meaningful for a hatch.
Example
ts
spawnActor(ctx, TrapDoor, { position: { x: 0, y: 0, z: 0 }, props: { opensWhen: ['switch'] } });TriggerBox
ts
const TriggerBox: ActorClass<object>;Overlap marker. Sizes are read from props at spawn; overlaps use entity root points.
Example
ts
spawnActor(ctx, TriggerBox, { name: 'gate', position: { x: 0, y: 0, z: 0 } });TriggerCapsule
ts
const TriggerCapsule: ActorClass<object>;Overlap marker. Sizes are read from props at spawn; overlaps use entity root points.
Example
ts
spawnActor(ctx, TriggerCapsule, { name: 'gate', position: { x: 0, y: 0, z: 0 } });TriggerSphere
ts
const TriggerSphere: ActorClass<object>;Overlap marker. Sizes are read from props at spawn; overlaps use entity root points.
Example
ts
spawnActor(ctx, TriggerSphere, { name: 'gate', position: { x: 0, y: 0, z: 0 } });ui
ts
const ui: object;Retained UI and player interactions for the active guest.
Type Declaration
events
Get Signature
ts
get events(): readonly UiEvent[];This tick's UI events in arrival order; the array is reused each tick.
Returns
readonly UiEvent[]
The pooled event array.
clear()
ts
clear(): void;Clear the UI once; subsequent clears emit nothing.
Returns
void
clicked()
ts
clicked(id): boolean;Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Button or clickable card id. |
Returns
boolean
Whether it was clicked this tick.
dropped()
ts
dropped(id): UiEvent | null;Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Draggable node id. |
Returns
UiEvent | null
Its drop event this tick, including the target, or null.
invalidate()
ts
invalidate(): void;Forget the previous model so the next set emits again.
Returns
void
set()
ts
set(nodes, options?): boolean;Emit a model only when its value changes, comparing up to 24 levels.
Parameters
| Parameter | Type | Description |
|---|---|---|
nodes | UiNode | readonly UiNode[] | One node or the ordered top-level nodes. |
options? | { theme?: UiTheme; } | Optional theme overrides. |
options.theme? | UiTheme | Theme token overrides. |
Returns
boolean
True when JSON will cross this frame.
submitted()
ts
submitted(id): boolean;Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Input id. |
Returns
boolean
Whether Enter submitted it this tick.
value()
ts
value(id): string | null;Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Input id. |
Returns
string | null
Latest changed or submitted text across ticks, or null if unedited.
Example
ts
import { defineGame, ui } from 'gameable';
defineGame({ systems: [() => {
ui.set({ type: 'button', id: 'play', text: 'Play' });
if (ui.clicked('play')) ui.clear();
}] });VehicleGripVolume
ts
const VehicleGripVolume: ActorClass<VehicleGripVolumeProps>;Timed oil sphere. Overlapping registered vehicle chassis refresh one source until recovery seconds after last contact; multiple areas combine by minimum grip. Duration zero expires immediately. Recovery zero lasts through the current step. Scale uses the largest world scale axis. Visuals can be supplied by a separate actor.
Example
ts
spawnActor(ctx, VehicleGripVolume, { position: hit.point, props: { radius: 3, duration: 8, gripScale: 0.15, recovery: 1 } });Velocity
ts
const Velocity: VelocityStore;Guest-integrated velocity, for entities the host physics does not own.
vfx
ts
const vfx: object;Emit particles and change the page's look. Declare features: { vfx: true }. Options and vectors are copied; reuse them in frame callbacks.
Type Declaration
burst()
ts
burst(
preset,
at,
options?
): void;Play a one-shot preset at a world position.
Parameters
| Parameter | Type | Description |
|---|---|---|
preset | VfxPreset | Built-in preset name. |
at | Vec3 | World position. |
options? | BurstOptions | Optional overrides. |
Returns
void
Nothing.
Example
ts
import { vfx } from 'gameable';
vfx.burst('dust', { x: 0, y: 0, z: 0 });move()
ts
move(id, at): void;Move an emitter (or change its entity offset).
Parameters
| Parameter | Type | Description |
|---|---|---|
id | number | Handle from start; 0 is ignored. |
at | Vec3 | Position or offset. |
Returns
void
Nothing.
Example
ts
import { vfx } from 'gameable';
const id = vfx.start('fire', {});
vfx.move(id, { x: 1, y: 0, z: 0 });post()
ts
post(settings): void;Apply partial post settings.
Parameters
| Parameter | Type | Description |
|---|---|---|
settings | PostSettings | Fields to change; reset first restores neutral values. |
Returns
void
Nothing.
Example
ts
import { vfx } from 'gameable';
vfx.post({ reset: true, exposure: 1.2 });start()
ts
start(preset, options): number;Start an emitter that runs until stopped.
Parameters
| Parameter | Type | Description |
|---|---|---|
preset | VfxPreset | Built-in preset name. |
options | StartOptions | Position or entity attachment and overrides. |
Returns
number
A guest-minted effect handle.
Example
ts
import { vfx } from 'gameable';
const id = vfx.start('smoke', { at: { x: 0, y: 0, z: 0 } });
vfx.stop(id);stop()
ts
stop(id): void;Stop an emitter.
Parameters
| Parameter | Type | Description |
|---|---|---|
id | number | Handle from start; 0 is ignored. |
Returns
void
Nothing.
Example
ts
import { vfx } from 'gameable';
const id = vfx.start('trail', {});
vfx.stop(id);Example
ts
import { defineGame, vfx } from 'gameable';
export default defineGame({
features: { vfx: true },
init() {
vfx.burst('hit-sparks', { x: 0, y: 1, z: 0 });
vfx.post({ bloom: 0.5 });
},
});WheeledVehicle
ts
const WheeledVehicle: ActorClass<WheeledVehicleProps>;Possessable four-wheel arcade car. Authority simulation; no client prediction yet.
Example
ts
const car = spawnActor(ctx, WheeledVehicle, { position: { x: 0, y: 1, z: 0 }, props: { handling: 'grippy', maxSpeed: 30 } });WorldText
ts
const WorldText: ActorClass<WorldTextProps>;Placeable world text, included when the game composes actorWidgets() into its UI. In rooms the game's UI system chooses which side displays these guest data.
Example
ts
spawnActor(ctx, WorldText, { position: { x: 0, y: 2, z: 0 }, props: { text: 'Welcome' } });Functions
abilities()
ts
function abilities(opts): ActorComponent;Create fixed-capacity RPG stats on one actor. Register definitions at module scope or in init. All mutations are authority-only. Events borrow pooled payloads; copy before retaining. Attribute changes settle once per component step. Periodic modifiers pulse at each period including an exact expiry boundary, rather than modifying current values. Infinite lifetimes are represented by the definition, never non-JSON numbers.
Parameters
| Parameter | Type | Description |
|---|---|---|
opts | AbilitiesOptions | Attributes, storage ceilings (default 64 each) and event callbacks. |
Returns
The component declaration.
Example
ts
const stats = abilities({ attributes: { health: { base: 100, min: 0, max: 100 } } });abilityCooldownRemaining()
ts
function abilityCooldownRemaining(actor, id): number;Read simulated seconds until the ability cooldown completes; ungranted returns zero.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor handle. |
id | string | Registered effect or ability id. |
Returns
number
Remaining simulated seconds, or zero if ungranted.
Example
ts
const seconds = abilityCooldownRemaining(hero, 'jump');activateAbility()
ts
function activateAbility(actor, id): boolean;Spend base cost and activate; failure emits a reason, clients cannot mutate.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor handle. |
id | string | Registered effect or ability id. |
Returns
boolean
Whether activation succeeded.
Example
ts
const jumped = activateAbility(hero, 'jump');activateCamera()
ts
function activateCamera(ctx, actor): void;Select an actor as the view target, also writing the current frame immediately. The last activation wins. A dead actor has no effect.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Running guest context. |
actor | ActorHandle<{ activateOnStart: boolean; fov: number; }> | Camera actor handle. |
Returns
void
Example
ts
activateCamera(ctx, view);activateEffect()
ts
function activateEffect(
ctx,
actor,
component?
): void;Activate once; omitting the name selects the first ParticleEffect component.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current context. |
actor | ActorHandle | Owning actor. |
component? | string | Component name. |
Returns
void
Example
ts
activateEffect(ctx, torch, 'flame');activeRuntime()
ts
function activeRuntime(): RuntimeState;The runtime the SDK facades are currently bound to.
Returns
RuntimeState
The active runtime.
Throws
When called outside init, a system, update or shutdown.
actorCatalog()
ts
function actorCatalog(): ActorCatalog;Describe every registered actor without hooks, handles or mutable references.
Returns
Detached JSON-safe catalog in registry order.
Example
ts
const json = JSON.stringify(actorCatalog());actorClass()
ts
function actorClass(name): ActorClass<object> | null;Look up a class by its unique name, or return null.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Unique class name or instance lookup name. |
Returns
ActorClass<object> | null
The matching class, or null.
Example
ts
const cls = actorClass('Crate');actorContains()
ts
function actorContains(actor, entity): boolean;Test an entity point against an actor's overlap shapes, including rotation and scale.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Volume actor. |
entity | number | Entity to test. |
Returns
boolean
True when any overlap shape contains the point.
Example
ts
const inside = actorContains(volume, ctx.player);actorWidgets()
ts
function actorWidgets(): readonly UiNode[];Borrow actor widgets in spawn/component order, with one reused array per guest. Unchanged reads allocate nothing; additions, edits and removals reconcile on the next read. The game owns ui.set; in rooms its UI system decides which side displays these guest data.
Returns
readonly UiNode[]
Borrowed visible nodes; do not mutate the array or nodes.
Example
ts
ctx.ui.set([...myScreens, ...actorWidgets()]);addItem()
ts
function addItem(
actor,
item,
amount?
): number;Add to existing stacks then empty slots; return overflow (all on clients or dead actors).
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
actor | ActorHandle | undefined | Owning actor. |
item | string | undefined | Catalog id. |
amount | number | 1 | Nonnegative safe integer; defaults to one. |
Returns
number
Uninserted amount.
Example
ts
const overflow = addItem(actor, 'coin', 5);addMovementInput()
ts
function addMovementInput(
entity,
worldDirection,
scale?
): void;Accumulate world-space input; the component consumes and clamps it once per tick.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Actor root entity. |
worldDirection | Vec3 | undefined | World direction. |
scale | number | 1 | Analog strength. |
Returns
void
Example
ts
addMovementInput(player, { x: 1, y: 0, z: 0 });addScore()
ts
function addScore(
ctx,
seat,
points
): void;Change a logged-in player's score.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
seat | | string | number | ActorHandle<PlayerStateProps> |
points | number |
Returns
void
Example
ts
addScore(ctx, 0, 10);addTag()
ts
function addTag(actor, tag): boolean;Add an idempotent manual tag; returns false at capacity or on clients.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor handle. |
tag | string | Exact manual tag or hierarchical query. |
Returns
boolean
Whether the tag was added or already present.
Example
ts
addTag(hero, 'state.ready');applyDamage()
ts
function applyDamage(
ctx,
target,
amount,
info?
): void;Notify a class of damage, then reduce Health through the gameplay damage part. Zero health leaves the actor alive until its class decides to destroy it.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
ctx | GameContext | undefined | Current game context. |
target | number | ActorHandle<object> | undefined | Actor receiving damage. |
amount | number | undefined | Positive damage amount. |
info | DamageInfo | EMPTY_DAMAGE_INFO | Damage attribution. |
Returns
void
Example
ts
applyDamage(ctx, target, 10, { instigator: attacker, type: 'fire' });applyEffect()
ts
function applyEffect(
actor,
id,
source?
): boolean;Apply an effect; false means gating, duplicate or capacity rejection. Source is saved as its root entity.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor handle. |
id | string | Registered effect or ability id. |
source? | ActorHandle<object> | Optional actor responsible for application. |
Returns
boolean
Whether the effect was applied or refreshed.
Example
ts
applyEffect(hero, 'heal', healer);applyLevelEdits()
ts
function applyLevelEdits(
level,
edits,
options?
): LevelFile;Apply edits to a level document and return the new document. The input is never changed.
Parameters
| Parameter | Type | Description |
|---|---|---|
level | LevelFile | The document as it is. |
edits | readonly LevelEdit[] | What to change, in order. |
options | ApplyLevelEditsOptions | Whether to validate the result. |
Returns
The edited document.
Throws
When an edit names an actor that is not there, a taken name, an unknown class, or an attachment that would dangle.
Example
ts
const next = applyLevelEdits(level, [{ op: 'set', name: 'exit', position: [3, 1.2, -10.5] }]);applyTransfer()
ts
function applyTransfer(
docA,
docB,
give,
take
):
| {
a: TransferDoc;
b: TransferDoc;
}
| null;Trade between two player documents: a gives b everything in give, and takes from b everything in take. A number field moves that amount (the giver must have at least that much); a list field moves those items (the giver must hold each one; an object item matches by value, whatever its key order). A missing document counts as {}.
Parameters
| Parameter | Type | Description |
|---|---|---|
docA | unknown | Player a's document, or null. |
docB | unknown | Player b's document, or null. |
give | unknown | What a gives b, such as { coins: 5 }. |
take | unknown | What a takes from b, such as { owned: ['gem'] }. |
Returns
| { a: TransferDoc; b: TransferDoc; } | null
Both new documents (the inputs are untouched), or null when the trade is impossible.
Example
ts
import { applyTransfer } from 'gameable';
applyTransfer({ coins: 10 }, { owned: ['gem'] }, { coins: 4 }, { owned: ['gem'] });
// { a: { coins: 6, owned: ['gem'] }, b: { owned: [], coins: 4 } }applyVehicleImpulse()
ts
function applyVehicleImpulse(
ctx,
pawn,
impulse,
point
): void;Apply a world-space impulse at a world-space chassis point, imparting linear motion and spin. Authority/solo only; dead actors and non-vehicles are ignored. No damage is applied.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Frame context. |
pawn | ActorHandle | Vehicle pawn. |
impulse | Vec3 | Newton-seconds along world axes. |
point | Vec3 | World application point; offset it from the centre to impart spin. |
Returns
void
Example
ts
applyVehicleImpulse(ctx, car, { x: 2000, y: 0, z: -4000 }, hit.point);arriveAtLevelStart()
ts
function arriveAtLevelStart(
ctx,
entity,
start,
index?
): void;Teleport to an arrival marker, clear motion and reset the player's view. Uses the same transform, physics and camera operations as respawnPlayer.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
ctx | GameContext | undefined | Current context. |
entity | number | undefined | Player entity. |
start | ActorHandle | undefined | Loaded PlayerStart or TargetPoint. |
index | number | 0 | Party arrival index; offsets 0, +1, -1, +2 metres along local X. |
Returns
void
Example
ts
arriveAtLevelStart(ctx, ctx.player, start);assetId()
ts
function assetId(name): number;Resolve a manifest string id to an asset handle, caching the result.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | The manifest string id, for example 'arena'. |
Returns
number
The handle, or 0 when the manifest has no such entry.
Example
ts
import { assetId } from 'gameable';
const arena = assetId('arena');assetUrl()
ts
function assetUrl(id): string;Resolve an id or alias using the most recently created live asset registry.
Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Manifest asset id. |
Returns
string
Its game-root-aware URL; throws when the registry or id is missing.
Example
ts
import { assetUrl } from 'gameable';
const response = await fetch(assetUrl('arena'));
console.log(response.ok);attach()
ts
function attach(
ctx,
child,
parent,
opts?
): void;Attach a child actor to a parent's root using local TRS; cycles throw.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current game context. |
child | ActorHandle | Child actor to move. |
parent | ActorHandle | Parent actor or component entity. |
opts | AttachmentOptions | Local transform or spawn options. |
Returns
void
Example
ts
attach(ctx, child, parent, { offset: [0, 2, 0] });attachedActor()
ts
function attachedActor(className, opts?): ActorComponent;Spawn an owned actor attached to this component, with JSON-safe instance props.
Parameters
| Parameter | Type |
|---|---|
className | string |
opts | ComponentOptions & object |
Returns
Example
ts
const passenger = attachedActor('Passenger', { offset: [0, 1, 0] });attachedActorOf()
ts
function attachedActorOf(actor, component): ActorHandle<object> | null;Find a living child, including after snapshot restoration.
Parameters
| Parameter | Type |
|---|---|
actor | ActorHandle |
component | string |
Returns
ActorHandle<object> | null
Example
ts
const passenger = attachedActorOf(vehicle, 'passenger');audioComponent()
ts
function audioComponent(asset, opts?): ActorComponent;Attach playback to this component's entity. Autoplay defaults to false and runs on the first step.
Parameters
| Parameter | Type | Description |
|---|---|---|
asset | string | Manifest audio id. |
opts | AudioComponentOptions | Playback and attachment settings. |
Returns
An entity-attached audio component.
Example
ts
const sound = audioComponent('wind', { autoPlay: true, looping: true });autoActorName()
ts
function autoActorName(level, index): string;The name of one entry: the written one, or the automatic one.
Parameters
| Parameter | Type | Description |
|---|---|---|
level | LevelFile | The level document. |
index | number | The entry's index in actors. |
Returns
string
Its name.
Throws
When there is no such entry.
Example
ts
const name = autoActorName(level, 0);bindVehicleInput()
ts
function bindVehicleInput(controller, bindings?): void;Bind a seated PlayerController; collection precedes all pawn component steps.
Parameters
| Parameter | Type | Description |
|---|---|---|
controller | ActorHandle | Controller actor. |
bindings | VehicleBindings | Optional key overrides. |
Returns
void
Example
ts
bindVehicleInput(controller, { brake: 'Control' });box()
ts
function box(halfExtents, opts?): ActorComponent;A box specified by half extents.
Parameters
| Parameter | Type | Description |
|---|---|---|
halfExtents | readonly [number, number, number] | Half size along each axis, in metres. |
opts | ShapeOptions | Local transform or spawn options. |
Returns
The component declaration.
Example
ts
import { box } from 'gameable';
const root = box([1, 1, 1], { collision: 'block' });breakConstraint()
ts
function breakConstraint(
ctx,
actor,
component?
): void;Remove a joint immediately and prevent recreation, including before its first step.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Game context. |
actor | ActorHandle | Owning actor. |
component? | string | Component name; defaults to the first constraint. |
Returns
void
Example
ts
breakConstraint(ctx, door);cameraArm()
ts
function cameraArm(length, opts?): ActorComponent;Hold children behind an origin, with collision retraction and exponential lag.
Parameters
| Parameter | Type | Description |
|---|---|---|
length | number | Arm length in metres. |
opts | ArmOptions | Local transform and arm settings. |
Returns
A spring arm scene component.
Example
ts
const arm = cameraArm(4, { usePawnControlRotation: true });cameraComponent()
ts
function cameraComponent(opts?): ActorComponent;Declare a point of view on an actor, with vertical field of view in degrees.
Parameters
| Parameter | Type | Description |
|---|---|---|
opts | ComponentOptions & object | Local transform and field of view (70 degrees by default). |
Returns
A camera scene component.
Example
ts
const eye = cameraComponent({ attach: 'arm', fov: 70 });canActivate()
ts
function canActivate(actor, id): boolean;Query cost, cooldown, lifetime and tag gates without mutating state.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor handle. |
id | string | Registered effect or ability id. |
Returns
boolean
Whether activation would succeed.
Example
ts
if (canActivate(hero, 'jump')) activateAbility(hero, 'jump');canSee()
ts
function canSee(
ctx,
actor,
pawn,
component?
): boolean;Test sight immediately without advancing timers or firing callbacks.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current context. |
actor | ActorHandle | Sensing actor. |
pawn | number | Target pawn entity. |
component? | string | Named sensor, or the first sensing component. |
Returns
boolean
Example
ts
if (canSee(ctx, guard, ctx.player)) guard.state.alert = true;capsule()
ts
function capsule(dims, opts?): ActorComponent;A vertical capsule specified by radius and half height of its straight section.
Parameters
| Parameter | Type | Description |
|---|---|---|
dims | readonly [number, number] | Shape dimensions in metres. |
opts | ShapeOptions | Local transform or spawn options. |
Returns
The component declaration.
Example
ts
import { capsule } from 'gameable';
const root = capsule([0.5, 1]);characterBody()
ts
function characterBody(opts?): ActorComponent;A character controller with the SDK's default capsule dimensions.
Parameters
| Parameter | Type | Description |
|---|---|---|
opts | ShapeOptions | Local transform or spawn options. |
Returns
The component declaration.
Example
ts
import { characterBody } from 'gameable';
const root = characterBody();characterMovement()
ts
function characterMovement(options?): ActorComponent;Kinematic capsule root driven by the guest movement solver, including pawn blocking. Use as the actor's root; submit input before the next actor step.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | CharacterMovementOptions | Metre-based solver settings, collision profile and facing. |
Returns
Root component declaration.
Example
ts
const Hero = defineActor('Hero', { components: { root: characterMovement({ maxWalkSpeed: 4 }) } });chaseVehicle()
ts
function chaseVehicle(
ctx,
ai,
target,
opts?
): void;Pursue a vehicle with bounded velocity prediction and physical contact rams.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Frame context. |
ai | ActorHandle | AI controller. |
target | ActorHandle | Vehicle actor. |
opts | ChaseOptions | Prediction horizon and ram policy. |
Returns
void
Example
ts
chaseVehicle(ctx, police, suspect, { leadTime: 0.6, ramDistance: 5, ramCooldown: 4 });choosePlayerStart()
ts
function choosePlayerStart(
ctx,
seat,
tag?,
ignore?
):
| ActorHandle<{
seat: number | null;
tag: string;
}>
| null;Choose a start: matching tag when available, free starts before occupied ones, explicit seat before seat modulo candidate count. Ties use actor spawn order.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
ctx | GameContext | undefined | Current context. |
seat | number | undefined | Player seat. |
tag | string | '' | Preferred tag; falls back to all starts if none match. |
ignore | number | 0 | Entity being respawned, ignored for occupancy. |
Returns
| ActorHandle<{ seat: number | null; tag: string; }> | null
Chosen marker, or null when no starts exist (origin fallback).
Example
ts
const start = choosePlayerStart(ctx, 0, 'red');circuitStandings()
ts
function circuitStandings(model, id): CircuitStandings | undefined;Read a circuit from a client's parsed HUD model (for example adapter.hudModel). The HUD transport retains full state for late joiners; undefined means no publication yet.
Parameters
| Parameter | Type | Description |
|---|---|---|
model | unknown | Parsed HUD model. |
id | string | Circuit id. |
Returns
CircuitStandings | undefined
Borrowed published standings, or undefined before receipt.
Example
ts
const state = circuitStandings(adapter.hudModel, 'track'); console.log(state?.rows);clearVehicleGrip()
ts
function clearVehicleGrip(
ctx,
pawn,
sourceId?
): void;Remove one grip source, or all sources when sourceId is omitted. Authority/solo only.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Frame context. |
pawn | ActorHandle | Vehicle pawn. |
sourceId? | string | number | Source to clear; omit to clear all. |
Returns
void
Example
ts
clearVehicleGrip(ctx, car, 'rocket');closeDoor()
ts
function closeDoor(ctx, door): void;Request closing unless stayOpen has latched.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current guest context. |
door | ActorHandle<DoorCoreProps> | Kit door instance. |
Returns
void
Example
ts
closeDoor(ctx, door);collisionProfile()
ts
function collisionProfile(name): Readonly<CollisionSetup>;Return an independent, deeply frozen profile. Unknown names list valid choices.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Profile name from the default ini. |
Returns
Readonly<CollisionSetup>
A frozen collision setup and response container.
Example
ts
const pawn = collisionProfile('Pawn');combineMove()
ts
function combineMove(state, out): Axis2;Combine WASD/arrow keys, the left touch stick and the first connected physical gamepad. Sticks use a radial 0.15 deadzone, rescaled to full range; forward is positive y. The sum is clamped to the unit circle. Allocates nothing.
Parameters
| Parameter | Type | Description |
|---|---|---|
state | object & | { keys: KeyState; } | { down: ArrayLike<number>; } | Host input, with either snapshot or guest key storage. |
out | Axis2 | Reusable destination for the combined axes. |
Returns
The destination. Never retain a caller's pooled result.
Example
ts
import { combineMove } from 'gameable';
const move = { x: 0, y: 0 };
combineMove({ down: new Uint32Array(8), gamepads: [] }, move);componentCatalog()
ts
function componentCatalog(): ComponentCatalog;Describe loaded component factories as detached JSON data.
Returns
Versioned component catalog.
Example
ts
const json = JSON.stringify(componentCatalog());componentDescription()
ts
function componentDescription(name): ComponentCatalogEntry | null;Look up a component factory description, including deprecated names.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Component factory name. |
Returns
ComponentCatalogEntry | null
Detached description, or null when unknown.
Example
ts
const description = componentDescription('cameraArm');computeDrive()
ts
function computeDrive(
state,
target,
tangent,
settings,
out
): void;Write pursuit steering and longitudinal control into caller-owned storage. No transforms or allocation. tangent is the desired path direction; null uses the target heading alone.
Parameters
| Parameter | Type | Description |
|---|---|---|
state | Readonly<DriveState> | Borrowed pose and signed speed. |
target | Readonly<Vec3> | World target. |
tangent | Readonly<Vec3> | null | Path direction, if available. |
settings | Readonly<DriveSettings> | Speed, stopping distance and gains. |
out | VehicleInput | Caller-owned normalized input. |
Returns
void
Example
ts
computeDrive(state, target, null, settings, input);configureGameplayActors()
ts
function configureGameplayActors(ctx, options?): void;Configure shared actor services in init. Inventory owner indices are player seats (solo = 0). Parts and scores are automatically included in actor snapshots. Call again from each game init.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | Pick<GameContext, "world"> | Current guest context. |
options | { damage?: Damage; inventory?: Inventory; } | Component or service configuration. |
options.damage? | Damage | Shared gameplay health bookkeeping. |
options.inventory? | Inventory | Shared inventory whose owners are player seats. |
Returns
void
Example
ts
configureGameplayActors(ctx, { inventory: createInventory({owners: 2, slots: 8, items: [{id: 'key'}]}) });constraintValue()
ts
function constraintValue(actor, component?): number | null;Read a constraint coordinate in degrees (hinge) or metres; null when unavailable.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor. |
component? | string | Component name; defaults to the first constraint. |
Returns
number | null
Example
ts
const angle = constraintValue(door);controllerOf()
ts
function controllerOf(pawn): ActorHandle<object> | null;Parameters
| Parameter | Type | Description |
|---|---|---|
pawn | number | ActorHandle<object> | A pawn: its entity or its actor. |
Returns
ActorHandle<object> | null
The living controller that possesses it, or null.
Example
ts
const controller = controllerOf(self);countItem()
ts
function countItem(actor, item): number;Count bag items, excluding equipment; dead actors hold zero.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor. |
item | string | Catalog id. |
Returns
number
Total held in the bag.
Example
ts
const coins = countItem(actor, 'coin');createAbilities()
ts
function createAbilities(options): Abilities;Create preallocated charge counters. Cooldowns must be finite nonnegative seconds; zero still takes one step. Charges default to 1 and must be positive safe integers. Ids must be unique. Invalid indices and options throw. A running clock keeps the duration and dt captured when use started it, including subsequent charge cycles; spending another charge while it runs does not restart it. Queries allocate nothing.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | { abilities: readonly object[]; onReady?: (ctx, owner, ability) => void; owners: number; } | Owner capacity, ability definitions and optional recharge callback. |
options.abilities | readonly object[] | Unique ids, cooldown seconds and charge limits. |
options.onReady? | (ctx, owner, ability) => void | Synchronous notifications in owner then ability order. |
options.owners | number | Number of owner indices, not entity ids. |
Returns
Full abilities implementing the gameplay lifecycle.
Example
ts
import { createAbilities, defineGame } from 'gameable';
const skills = createAbilities({ owners: 1, abilities: [{ id: 'dash', cooldown: 0.5 }] });
export default defineGame({
init: () => skills.reset(),
systems: [(ctx) => {
if (ctx.frame % 60 === 0) skills.use(ctx, 0, 'dash');
skills.step(ctx);
}],
});createBehaviorTree()
ts
function createBehaviorTree<C>(root, options?): BehaviorTree<C>;Compile descriptions once; tick and reset use only preallocated storage.
Each entity has its own tick counter. Before a previously running node runs, if its last-ticked stamp is older than the previous tick, its entire subtree is reset. Thus skipping a branch for even one tick interrupts it; resetting is lazy until re-entry. Completed nodes reset their own memory immediately. Calls recurse only to the description's depth. Do not re-enter the same tree from a leaf. Reusing a description creates independent node occurrences.
Type Parameters
| Type Parameter |
|---|
C |
Parameters
| Parameter | Type | Description |
|---|---|---|
root | BtNode<C> | The stateless tree description. |
options? | { maxEntities?: number; } | Capacity; maxEntities defaults to 4096. |
options.maxEntities? | number | Maximum number of entities; defaults to 4096. |
Returns
BehaviorTree<C>
A tree with independent per-entity state; invalid entity ids throw RangeError.
Example
ts
import { bt, createBehaviorTree } from 'gameable';
const tree = createBehaviorTree(bt.wait<null>(0.5), { maxEntities: 200 });
tree.tick(null, 10, 1 / 60);
tree.reset(10);createCharacterMovement()
ts
function createCharacterMovement(settings?): CharacterMovement;Create independent state and allocate all per-mover scratch outside the frame loop.
Parameters
| Parameter | Type | Description |
|---|---|---|
settings | Partial<CharacterMovementSettings> | Optional overrides of the metre-based defaults. |
Returns
Computed result; caller owns or borrows it as described above.
Example
ts
const cm = createCharacterMovement({ maxWalkSpeed: 4 });createCheckpointModule()
ts
function createCheckpointModule(match, options): GameplayModule;Register checkpoint recovery before running the match.
Parameters
| Parameter | Type | Description |
|---|---|---|
match | MatchModule | Shared match state. |
options | CheckpointModuleOptions | Immutable module configuration. |
Returns
The configured module with reusable state.
Example
ts
import { createCheckpointModule, type MatchModule } from 'gameable';
const configure = (match: MatchModule) => createCheckpointModule(match, { axis: 'z', direction: 'decreasing', thresholds: [], points: [], spawns: [[0,3,0]], maxAbsX: 4, minY: 2, fallY: -5, lobbyRespawn: 'seat-start', resetKnock: true });
console.log(configure);createCircuitRace()
ts
function createCircuitRace(options): CircuitRace;Create independent lap/places state. Start expects gate 1; only a full ordered circuit awards a lap.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | CircuitOptions | Circuit identity, gate geometry and capacity. |
Returns
Preallocated crossing/ranking system and explicit snapshot adapter.
Example
ts
import { createCircuitRace } from 'gameable';
const race = createCircuitRace({id:'track',laps:2,maxRacers:4,gates:[{position:[0,0,0],yaw:0,halfExtents:[3,2,1]},{position:[0,0,10],yaw:0,halfExtents:[3,2,1]}]});
console.log(race.standings);createCrowd()
ts
function createCrowd(nav, options?): Crowd;Construct deterministic, allocation-free crowd simulation in the guest. Navigation queries must also honour their allocation-free contract.
Parameters
| Parameter | Type | Description |
|---|---|---|
nav | NavQuery | Navigation queries over walkable ground. |
options | CrowdOptions | Capacity, avoidance and application settings. |
Returns
A crowd with all storage reserved at construction.
Example
ts
import { createNavGrid, createCrowd } from 'gameable';
const nav = createNavGrid({ min: [-10, -10], max: [10, 10] });
nav.buildFlat();
const crowd = createCrowd(nav, { maxAgents: 50 });
crowd.add(1);
crowd.setPosition(1, -5, 0);
crowd.moveTo(1, 5, 0);
crowd.step(1 / 60);createDamage()
ts
function createDamage(options?): Damage;Create preallocated health bookkeeping. Call reset from game init. Callbacks run synchronously for the entity being mutated, damage before death.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | { capacity?: number; invulnerableSeconds?: number; onDamage?: (ctx, entity, amount, source) => void; onDeath?: (ctx, entity, source) => void; onHeal?: (ctx, entity, amount) => void; onRevive?: (ctx, entity) => void; } | Entity ceiling (default current ECS ceiling), i-frame duration and callbacks. |
options.capacity? | number | Fixed entity ceiling; defaults to getMaxEntities(). |
options.invulnerableSeconds? | number | Seconds of protection after a nonfatal hit; defaults to zero. |
options.onDamage? | (ctx, entity, amount, source) => void | Called with the hp actually removed, before onDeath. |
options.onDeath? | (ctx, entity, source) => void | Called once per death, after onDamage. |
options.onHeal? | (ctx, entity, amount) => void | Called with the hp actually restored. |
options.onRevive? | (ctx, entity) => void | Called after a dead entity is revived. |
Returns
A health part; its snapshot excludes the Health component itself.
Example
ts
import { createDamage, defineGame } from 'gameable';
const hits = createDamage({ invulnerableSeconds: 0.2 });
export default defineGame({ init: () => hits.reset(), systems: [ctx => hits.step(ctx)] });createGuest()
ts
function createGuest(host, definition): Guest;Create a guest from a host and a game definition.
Parameters
| Parameter | Type | Description |
|---|---|---|
host | HostApi | The host services, in guest-side JS shapes. |
definition | GameDefinition | The result of defineGame. |
Returns
The five WIT exports, plus dead and state.
Example
ts
import { createGuest } from 'gameable';
import { createMockHost, createFrameInput } from 'gameable/test';
const guest = createGuest(createMockHost(), game);
guest.init({ seed: 1, fixedHz: 60, viewportWidth: 1, viewportHeight: 1, devMode: true });
const out = guest.tick(createFrameInput({ frame: 0 }));createInventory()
ts
function createInventory(options): Inventory;Create preallocated inventories. Item ids must be unique; stacks default to 1 and must be integers in 1..65535. At most 32768 items fit the Int16 slot index. Invalid indices, amounts and options throw. Runtime operations allocate nothing.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | { items: readonly object[]; onChange?: (owner, item, total) => void; owners: number; slots: number; } | Owner/slot capacities, item definitions and optional change callback. |
options.items | readonly object[] | Unique ids and maximum per-slot stack sizes. |
options.onChange? | (owner, item, total) => void | Synchronous notifications; see Inventory for ordering. |
options.owners | number | Number of owner indices, not entity ids. |
options.slots | number | Number of slots per owner. |
Returns
Empty inventories implementing the gameplay lifecycle.
Example
ts
import { createInventory } from 'gameable';
const bags = createInventory({ owners: 2, slots: 3, items: [{ id: 'coin', stack: 99 }] });
bags.add(0, 'coin', 12);
bags.transfer(0, 1, 'coin', 4);
console.log(bags.count(1, 'coin')); // 4createMatchHudModule()
ts
function createMatchHudModule(match, options): GameplayModule;Publish private event histories and shared roster semantics without array identity misses.
Parameters
| Parameter | Type | Description |
|---|---|---|
match | MatchModule | Shared match state. |
options | MatchHudModuleOptions | Immutable module configuration. |
Returns
The configured module with reusable state.
Example
ts
import { createMatchHudModule, type MatchModule } from 'gameable';
const configure = (match: MatchModule) => createMatchHudModule(match, { namespace: 'race', secondsStep: 0.1 });
console.log(configure);createMatchModule()
ts
function createMatchModule(options): MatchModule;Construct independent match state; initialize it after guest snapshot restoration.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | MatchModuleOptions | Immutable module configuration. |
Returns
The configured module with reusable state.
Example
ts
import { createMatchModule } from 'gameable';
const match = createMatchModule({ maxPlayers: 1, history: 8, spawns: [[0,3,0]], start: 'all-ready', minPlayers: 2, soloMinPlayers: 1, lateJoin: 'spectate-after-loading', spectatorSpawnZ: 3, loadingSeconds: 20, cardSeconds: 1.5, countdownSeconds: 4.5, limitSeconds: 180, afterFirstSeconds: 90, resultsSeconds: 8 });
console.log(match.state.phase);createMoverModule()
ts
function createMoverModule(match, options): MoverModule;Build course prefabs at construction, then update poses using authority time.
Parameters
| Parameter | Type | Description |
|---|---|---|
match | MatchModule | Shared match state. |
options | MoverModuleOptions | Immutable module configuration. |
Returns
The configured module with reusable state.
Example
ts
import { createMoverModule, type MatchModule, type MoverModuleOptions } from 'gameable';
const configure = (match: MatchModule, options: MoverModuleOptions) => createMoverModule(match, options);
console.log(configure);createNavGrid()
ts
function createNavGrid(options): NavGrid;Create a bounded heightfield with allocation-free navigation queries.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | NavGridOptions | Bounds, agent dimensions and storage limits. |
Returns
An unbuilt navigation grid.
Example
ts
import { createNavGrid } from 'gameable';
const grid = createNavGrid({ min: [0, 0], max: [20, 20] });
grid.buildFlat();
const path = new Float32Array(256 * 3);
const count = grid.findPath(2, 2, 18, 18, path);
console.log(count);createPlacingModule()
ts
function createPlacingModule(match, options): GameplayModule;Award places before the match system decides whether racing has ended.
Parameters
| Parameter | Type | Description |
|---|---|---|
match | MatchModule | Shared match state. |
options | PlacingModuleOptions | Immutable module configuration. |
Returns
The configured module with reusable state.
Example
ts
import { createPlacingModule, type MatchModule } from 'gameable';
const configure = (match: MatchModule) => createPlacingModule(match, { axis: 'z', direction: 'decreasing', at: -68, maxAbsX: 5, minY: 2, maxY: 6, tieBreak: 'seat', requiresAllCheckpoints: false, freezeFinishers: true });
console.log(configure);createQuests()
ts
function createQuests(options): Quests;Create independent quest state for integer owner seats. Duplicate ids, invalid targets and cyclic or missing prerequisites throw at creation.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | { onComplete?: (owner, quest) => void; onObjectiveDone?: (owner, quest, objective) => void; onProgress?: (owner, quest, objective, value) => void; onStart?: (owner, quest) => void; owners: number; quests: readonly object[]; } | Quest definitions, owner capacity and synchronous callbacks. |
options.onComplete? | (owner, quest) => void | Called after all objective completion events. |
options.onObjectiveDone? | (owner, quest, objective) => void | Called after progress first reaches its target. |
options.onProgress? | (owner, quest, objective, value) => void | Called when an objective value changes. |
options.onStart? | (owner, quest) => void | Called when an available quest is started. |
options.owners | number | Number of independent owner seats. |
options.quests | readonly object[] | Quest ids, prerequisites and objective targets. |
Returns
A preallocated quest log; call reset from game init.
Example
ts
import { createQuests } from 'gameable';
const quests = createQuests({ owners: 2, quests: [{ id: 'win', objectives: [{ id: 'points', target: 10 }] }] });
quests.start(0, 'win');
quests.progress(0, 'win', 'points', 3);createRng()
ts
function createRng(initialSeed?): Rng;Create a seeded xoshiro128** generator.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
initialSeed | number | 1 | A 32-bit seed. 0 is remapped so the state is never all zero. |
Returns
A generator whose whole state is four integers.
createSelection()
ts
function createSelection(max?): Selection;Create a bounded selection (default 256); box projection uses pooled scratch.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
max | number | 256 | Maximum selected entities (default 256). |
Returns
A game-owned selection set.
Example
ts
const selected = createSelection(); selected.set(unit);createThirdPersonController()
ts
function createThirdPersonController(clips?, platforming?): object;Create one allocation-free camera-relative controller. Call reset in game init; update from a guest system. Tuning comes from ctx.rules: walkSpeed, runSpeed, acceleration, deceleration, jumpSpeed, landingSeconds, moveTurnRate, idleTurnRate, idleTurnThreshold and camera pitch/distance/height. canJump: false (or jumpSpeed: 0) turns jumping off: Space does nothing.
update drives the single player: ctx.player from ctx.input, with ctx.camera. updatePlayers drives a room on its authority: each player's own entity (PlayerHandle.entity, so a possess moves the controller too) from that player's own input, with that player's own camera. Each seat has its own state, made the first time the seat is seen and reset whenever the seat's entity changes (a join, a respawn, a possess). Body setup preserves look; a room camera resets only when its spawn generation is acknowledged. updateLocal drives a page's own prediction body from its local player's input and camera, using that body's entity to reset the seat state.
Parameters
| Parameter | Type | Description |
|---|---|---|
clips? | ThirdPersonClips | Optional complete base-layer clip mapping, configured once. |
platforming? | PlatformingOptions | Opt-in double jump, dash, wall jump, coyote time and buffering for physics characters. |
Returns
Persistent state, reset and update functions.
reset
ts
reset: (ctx) => void;Reset the single player's state and look; forget every seat.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | The init context. |
Returns
void
state
ts
state: object = locomotionState;state.airborne
ts
airborne: number = 0;state.descending
ts
descending: boolean = false;state.facing
ts
facing: number = Math.PI;state.grounded
ts
grounded: boolean = false;state.landing
ts
landing: number = 0;state.pitch
ts
pitch: number = 0;state.platforming
ts
platforming: object;state.platforming.buffer
ts
buffer: number = 0;state.platforming.burst
ts
burst: number = 0;state.platforming.cooldown
ts
cooldown: number = 0;state.platforming.coyote
ts
coyote: number = 0;state.platforming.jumps
ts
jumps: number = 0;state.platforming.wallLock
ts
wallLock: number = 0;state.platforming.x
ts
x: number = 0;state.platforming.z
ts
z: number = 0;state.speed
ts
speed: number = 0;state.state
ts
state: string = IDLE;state.turning
ts
turning: boolean = false;state.vx
ts
vx: number = 0;state.vz
ts
vz: number = 0;state.yaw
ts
yaw: number = 0;stateOf
ts
stateOf: (player) =>
| {
airborne: number;
descending: boolean;
facing: number;
grounded: boolean;
landing: number;
pitch: number;
platforming: {
buffer: number;
burst: number;
cooldown: number;
coyote: number;
jumps: number;
wallLock: number;
x: number;
z: number;
};
speed: number;
state: string;
turning: boolean;
vx: number;
vz: number;
yaw: number;
}
| undefined;Parameters
| Parameter | Type | Description |
|---|---|---|
player | number | A player id. |
Returns
| { airborne: number; descending: boolean; facing: number; grounded: boolean; landing: number; pitch: number; platforming: { buffer: number; burst: number; cooldown: number; coyote: number; jumps: number; wallLock: number; x: number; z: number; }; speed: number; state: string; turning: boolean; vx: number; vz: number; yaw: number; } | undefined
That seat's state, or undefined before it was first driven.
update
ts
update: (ctx, freeze) => void;Drive the single player one step.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
ctx | GameContext | undefined | The frame context. |
freeze | boolean | false | True to hold the player still. |
Returns
void
updateLocal
ts
updateLocal: (ctx, entity, freeze) => void;Drive a local body from this page's player input and camera, with its own seat state. The player camera already integrates the mouse, just as on the authority.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
ctx | GameContext | undefined | The client frame context. |
entity | number | undefined | The page's own body; 0 drives nothing. |
freeze | boolean | false | True to hold the body still. |
Returns
void
Example
ts
controller.updateLocal(ctx, ownBody);updatePlayers
ts
updatePlayers: (ctx, freeze) => void;Drive every room player's own entity one step, from their own input.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
ctx | GameContext | undefined | The frame context, on the authority. |
freeze | boolean | ((player) => boolean) | false | True to hold everyone still, or a test per player (hoist it: a function made per frame allocates), such as "this player is talking". |
Returns
void
Example
ts
const controller = createThirdPersonController();
// In init: controller.reset(ctx); in a system:
if (ctx.net.role === 'solo') controller.update(ctx);
else controller.updatePlayers(ctx);createTimers()
ts
function createTimers(options): Timers;Create preallocated timers. Invalid slots throw RangeError. Nonfinite durations or nonpositive/nonfinite timesteps throw RangeError; zero/negative durations take one step. Repeating timers rearm before callbacks. All timers advance before callbacks run.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | { capacity: number; onFire?: (ctx, timer) => void; } | Slot capacity and optional synchronous onFire callback. |
options.capacity | number | Number of timer slots. |
options.onFire? | (ctx, timer) => void | Called synchronously in ascending slot order. |
Returns
Timer slots implementing the gameplay lifecycle.
Example
ts
import { createTimers, defineGame } from 'gameable';
const timers = createTimers({ capacity: 1 });
export default defineGame({ init(ctx) { timers.reset(); timers.start(ctx, 0, 1); }, systems: [ctx => timers.step(ctx)] });createTopDownCamera()
ts
function createTopDownCamera(options?): TopDownCamera;Fixed-tilt perspective camera with keys, middle/touch drag, pinch and optional edge pan. Keep rig.state in snapshots; restore with Object.assign(rig.state, saved). Do not also declare player.camera: its host camera takes precedence.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | TopDownCameraOptions | Controls and distance/focus limits. |
Returns
A rig to update once per tick.
Example
ts
const rig = createTopDownCamera({ distance: 14 });
defineGame({ systems: [(ctx) => rig.update(ctx, ctx.dt)] });createTriggers()
ts
function createTriggers(options): Triggers;Create preallocated geometric zones. Call reset from init before adding zones. No physics or networking is consulted. Entities without Transform are outside. Events run synchronously: exits first, then enters, volume index then watch order.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | { capacity: number; compactSnapshot?: boolean; contains?: (volume, entity) => boolean; onEnter?: (ctx, volume, entity) => void; onExit?: (ctx, volume, entity) => void; watchCapacity: number; } | Fixed volume/watch ceilings and optional event callbacks. |
options.capacity | number | Maximum number of volumes. |
options.compactSnapshot? | boolean | Serialize only allocated volumes and occupied inside slots. |
options.contains? | (volume, entity) => boolean | Optional local-space containment override for moving actor shapes. |
options.onEnter? | (ctx, volume, entity) => void | Called after exits, in volume then watch order. |
options.onExit? | (ctx, volume, entity) => void | Called before enters, in volume then watch order. |
options.watchCapacity | number | Maximum number of watched entities. |
Returns
A trigger part whose snapshot includes volumes, watches and inside bits.
Example
ts
import { createTriggers, defineGame } from 'gameable';
const zones = createTriggers({ capacity: 1, watchCapacity: 1 });
export default defineGame({
init(ctx) { zones.reset(); zones.addSphere(0, 0, 0, 3); zones.watch(ctx.player); },
systems: [ctx => zones.step(ctx)],
});createTurns()
ts
function createTurns(options): Turns;Create a turn controller. Reset in init; each event-producing call supplies ctx. Time limits restart for each new turn, rather than each phase. Snapshot includes the captured dt, integer countdown, eliminated seats and skips.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | { onPhase?: (ctx, seat, phase) => void; onRound?: (ctx, round) => void; onTimeout?: (ctx, seat) => void; onTurn?: (ctx, seat, round) => void; phases?: readonly string[]; seats: number; turnSeconds?: number; } | Seats, unique phase ids, duration and ordered event callbacks. |
options.onPhase? | (ctx, seat, phase) => void | Called when a phase starts. |
options.onRound? | (ctx, round) => void | Called before turn events when a round starts. |
options.onTimeout? | (ctx, seat) => void | Called before ending an expired turn. |
options.onTurn? | (ctx, seat, round) => void | Called when an eligible seat begins its turn. |
options.phases? | readonly string[] | Unique phase ids; defaults to a single turn phase. |
options.seats | number | Number of seats, indexed from zero. |
options.turnSeconds? | number | Turn duration in seconds; zero disables timeouts. |
Returns
A preallocated controller with JSON-safe persistence.
Example
ts
import { createTurns, defineGame } from 'gameable';
const turns = createTurns({ seats: 2, turnSeconds: 30 });
export default defineGame({
init: ctx => { turns.reset(); turns.start(ctx); },
systems: [ctx => {
if (ctx.frame === 60) turns.eliminate(ctx, 0);
turns.step(ctx);
}],
});createTweens()
ts
function createTweens(options): Tweens;Create fixed-step tweens with registered lane names for snapshots. Built-in Transform lanes follow ECS resizing. Custom names must be unique and cannot shadow built-ins; each custom array must have one name. Snapshots include target values, which restore writes back into the registered lanes. Reset and stop do not change lane values. Start does not write until step. Repeat holds its final value until the next step; yoyo swaps endpoints. All final writes and loop rearming precede onDone callbacks. Nonfinite values/durations, invalid indices or timesteps throw RangeError.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | { capacity: number; lanes?: Record<string, Float32Array<ArrayBufferLike>>; onDone?: (ctx, tween) => void; } | Capacity, custom lanes and optional nonloop completion callback. |
options.capacity | number | Number of tween slots. |
options.lanes? | Record<string, Float32Array<ArrayBufferLike>> | Named custom Float32Array lanes. |
options.onDone? | (ctx, tween) => void | Called synchronously in ascending slot order for nonloop completions. |
Returns
The tween pool implementing the gameplay lifecycle.
Example
ts
import { createTweens, defineGame, Transform } from 'gameable';
const tweens = createTweens({ capacity: 8 });
export default defineGame({ init(ctx) { tweens.reset(); tweens.start(ctx, Transform.x, 1, 5, 1); }, systems: [ctx => tweens.step(ctx)] });createWalkJumpModule()
ts
function createWalkJumpModule(match, options): WalkJumpModule;Build the controller adapter; put its tuning in the game rules too.
Parameters
| Parameter | Type | Description |
|---|---|---|
match | MatchModule | Shared match state. |
options | WalkJumpModuleOptions | Immutable module configuration. |
Returns
The configured module with reusable state.
Example
ts
import { createWalkJumpModule, type MatchModule, type WalkJumpModuleOptions } from 'gameable';
const configure = (match: MatchModule, options: WalkJumpModuleOptions) => createWalkJumpModule(match, options);
console.log(configure);createWaves()
ts
function createWaves(options): Waves;Create a wave spawner. Events run synchronously: wave-start, spawn attempts in ascending index order, wave-clear, then all-clear for a nonlooping finale. A looping finale omits all-clear. Call killed when an entity dies/despawns.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | { loop?: boolean; maxAlive?: number; onAllClear?: (ctx) => void; onSpawn: (ctx, wave, index) => number; onWaveClear?: (ctx, wave) => void; onWaveStart?: (ctx, wave) => void; waves: readonly object[]; } | Wave durations in seconds, capacity and callbacks. |
options.loop? | boolean | Restart wave zero after the final clear. |
options.maxAlive? | number | Optional positive limit on simultaneous survivors. |
options.onAllClear? | (ctx) => void | Called after the final nonlooping clear. |
options.onSpawn | (ctx, wave, index) => number | Called for each attempt; return an entity or zero. |
options.onWaveClear? | (ctx, wave) => void | Called once all attempts and tracked entities are gone. |
options.onWaveStart? | (ctx, wave) => void | Called when a wave starts. |
options.waves | readonly object[] | Spawn counts and durations in seconds. |
Returns
A preallocated spawner with JSON-safe persistence.
Example
ts
import { createWaves, defineGame } from 'gameable';
const waves = createWaves({ waves: [{ count: 2, every: 0.5 }], onSpawn: () => 0 });
export default defineGame({ init: ctx => { waves.reset(); waves.start(ctx); }, systems: [ctx => waves.step(ctx)] });crossingFraction()
ts
function crossingFraction(
gate,
from,
to
): number;Forward swept plane hit fraction, or -1. Starting on the plane is not a crossing.
Parameters
| Parameter | Type | Description |
|---|---|---|
gate | CircuitGate | Gate geometry. |
from | CircuitPoint | Previous position. |
to | CircuitPoint | Current position. |
Returns
number
Fraction in (0,1], or -1.
Example
ts
console.log(crossingFraction({position:[0,0,0],yaw:0,halfExtents:[1,1,1]}, [0,0,-2], [0,0,2]));dataAsset()
ts
function dataAsset<Value>(name): FrozenData<Value> | null;Find an immutable config by name, or null when absent (including table names).
Type Parameters
| Type Parameter | Default type |
|---|---|
Value extends object | Record<string, unknown> |
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Asset name. |
Returns
FrozenData<Value> | null
The config object, or null.
Example
ts
const rules = dataAsset<{ lives: number }>('Rules');dataTable()
ts
function dataTable<Row>(name): DataTable<Row> | null;Find a registered table by name, or null when absent (including asset names).
Type Parameters
| Type Parameter | Default type |
|---|---|
Row extends object | Record<string, unknown> |
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Table name. |
Returns
DataTable<Row> | null
The typed table, or null. The caller supplies its known row type.
Example
ts
const loot = dataTable<{ weight: number }>('Loot');deactivateCamera()
ts
function deactivateCamera(ctx): void;Release the view target; normal game/player camera writes resume next step. Without another camera writer the last view remains. Safe to repeat.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Running guest context. |
Returns
void
Example
ts
deactivateCamera(ctx);deactivateEffect()
ts
function deactivateEffect(
ctx,
actor,
component?
): void;Stop the held emitter exactly once, including component destruction.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current context. |
actor | ActorHandle | Owning actor. |
component? | string | Component name. |
Returns
void
Example
ts
deactivateEffect(ctx, torch);defineAbility()
ts
function defineAbility(definition): void;Register a unique ability at module scope or during init.
Parameters
| Parameter | Type | Description |
|---|---|---|
definition | AbilityDefinition | Cost, tags and simulated-second timers. |
Returns
void
Example
ts
defineAbility({ id: 'jump', cooldown: 0, cost: { attribute: 'energy', amount: 1 } });defineActor()
ts
function defineActor<P>(name, spec): ActorClass<P>;Define a unique actor class, validating its component graph immediately. lifeSpan sets an engine-owned lifespan in seconds (the Unreal SetLifeSpan equivalent); omit it or use zero for an actor that lives until explicitly destroyed.
Type Parameters
| Type Parameter | Default type |
|---|---|
P extends object | Record<string, unknown> |
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Unique class name or instance lookup name. |
spec | ActorSpec<P> | Default components, properties and hooks. |
Returns
ActorClass<P>
The registered actor class.
Example
ts
const Marker = defineActor('Marker', { components: { root: scene() } });defineAIController()
ts
function defineAIController<P>(name, spec): ActorClass<AIControllerProps & P>;Define an AI whose component retains movement when lifecycle hooks are overridden.
Type Parameters
| Type Parameter |
|---|
P extends object |
Parameters
| Parameter | Type |
|---|---|
name | string |
spec | Omit<ActorSpec<AIControllerProps & P>, "components"> & object & object |
Returns
ActorClass<AIControllerProps & P>
Example
ts
const Guard = defineAIController('Guard', { components: { root: scene() }, onMoveCompleted(self, result, ctx) {} });defineDataAsset()
ts
function defineDataAsset<Value>(
name,
value,
schema?
): FrozenData<Value>;Validate, deeply freeze and register a single config object. Assets use their name as their catalog row key; tableRef fields must reference tables, not assets.
Type Parameters
| Type Parameter |
|---|
Value extends object |
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Unique content name. |
value | Value | Config object; an optional string description is used in the catalog. |
schema | DataSchema | Optional field constraints. |
Returns
FrozenData<Value>
The immutable config object.
Example
ts
const rules = defineDataAsset('Rules', { lives: 3 });defineDataTable()
ts
function defineDataTable<Row>(name, spec): DataTable<Row>;Define, validate and deeply freeze a table in declaration order. Missing lookups return undefined. Definitions share one namespace with assets and persist until resetDataTableRegistry(), just like actor declarations. Seed the supplied RNG in init.
Type Parameters
| Type Parameter |
|---|
Row extends object |
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Unique content name. |
spec | { description: string; rows: Record<string, Row>; schema?: DataSchema; } | Rows, optional schema and authoring description. |
spec.description | string | Authoring description. |
spec.rows | Record<string, Row> | Named content rows. |
spec.schema? | DataSchema | Optional required-field constraints. |
Returns
DataTable<Row>
The registered table.
Example
ts
const loot = defineDataTable('Loot', {
description: 'Drop weights.', rows: { coin: { weight: 3 }, gem: { weight: 1 } },
});defineEffect()
ts
function defineEffect(definition): void;Register a unique effect. Init-time definitions reset with the actor runtime; module-scope declarations seed each fresh runtime, like actor classes.
Parameters
| Parameter | Type | Description |
|---|---|---|
definition | EffectDefinition | Effect settings; stack uses independent lifetimes, refresh restarts one lifetime. |
Returns
void
Example
ts
defineEffect({ id: 'armor', duration: 'infinite', modifiers: [] });defineGame()
ts
function defineGame(spec): GameDefinition;Declare a game.
Parameters
| Parameter | Type | Description |
|---|---|---|
spec | GameSpec | The declaration. |
Returns
The frozen definition, ready for createGuest or a build.
Example
ts
import { defineGame, prefab } from 'gameable';
const Player = prefab({
body: { shape: 'capsule', dims: [0.3, 0.9], kind: 'character' },
});
export default defineGame({
assets: ['arena'],
world: { gravity: -9.81 },
player: { prefab: Player, spawn: [0, 1, 0], camera: 'firstPerson' },
systems: [(ctx) => { ctx.hud.set({ frame: ctx.frame }); }],
});defineGameMode()
ts
function defineGameMode<P>(name, spec): ActorClass<GameModeProps & P>;Define match rules without replacing the framework state machine.
Type Parameters
| Type Parameter |
|---|
P extends object |
Parameters
| Parameter | Type |
|---|---|
name | string |
spec | Omit<ActorSpec<GameModeProps & P>, "components"> & Partial<Pick<ActorSpec<GameModeProps & P>, "components">> & GameModeHooks<GameModeProps & P> |
Returns
ActorClass<GameModeProps & P>
Example
ts
const Duel = defineGameMode('Duel', { ...GameMode.spec, props: { ...GameMode.spec.props!, minPlayers: 2 } });defineMessage()
ts
function defineMessage<T>(
name,
check,
options?
): MessageDef<T>;Declare a game message. Call it at module scope, once per name: a second definition with the same name before the next init throws.
A received payload that is over maxBytes, does not parse, fails check or makes check throw is dropped and counted in ctx.net.stats.dropped; a system never sees it.
Type Parameters
| Type Parameter |
|---|
T |
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | The message name; unique within the game. |
check | MessageCheck<T> | The game's own type guard. Pure: no clock, no randomness. |
options? | MessageOptions | maxBytes, default 2,048 (the wire cap). |
Returns
MessageDef<T>
The definition.
Throws
On a duplicate name, an empty name, a name starting with aos: (reserved for the engine, as ctx.net.setPhase's aos:phase), or a maxBytes that is not a whole number from 1 to 2,048.
Example
ts
import { defineMessage, hasKeys } from 'gameable';
const hasFor = hasKeys('for');
export const Vote = defineMessage(
'vote',
(p): p is { for: number } => hasFor(p) && typeof p.for === 'number',
{ maxBytes: 64 },
);definePlayerController()
ts
function definePlayerController<P>(name, spec): ActorClass<P>;Define a seated controller whose playerTick survives ordinary actor hook overrides.
Type Parameters
| Type Parameter |
|---|
P extends object |
Parameters
| Parameter | Type |
|---|---|
name | string |
spec | Omit<ActorSpec<P>, "components"> & Partial<Pick<ActorSpec<P>, "components">> & object |
Returns
ActorClass<P>
Example
ts
const Controller = definePlayerController('MyController', { components: { root: scene() }, playerTick(self, input, ctx) {} });defineProjectile()
ts
function defineProjectile<P>(name, spec?): ActorClass<ProjectileProps & P>;Define a projectile with shared flight, lifespan and optional impact effects. Effect-only defaults require a hook at definition; instance overrides are checked at spawn.
Type Parameters
| Type Parameter | Default type |
|---|---|
P extends object | object |
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Unique actor class name. |
spec | ProjectileSpec<P> | Projectile defaults and actor hooks. |
Returns
ActorClass<ProjectileProps & P>
The registered projectile class.
Example
ts
const Spark = defineProjectile('Spark', { props: { hitResponse: 'effect' }, onProjectileHit(self, hit, ctx) { ctx.physics.applyImpulse(hit.entity, 0, 10, 0, hit.point.x, hit.point.y, hit.point.z); } });describeAsset()
ts
function describeAsset(idOrName): AssetDesc | null;Metadata for an asset handle or manifest name.
Parameters
| Parameter | Type | Description |
|---|---|---|
idOrName | string | number | A handle from assetId, or a manifest string id. |
Returns
AssetDesc | null
The description, or null when the asset is unknown.
Example
ts
import { describeAsset } from 'gameable';
const desc = describeAsset('myra');
if (desc?.kind === 'character') console.log('rig backend', desc.rig);describeDataTables()
ts
function describeDataTables(): DataTableCatalogEntry[];Describe declarations in registration order, detached from frozen runtime values.
Returns
JSON-safe entries for tables and assets, with row schemas and reference metadata.
Example
ts
const catalog = JSON.stringify(describeDataTables());despawn()
ts
function despawn(entity): void;Destroy an entity, its body and its host-side representation.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | The entity id. |
Returns
void
Nothing.
Example
ts
import { despawn } from 'gameable';
despawn(enemy);destroyActor()
ts
function destroyActor(
ctx,
handle,
reason?
): void;Queue destruction inside an actor step, or complete it immediately outside one.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
ctx | GameContext | undefined | Current game context. |
handle | ActorHandle | undefined | Actor to destroy. |
reason | EndPlayReason | 'destroyed' | Reason passed to endPlay. |
Returns
void
Example
ts
destroyActor(ctx, actor, 'levelUnload');detach()
ts
function detach(ctx, child): void;Detach while retaining the child's current world transform.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current game context. |
child | ActorHandle | Child actor to move. |
Returns
void
Example
ts
detach(ctx, child);doorState()
ts
function doorState(door): Readonly<DoorStatus>;Borrow a read-only status view; do not retain it across restore.
Parameters
| Parameter | Type | Description |
|---|---|---|
door | ActorHandle<DoorCoreProps> | Kit door instance. |
Returns
Readonly<DoorStatus>
Frozen live view of phase, fraction and lock status.
Example
ts
console.log(doorState(door).locked);driveTowards()
ts
function driveTowards(
ctx,
ai,
target,
opts?
): void;Drive a possessed car toward a point or living actor. Completion fires once through onMoveCompleted.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Frame context. |
ai | ActorHandle | AI controller. |
target | Vec3 | ActorHandle<object> | World point or actor. |
opts | DriveOptions | Speed and arrival controls. |
Returns
void
Example
ts
driveTowards(ctx, ai, { x: 0, y: 0, z: 40 }, { speed: 12 });dropThroughPlatform()
ts
function dropThroughPlatform(entity, seconds?): boolean;Drop through one-way surfaces for a short, per-character interval. Only works while supported by a SoftPlatform; ordinary floors remain solid.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | CharacterMovement capsule. |
seconds | number | 0.3 | Ignore interval, default 0.3 seconds. |
Returns
boolean
Whether a drop was requested.
Example
ts
dropThroughPlatform(hero.entity);endMatch()
ts
function endMatch(ctx, winners?): void;End the match; ties share victory unless explicit seats are supplied.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
winners? | number[] |
Returns
void
Example
ts
endMatch(ctx, [0]);endPhase()
ts
function endPhase(ctx): void;End the current phase; the final phase resolves the round by score.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current authority context. |
Returns
void
Example
ts
endPhase(ctx);endRound()
ts
function endRound(ctx, winner?): void;Resolve a round. Omitted winner uses scores; null explicitly declares a draw.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current authority context. |
winner? | number | null | Team id or player seat; null declares a draw. |
Returns
void
Example
ts
endRound(ctx, 1);equipItem()
ts
function equipItem(
actor,
slot,
item
): boolean;Move one bag item into its declared equipment slot, returning old equipment to the bag. Fails without changes when the old item cannot fit after taking the new one.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor. |
slot | string | Named equipment slot. |
item | string | Catalog id with a matching equipSlot. |
Returns
boolean
Whether equipment was set.
Example
ts
const changed = equipItem(actor, 'hand', 'sword');equipped()
ts
function equipped(actor, slot): string | undefined;Read an equipment id, or undefined for empty, unknown slots or dead actors.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor. |
slot | string | Named equipment slot. |
Returns
string | undefined
Equipped item id or undefined.
Example
ts
const weapon = equipped(actor, 'hand');faceTile()
ts
function faceTile(entity, tile): void;Turn toward a tile without stepping.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Walker entity. |
tile | Readonly<GridTile> | Target tile. |
Returns
void
Example
ts
faceTile(hero.entity, { x: 3, z: 0 });faceToward()
ts
function faceToward(entity, target): number;Turn an entity, upright, to face another entity or a point on the ground plane.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | The entity to turn. |
target | number | FlatPoint | What it should face: an entity, or a point. |
Returns
number
The yaw it now has.
Example
ts
import { faceToward } from 'gameable';
declare const npc: number;
declare const hero: number;
faceToward(npc, hero); // the NPC turns to the herofeaturesOf()
ts
function featuresOf(definition): FeatureOptions;Normalise a game's features block.
Parameters
| Parameter | Type | Description |
|---|---|---|
definition | GameDefinition | The defineGame result. |
Returns
A frozen table: feature name to its options; true becomes {}, false is dropped.
Example
ts
import { defineGame, featuresOf } from 'gameable';
const game = defineGame({ features: { characters: true, multiplayer: { maxPlayers: 6 } } });
console.log(featuresOf(game)); // { characters: {}, multiplayer: { maxPlayers: 6 } }findThing()
ts
function findThing(things, words): WorldThing | null;The thing some words name, or null.
Parameters
| Parameter | Type | Description |
|---|---|---|
things | readonly WorldThing[] | The world's things. |
words | string | What was said, for example "the trunk". |
Returns
WorldThing | null
The best match, or null when nothing answers.
Example
ts
import { findThing } from 'gameable';
const trunk = findThing(things, 'the trunk');
console.log(trunk?.label); // 'steamer trunk'findThings()
ts
function findThings(
things,
words,
out?
): WorldThing[];Every thing that answers some words, the best first.
An occasional question, not a per-step one: it splits the words asked.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
things | readonly WorldThing[] | undefined | The world's things. |
words | string | undefined | What was said, for example "the trunk" or "walk to the round window". |
out | WorldThing[] | [] | The array to fill; emptied first. |
Returns
out.
Example
ts
import { findThings, type WorldThing } from 'gameable';
const found: WorldThing[] = [];
findThings(things, 'a box', found);
console.log(found.map((thing) => thing.label)); // ['hat box', 'steamer trunk']fireImpulse()
ts
function fireImpulse(
ctx,
actor,
component?
): void;Fire a radial component once; omitting the name selects the first radial component.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
actor | ActorHandle |
component? | string |
Returns
void
Example
ts
fireImpulse(ctx, explosion, 'force');fitBox()
ts
function fitBox(vertices): FittedShape;Fit the local AABB; scale must already be baked into vertices.
Parameters
| Parameter | Type | Description |
|---|---|---|
vertices | Float32Array | Mesh-local xyz points in metres. |
Returns
Box half-extents and center, with identity rotation.
Example
ts
const box = fitBox(new Float32Array([-1,-1,-1,1,1,1]));fitCapsule()
ts
function fitCapsule(vertices): FittedShape;Fit a longest-bounds-axis capsule, ties X then Y then Z. Expand the radial heuristic to enclose every vertex before applying the length rule.
Parameters
| Parameter | Type | Description |
|---|---|---|
vertices | Float32Array | Mesh-local xyz points, with scale pre-baked. |
Returns
Capsule radius and cylindrical half-height, with local Y rotated onto its axis.
Example
ts
const capsule = fitCapsule(new Float32Array([0,-2,0,1,2,0,-1,2,0]));fitKDop()
ts
function fitKDop(vertices, count): Float32Array;Fit 10X, 18 or 26 outward support planes and return convex-hull xyz points. No decomposition or padding is applied. Pre-bake build scale into the vertices.
Parameters
| Parameter | Type | Description |
|---|---|---|
vertices | Float32Array | Nonempty finite mesh-local xyz points. |
count | 10 | 18 | 26 | Number of support directions; 10 means the 10X variant. |
Returns
Float32Array
Packed convex hull vertices for engine convex geometry.
Example
ts
const points = fitKDop(new Float32Array([-1,-1,-1,1,1,1]), 26);fitSphere()
ts
function fitSphere(vertices): FittedShape;Choose the smaller of the incremental sphere and AABB-center sphere.
Parameters
| Parameter | Type | Description |
|---|---|---|
vertices | Float32Array | Mesh-local xyz points, with scale pre-baked. |
Returns
Enclosing sphere; zero-radius meshes fail.
Example
ts
const sphere = fitSphere(new Float32Array([-1,0,0,1,0,0]));flyingMovement()
ts
function flyingMovement(opts?): ActorComponent;Fly a pawn with acceleration, braking and player-relative movement.
Parameters
| Parameter | Type |
|---|---|
opts | { acceleration?: number; deceleration?: number; maxSpeed?: number; } |
opts.acceleration? | number |
opts.deceleration? | number |
opts.maxSpeed? | number |
Returns
Example
ts
const movement = flyingMovement({ maxSpeed: 12 });followRacingLine()
ts
function followRacingLine(
ctx,
ai,
line,
opts?
): void;Follow a sampled spline or explicitly ordered TargetPoints; positions are captured at request time.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Frame context. |
ai | ActorHandle | AI controller. |
line | | readonly string[] | { actor: string; component: string; } | Named spline component or ordered TargetPoint names. |
opts | RacingLineOptions | Line speed, lookahead and rival offset. |
Returns
void
Example
ts
followRacingLine(ctx, ai, { actor: 'track', component: 'line' }, { speed: 18, loop: true });formationSlot()
ts
function formationSlot(
i,
n,
spacing,
yaw,
out
): Vec3;Write a centred grid slot, front (+Z) row first, rotated about +Y by yaw radians. Rows contain ceil(sqrt(n)) slots; the final partial row is centred separately. Invalid indices and empty formations write zero. No allocations.
Parameters
| Parameter | Type | Description |
|---|---|---|
i | number | Zero-based slot index. |
n | number | Number of formation members. |
spacing | number | Distance between slots in metres. |
yaw | number | Facing in radians about +Y. |
out | Vec3 | Caller-owned offset vector. |
Returns
The supplied offset vector.
Example
ts
formationSlot(0, 4, 2, 0, offset);gameMode()
ts
function gameMode():
| ActorHandle<GameModeProps>
| null;The live mode, including a derived class.
Returns
| ActorHandle<GameModeProps> | null
Example
ts
const mode = gameMode();gameState()
ts
function gameState():
| ActorHandle<GameStateProps>
| null;The mode's live public state actor.
Returns
| ActorHandle<GameStateProps> | null
Example
ts
const elapsed = gameState()?.props.elapsed;gameUrl()
ts
function gameUrl(address): string;Sanitize and resolve a game file address, safely repeatable on its own output. game:x uses the game folder; /x is its legacy spelling. Bundler URLs already under the game folder and site service mounts retain their paths. Relative paths and http(s), data, blob and protocol-relative URLs are unchanged. File URLs are also unchanged when no browser page exists.
Parameters
| Parameter | Type | Description |
|---|---|---|
address | string | A game file address. |
Returns
string
The resolved address.
Throws
For controls, backslashes, unsafe schemes or paths escaping the game folder.
Example
ts
import { resolveGameAddress } from 'gameable/assets';
const response = await fetch(resolveGameAddress('game:worlds/attic/world.json'));
console.log(response.ok);getAttribute()
ts
function getAttribute(actor, name): number;Read the clamped modified value.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor handle. |
name | string | Declared attribute name. |
Returns
number
The current modified value.
Example
ts
const hp = getAttribute(hero, 'health');getAttributeBase()
ts
function getAttributeBase(actor, name): number;Read the permanent base value.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor handle. |
name | string | Declared attribute name. |
Returns
number
The permanent base value.
Example
ts
const hp = getAttributeBase(hero, 'health');getMaxEntities()
ts
function getMaxEntities(): number;How many entities the built-in component arrays currently hold.
Returns
number
The configured entity ceiling.
grantAbility()
ts
function grantAbility(actor, id): boolean;Grant a registered ability once; false means client or capacity rejection.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor handle. |
id | string | Registered effect or ability id. |
Returns
boolean
Whether the ability is granted.
Example
ts
grantAbility(hero, 'jump');gridInputFromKeys()
ts
function gridInputFromKeys(ctx, directions?): GridDirection | undefined;Read WASD/arrows, with the newest pressed key winning. Simultaneous presses use W/up, S/down, D/right, A/left order. Call once in init to preallocate key history. Eight-way mode combines the newest horizontal and vertical keys.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
ctx | GameContext | undefined | Input context. |
directions | 4 | 8 | 4 | Four by default; pass the component's direction count. |
Returns
GridDirection | undefined
A compass direction, or undefined when no movement key is held.
Example
ts
const dir = gridInputFromKeys(ctx); if (dir) requestGridMove(hero.entity, dir);gridMovement()
ts
function gridMovement(options?): ActorComponent;Kinematic tile stepping. Use as the actor root; north is -Z. Origin is tile (0,0)'s centre. Requests made in actor ticks/systems are consumed on the following component step. A fresh hold spends turnInPlaceSeconds turning before walking; continuing steps have no delay.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | GridMovementOptions | Tile geometry, timing, collision policy and borrowed-tile callbacks. |
Returns
A kinematic capsule or box component.
Example
ts
const root = gridMovement({ stepSeconds: 0.22, collision: 'Pawn' });gridStateOf()
ts
function gridStateOf(entity): Readonly<GridState>;Read borrowed state.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Walker entity. |
Returns
Readonly<GridState>
Current state.
Example
ts
const moving = gridStateOf(hero.entity).moving;hasAllTags()
ts
function hasAllTags(actor, tags): boolean;Test all hierarchical tags; an empty list succeeds.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor handle. |
tags | readonly string[] | Tag queries to match. |
Returns
boolean
Whether every query matches.
Example
ts
const ready = hasAllTags(hero, ['weapon', 'state.ready']);hasAnyTag()
ts
function hasAnyTag(actor, tags): boolean;Test any hierarchical tag.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor handle. |
tags | readonly string[] | Tag queries to match. |
Returns
boolean
Whether at least one query matches.
Example
ts
const busy = hasAnyTag(hero, ['state.stunned', 'state.dead']);hasEffect()
ts
function hasEffect(actor, id): boolean;Test for at least one active effect stack.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor handle. |
id | string | Registered effect or ability id. |
Returns
boolean
Whether any stack is active.
Example
ts
const armored = hasEffect(hero, 'armor');hasItem()
ts
function hasItem(
actor,
item,
amount?
): boolean;Test bag contents, excluding equipment.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
actor | ActorHandle | undefined | Owning actor. |
item | string | undefined | Catalog id. |
amount | number | 1 | Nonnegative safe integer; defaults to one. |
Returns
boolean
Whether the bag holds the requested amount.
Example
ts
if (hasItem(actor, 'key')) actor.state.unlocked = true;hasKeys()
ts
function hasKeys<K>(...keys): (x) => x is Record<K, unknown>;A guard for a record with every one of keys as an own property (any value, even undefined); extra keys are allowed. Make it once, at module scope: the guard it returns allocates nothing per call.
Type Parameters
| Type Parameter |
|---|
K extends string |
Parameters
| Parameter | Type | Description |
|---|---|---|
...keys | K[] | The keys a payload must have. |
Returns
The guard.
(x) => x is Record<K, unknown>
Example
ts
const hasItemSlot = hasKeys('item', 'slot');
const Pick = defineMessage(
'pick',
(p): p is { item: string; slot: number } =>
hasItemSlot(p) && typeof p.item === 'string' && typeof p.slot === 'number',
);hasTag()
ts
function hasTag(actor, tag): boolean;Query tags hierarchically: state.stunned matches state, but state does not match state.stunned.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor. |
tag | string | Exact tag or ancestor. |
Returns
boolean
Whether any manual or granted tag matches.
Example
ts
if (hasTag(hero, 'state')) hero.state.busy = true;hitUnderCursor()
ts
function hitUnderCursor(
ctx,
out,
opts?
): boolean;Raycast through the pointer and copy a hit into caller-owned storage. Query is physics.raycast's layer mask; default distance is 500 metres. This helper allocates nothing; physics.raycast's host/ABI may allocate its result. False on an unusable camera or a miss, leaving out unchanged.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
out | CursorHit |
opts? | { maxDistance?: number; query?: CollisionLayers; } |
opts.maxDistance? | number |
opts.query? | CollisionLayers |
Returns
boolean
Example
ts
if (hitUnderCursor(ctx, hit)) console.log(hit.entity);hostMoveQuery()
ts
function hostMoveQuery(
entity,
capsule,
mask?
): MoveQuery;Adapt guest physics queries to the movement solver. Results are borrowed until the next call. The guest supplies contact points rather than penetration normals; normals point from the contact toward the closest capsule segment point, with a deterministic horizontal escape at zero distance.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Mover entity to exclude from every probe. |
capsule | Capsule | Radius and straight-section half height in metres. |
mask? | CollisionLayers | Blocking layers, or all layers when omitted. |
Returns
Reusable query adapter.
Example
ts
const query = hostMoveQuery(player, { radius: 0.35, halfHeight: 0.55 });inputFor()
ts
function inputFor(ctx, pawn):
| {
touch: {
get active(): boolean;
get pinch(): number;
get turn(): number;
stick: Axis2;
};
get control(): Readonly<NonNullable<InputState["control"]>>;
get focused(): boolean;
get mods(): InputMods;
get mouse(): MouseState;
action: ActionState;
axis2: Axis2;
gamepad: | {
axes: ArrayLike<number>;
buttons: number;
connected: boolean;
index: number;
pressed: number;
released: number;
}
| null;
isDown: boolean;
mouseDown: boolean;
mousePressed: boolean;
mouseReleased: boolean;
pressed: boolean;
released: boolean;
}
| null;The input that drives a pawn: its player's, or null for an AI's pawn or no controller.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | The game context. |
pawn | number | ActorHandle<object> | The pawn. |
Returns
The player's input, read like ctx.input, or null.
Type Literal
ts
{
touch: {
get active(): boolean;
get pinch(): number;
get turn(): number;
stick: Axis2;
};
get control(): Readonly<NonNullable<InputState["control"]>>;
get focused(): boolean;
get mods(): InputMods;
get mouse(): MouseState;
action: ActionState;
axis2: Axis2;
gamepad: | {
axes: ArrayLike<number>;
buttons: number;
connected: boolean;
index: number;
pressed: number;
released: number;
}
| null;
isDown: boolean;
mouseDown: boolean;
mousePressed: boolean;
mouseReleased: boolean;
pressed: boolean;
released: boolean;
}touch
ts
touch: object;Fingers on a touch screen, as the host's touch layer packs them: the first finger is the pointer (mouse), a tap is pressed('Tap'), and the thumb sticks, the pinch and the turn are here.
touch.active
Get Signature
ts
get active(): boolean;Is a finger on the screen? (The touch pad is connected.)
Returns
boolean
True while any finger is down.
touch.pinch
Get Signature
ts
get pinch(): number;Two fingers' pinch this step, as a scale factor: over 1 the fingers moved apart (zoom in), under 1 together, exactly 1 with no pinch.
Returns
number
The scale factor.
touch.turn
Get Signature
ts
get turn(): number;Two fingers' turn this step, in radians, counter-clockwise on the screen positive.
Returns
number
The turn.
touch.stick()
ts
stick(side): Axis2;A thumb stick's push.
Parameters
| Parameter | Type | Description |
|---|---|---|
side | "left" | "right" | The left stick (movement) or the right one (the camera). |
Returns
A pooled { x, y }, -1..1, y up the screen positive. Never retain it.
control
Get Signature
ts
get control(): Readonly<NonNullable<InputState["control"]>>;Received page control for this frame. Owned by the SDK; read during the tick.
Returns
Readonly<NonNullable<InputState["control"]>>
The control state received with this input sequence.
focused
Get Signature
ts
get focused(): boolean;Does the canvas have focus? Treat input as neutral when it does not.
Returns
boolean
True while the canvas is focused.
mods
Get Signature
ts
get mods(): InputMods;Keyboard modifier state.
Returns
The modifiers for this frame.
mouse
Get Signature
ts
get mouse(): MouseState;Pointer position, per-frame delta, wheel and button bitsets.
Returns
The mouse state for this frame. Owned by the SDK; never retain it.
action()
ts
action(name): ActionState;Read a declared button into pooled storage. Unknown names throw.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Declared button action name. |
Returns
Pooled button state; read immediately.
axis2()
ts
axis2(
negX,
posX?,
negY?,
posY?,
stick?
): Axis2;Pass a declared axis action name alone, or four keys. A two-axis reading built from four keys, plus a thumb stick on a touch screen: the left one by default, so axis2('A', 'D', 'S', 'W') moves on a phone with no other binding. Pass 'right' for a camera axis, 'none' for keys only. With the left stick and opposing WASD/arrow movement pairs, uses combined movement (both key sets, left touch and first physical pad, radial deadzone and unit-circle clamp), with each binding's requested sign. Page control supplies that same movement when present. Other bindings read only their four keys and the requested touch stick.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
negX | string | undefined | Declared axis name, or key driving x negative, e.g. 'A'. |
posX? | string | undefined | Key that drives x positive, for example 'D'. |
negY? | string | undefined | Key that drives y negative, for example 'S'. |
posY? | string | undefined | Key that drives y positive, for example 'W'. |
stick? | StickSide | 'left' | Which thumb stick to add, 'left' by default. |
Returns
A pooled { x, y } with components in -1..1. Never retain it.
gamepad()
ts
gamepad(index):
| {
axes: ArrayLike<number>;
buttons: number;
connected: boolean;
index: number;
pressed: number;
released: number;
}
| null;One connected gamepad.
Parameters
| Parameter | Type | Description |
|---|---|---|
index | number | Navigator gamepad index. |
Returns
| { axes: ArrayLike<number>; buttons: number; connected: boolean; index: number; pressed: number; released: number; } | null
The gamepad, or null when nothing is connected at that index. Owned by the SDK; never retain it.
isDown()
ts
isDown(key): boolean;Is the key held this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
key | string | A DOM code ('KeyW'), a bare letter/digit ('W', '1') or an alias ('Shift', 'Esc'). |
Returns
boolean
True while the key is down.
mouseDown()
ts
mouseDown(button): boolean;Is a mouse button held?
Parameters
| Parameter | Type | Description |
|---|---|---|
button | number | A MOUSE_BUTTONS value, or a raw bit mask. |
Returns
boolean
True while the button is down.
mousePressed()
ts
mousePressed(button): boolean;Did a mouse button go down this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
button | number | A MOUSE_BUTTONS value, or a raw bit mask. |
Returns
boolean
True on the frame the button went down.
mouseReleased()
ts
mouseReleased(button): boolean;Did a mouse button come up this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
button | number | A MOUSE_BUTTONS value, or a raw bit mask. |
Returns
boolean
True on the frame the button came up.
pressed()
ts
pressed(key): boolean;Did the key go down this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
key | string | A key name. |
Returns
boolean
True on the frame the key went down.
released()
ts
released(key): boolean;Did the key come up this frame?
Parameters
| Parameter | Type | Description |
|---|---|---|
key | string | A key name. |
Returns
boolean
True on the frame the key came up.
null
Example
ts
const move = inputFor(ctx, self)?.axis('move');interactable()
ts
function interactable(): ActorComponent;Add interaction to any actor; its props include InteractableProps and its spec supplies onInteract. The actor runtime's optional onInteract hook keeps callbacks out of level JSON.
Returns
The reusable component declaration.
Example
ts
const Terminal = defineActor('Terminal', {components: {root: scene(), use: interactable()}, props: {prompt: 'Use',range: 2,facingDegrees: 75,action: 'E',once: false,enabled: true}, onInteract(self, who, ctx) { console.log(who); }});interactionNotice()
ts
function interactionNotice(
ctx,
seat,
message
): void;Publish a short notice to one player using the preallocated interaction model.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current guest context. |
seat | number | Player seat index. |
message | string | Notice text. |
Returns
void
Example
ts
interactionNotice(ctx, 0, 'Find the key');inventoryComponent()
ts
function inventoryComponent(options): ActorComponent;Attach a bag and named equipment to each actor. Owner indices are reused lowest first. Each distinct schema gets one library per runtime; identical schemas share it, even with different callbacks. Library storage allocates once on the first spawn of each schema; subsequent item calls allocate nothing. Equipment swaps emit bag removal/addition followed by unequipped/equipped events. Destruction and snapshot restoration are silent. Dropping world pickups is not supported.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | InventoryComponentOptions | Bag schema and event callbacks. |
Returns
A scene component with authority lifecycle hooks.
Example
ts
import { defineActor, scene, inventoryComponent } from 'gameable';
const Chest = defineActor('Chest', {
components: { root: scene(), bag: inventoryComponent({ slots: 8, items: [{ id: 'coin', stack: 99 }] }) },
});isDoor()
ts
function isDoor(actor): boolean;Marker-based identification, including legacy Door and derived specs.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle<object> | null | undefined | Candidate actor instance. |
Returns
boolean
Whether the actor carries the door marker.
Example
ts
if (isDoor(actor)) console.log(actor.name);isDoorOpen()
ts
function isDoorOpen(door): boolean;Whether the door is fully open.
Parameters
| Parameter | Type | Description |
|---|---|---|
door | ActorHandle | Kit or legacy door instance. |
Returns
boolean
Whether the panel is fully open.
Example
ts
if (isDoorOpen(door)) leave();isRecord()
ts
function isRecord(x): x is Record<string, unknown>;A plain JSON object: not null, not an array.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | unknown | A parsed payload. |
Returns
x is Record<string, unknown>
True for an object record.
Example
ts
const Move = defineMessage('move', (p): p is { x: number } => isRecord(p) && typeof p.x === 'number');isSignalOn()
ts
function isSignalOn(actor): boolean;Read the shared actor signal contract.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle<object> | null | undefined | Signal source, or a missing actor. |
Returns
boolean
Whether the signal reports on.
Example
ts
if (isSignalOn(lever)) openDoor(ctx, door);isSoundPlaying()
ts
function isSoundPlaying(actor, component?): boolean;Read playback status after the latest sound-ended events.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor. |
component? | string | Audio component name. |
Returns
boolean
Whether the sound remains live.
Example
ts
const playing = isSoundPlaying(actor);jump()
ts
function jump(entity): void;Request a jump on the next movement tick; airborne requests are consumed too.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Actor root entity. |
Returns
void
Example
ts
jump(player);keyIndex()
ts
function keyIndex(name): number;Bit index for a key name, or -1 when the name is unknown. Names are case-sensitive, except that a bare letter or F-key also answers in lower case ('w', 'f1'). Allocates nothing.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | A DOM KeyboardEvent.code, a bare letter/digit, or an alias. |
Returns
number
The bit index in 0..255, or -1.
keyIndex2()
ts
function keyIndex2(name): number;Second bit index for names that cover a left/right pair ('Shift'), or -1. Case-sensitive, like the aliases it covers. Allocates nothing.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | A key name or alias. |
Returns
number
The second bit index, or -1 when the name maps to one key.
lastDamageInstigator()
ts
function lastDamageInstigator(entity): number;Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | An entity. |
Returns
number
The instigator entity of the last hit that removed its health, or 0.
Example
ts
const killer = lastDamageInstigator(pawn);launchCharacter()
ts
function launchCharacter(
entity,
velocity,
xyOverride,
zOverride
): void;Launch into falling mode, adding or replacing horizontal and vertical velocity.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Actor root entity. |
velocity | Vec3 | Launch velocity in metres per second. |
xyOverride | boolean | Replace horizontal (world X/Z) velocity. |
zOverride | boolean | Replace vertical (world Y) velocity, the option name uses a Z-up convention. |
Returns
void
Example
ts
launchCharacter(player, { x: 2, y: 6, z: 0 }, true, true);levelActorNames()
ts
function levelActorNames(level): string[];Resolve the name of every entry in a level, in file order.
Parameters
| Parameter | Type | Description |
|---|---|---|
level | LevelFile | The level document. |
Returns
string[]
One name per entry: the written one, or the automatic one.
Example
ts
const names = levelActorNames({ format: 1, actors: [{ class: 'Door', position: [0, 0, 0] }] }); // ['Door1']levelDocumentOf()
ts
function levelDocumentOf(level): string;A level document as a file: two-space indent, a number or string list on one line, a newline at the end, the way the templates' level files are written. A save by hand and a save by a worker then look the same.
Parameters
| Parameter | Type | Description |
|---|---|---|
level | LevelFile | The document. |
Returns
string
The file's text.
Example
ts
const text = levelDocumentOf(applyLevelEdits(level, edits));limitWalk()
ts
function limitWalk(
walk,
x,
z,
velocity
): void;Keep a walker inside the world's walk limit: change the velocity it asked for.
A room's walls do the stopping (inside-collision: nothing changes here). An open place has a circle with a soft edge: from fadeFrom outward the speed away from the middle falls off, at radius it is none, and past it the walker is eased back in. Walking along the edge or back in is never slowed.
Parameters
| Parameter | Type | Description |
|---|---|---|
walk | WorldWalk | The world's walk limit. |
x | number | Where the walker is, x. |
z | number | Where the walker is, z. |
velocity | Vec3 | The velocity asked for; x and z are changed in place. |
Returns
void
Nothing.
Example
ts
import { limitWalk } from 'gameable';
const velocity = { x: 2, y: 0, z: 0 };
limitWalk(list.walk, 12.5, 0, velocity);
console.log(velocity.x); // 1: half way through the soft edge of an 11 to 14 metre limitloadAsset()
ts
function loadAsset(idOrName, priority?): void;Ask the host to start loading an asset.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
idOrName | string | number | undefined | A handle or manifest string id. |
priority | number | 0 | Higher runs first. Default 0. |
Returns
void
Nothing.
Example
ts
import { loadAsset } from 'gameable';
loadAsset('boss-arena', 10);loadLevel()
ts
function loadLevel(
ctx,
level,
options?
): object;Spawn in file order, then attach using local position and rotation. Validates before spawning. Every actor gets a source naming the level and its entry, and a name (the entry's, or the automatic one), so an editor can list it and write it back.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current guest context. |
level | LevelFile | Level document. |
options | LoadLevelOptions | The level's name for the actors' sources. |
Returns
object
Handles in file order and a dictionary of actors by name.
actors
ts
actors: ActorHandle<object>[];named
ts
named: Record<string, ActorHandle>;Example
ts
const { named } = loadLevel(ctx, { format: 1, actors: [{ class: 'Door', name: 'gate', position: [0, 0, 8] }] });lockDoor()
ts
function lockDoor(door, item): void;Lock future opening requests with an inventory item.
Parameters
| Parameter | Type | Description |
|---|---|---|
door | ActorHandle<DoorCoreProps> | Kit door instance. |
item | string | Required inventory item id. |
Returns
void
Example
ts
lockDoor(door, 'key');lowerCollision()
ts
function lowerCollision(input): LoweredCollision;Map collision policy onto engine body fields. Prefab spawn carries the overlap mask to a companion sensor when both block and overlap channels are present.
Parameters
| Parameter | Type | Description |
|---|---|---|
input | | "Spectator" | CollisionSetup | "NoCollision" | "BlockAll" | "OverlapAll" | "BlockAllDynamic" | "OverlapAllDynamic" | "IgnoreOnlyPawn" | "OverlapOnlyPawn" | "Pawn" | "CharacterMesh" | "PhysicsActor" | "Destructible" | "InvisibleWall" | "InvisibleWallDynamic" | "Trigger" | "Ragdoll" | "Vehicle" | "UI" | Named profile or custom setup. |
Returns
Body fields, overlap mask and query-only metadata.
Example
ts
const fields = lowerCollision('BlockAll');markMoved()
ts
function markMoved(entity, flags?): void;Tell the packer an entity's Transform changed.
spawn and the built-in velocity integration mark for you. Two cases they do not cover: a system that writes Transform.x[e] (or any other lane) by hand, and a body-driven entity, whose transform the host now owns outright — BodyIndex.ingest copies the physics rows in for the guest to read and deliberately does not mark them. Either way, nothing notices the write, the row is never packed and the host never moves the object. Call this after such a write. To move a physics body, send a command (setBodyTransform) rather than writing the lane.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Entity id. Out-of-range ids are ignored. |
flags | number | TRANSFORM_ALL | Which lanes changed; defaults to position, rotation and scale. |
Returns
void
Nothing.
Example
ts
import { Transform, TRANSFORM_FLAGS, markMoved } from 'gameable';
Transform.y[e] = Transform.y[e] + 0.1;
markMoved(e, TRANSFORM_FLAGS.POSITION);matchState()
ts
function matchState(): MatchState;Current match lifecycle, or waiting before a mode exists.
Returns
Example
ts
const state = matchState();matchSummary()
ts
function matchSummary(): Readonly<MatchSummary>;Borrow the current match summary for composition into the game's own HUD. The object and its rows are reused: copy them if a historical value is needed.
Returns
Readonly<MatchSummary>
Example
ts
ctx.hud.set({ score: 10, match: matchSummary() });maxEntities()
ts
function maxEntities(): number;The entity ceiling the built-in components are currently sized for.
Returns
number
The configured maximum.
Example
ts
import { maxEntities } from 'gameable';
console.log(maxEntities()); // 4096mergeTileColliders()
ts
function mergeTileColliders(cells, cellSize?): TileCollisionBox[];Greedily merge identical-height cells, scanning z then x and extending x first. Duplicate cells collapse; conflicting duplicate heights throw. This deterministic greedy cover reduces seams but is not a globally minimum rectangle partition. Cell (x,z) covers [x,x+1] by [z,z+1], scaled by cellSize.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
cells | readonly CollisionCell[] | undefined | Occupied integer grid coordinates and positive heights. |
cellSize | number | 1 | Horizontal grid spacing in metres, default one. |
Returns
Disjoint boxes preserving occupied volume.
Example
ts
const boxes = mergeTileColliders([{ x: 0, z: 0, height: 1 }, { x: 1, z: 0, height: 1 }]);mesh()
ts
function mesh(assetName, opts?): ActorComponent;A renderable addressed by its manifest id.
Parameters
| Parameter | Type | Description |
|---|---|---|
assetName | string | Manifest asset id. |
opts | ShapeOptions | Local transform or spawn options. |
Returns
The mesh component declaration.
Example
ts
import { mesh } from 'gameable';
const look = mesh('crate');
const house = mesh('thing.house', { fit: 'box' }); // collides as drawnmoduleCatalog()
ts
function moduleCatalog(): ModuleCatalog;Describe loaded gameplay factories as detached JSON data.
Returns
Gameplay module catalog.
Example
ts
const json = JSON.stringify(moduleCatalog());moveItem()
ts
function moveItem(
actor,
from,
to
): void;Merge matching stacks or swap bag slots; emits no item events.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor. |
from | number | Source bag slot. |
to | number | Destination bag slot. |
Returns
void
Example
ts
moveItem(actor, 0, 1);movementOf()
ts
function movementOf(entity):
| {
floor: FloorResult;
isFalling: boolean;
isMovingOnGround: boolean;
mode: "walking" | "falling";
velocity: Readonly<Vec3>;
}
| undefined;Read borrowed solver state, or undefined for an entity without this component.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Actor root entity. |
Returns
| { floor: FloorResult; isFalling: boolean; isMovingOnGround: boolean; mode: "walking" | "falling"; velocity: Readonly<Vec3>; } | undefined
Current movement mode, velocity and floor.
Example
ts
const airborne = movementOf(player)?.isFalling;moverCarry()
ts
function moverCarry(
mover,
contact,
previousX,
currentX,
x,
y,
z,
grounded
): number | undefined;Return supported X displacement using the authority's strict foot bounds.
Parameters
| Parameter | Type | Description |
|---|---|---|
mover | { bounds: readonly number[]; carry: boolean; collider: { dims: readonly number[]; rotation: readonly number[]; shape: "box" | "capsule"; }; id: string; knock: "none" | "rotating-tangent" | "toward-center"; motion: | { angularRate: number; kind: "rotate-y"; } | { amplitude: number; angularRate: number; kind: "sine-x"; phase: number; }; position: readonly number[]; } | Authored platform bounds and base position. |
mover.bounds | readonly number[] | - |
mover.carry | boolean | - |
mover.collider | { dims: readonly number[]; rotation: readonly number[]; shape: "box" | "capsule"; } | - |
mover.collider.dims | readonly number[] | - |
mover.collider.rotation | readonly number[] | - |
mover.collider.shape | "box" | "capsule" | - |
mover.id | string | - |
mover.knock | "none" | "rotating-tangent" | "toward-center" | - |
mover.motion | | { angularRate: number; kind: "rotate-y"; } | { amplitude: number; angularRate: number; kind: "sine-x"; phase: number; } | - |
mover.position | readonly number[] | - |
contact | { carryTolerance: number; foot: number; } | Foot offset and support tolerance. |
contact.carryTolerance | number | - |
contact.foot | number | - |
previousX | number | Last consumed replicated or authority X. |
currentX | number | Current platform X. |
x | number | Player centre X. |
y | number | Player centre Y. |
z | number | Player centre Z. |
grounded | boolean | Whether the character has walkable ground contact. |
Returns
number | undefined
X displacement, or undefined for unsupported feet.
Example
ts
import { moverCarry, type MoverModuleOptions } from 'gameable';
const supported = (mover: MoverModuleOptions['movers'][number], contact: MoverModuleOptions['contact']) =>
moverCarry(mover, contact, 0, 0.1, 0, 3.15, -34.5, true);
console.log(supported);moverPose()
ts
function moverPose(
mover,
time,
out
): void;Compute an authority mover pose into reusable storage.
Parameters
| Parameter | Type | Description |
|---|---|---|
mover | { bounds: readonly number[]; carry: boolean; collider: { dims: readonly number[]; rotation: readonly number[]; shape: "box" | "capsule"; }; id: string; knock: "none" | "rotating-tangent" | "toward-center"; motion: | { angularRate: number; kind: "rotate-y"; } | { amplitude: number; angularRate: number; kind: "sine-x"; phase: number; }; position: readonly number[]; } | Authored motion and base position. |
mover.bounds | readonly number[] | - |
mover.carry | boolean | - |
mover.collider | { dims: readonly number[]; rotation: readonly number[]; shape: "box" | "capsule"; } | - |
mover.collider.dims | readonly number[] | - |
mover.collider.rotation | readonly number[] | - |
mover.collider.shape | "box" | "capsule" | - |
mover.id | string | - |
mover.knock | "none" | "rotating-tangent" | "toward-center" | - |
mover.motion | | { angularRate: number; kind: "rotate-y"; } | { amplitude: number; angularRate: number; kind: "sine-x"; phase: number; } | - |
mover.position | readonly number[] | - |
time | number | Authority elapsed seconds. |
out | { x: number; y: number; yaw: number; z: number; } | Caller-owned pose storage. |
out.x | number | - |
out.y | number | - |
out.yaw | number | - |
out.z | number | - |
Returns
void
Example
ts
import { moverPose, type MoverModuleOptions } from 'gameable';
const sample = (mover: MoverModuleOptions['movers'][number]) => {
const pose = { x: 0, y: 0, z: 0, yaw: 0 };
moverPose(mover, 1, pose);
return pose;
};
console.log(sample);moveState()
ts
function moveState(pawn): "idle" | "moving" | "arrived" | "failed";Read the current pawn's order; unknown or destroyed pawns are idle.
Parameters
| Parameter | Type | Description |
|---|---|---|
pawn | number | Character actor root entity. |
Returns
"idle" | "moving" | "arrived" | "failed"
Current walking request status.
Example
ts
const arrived = moveState(player) === 'arrived';moveStatus()
ts
function moveStatus(ai): "idle" | "moving";Read the controller's current movement status.
Parameters
| Parameter | Type |
|---|---|
ai | ActorHandle |
Returns
"idle" | "moving"
Example
ts
const moving = moveStatus(ai) === 'moving';moveThing()
ts
function moveThing(
thing,
position,
rotation,
moved?
): void;Put a thing somewhere new: its position, its turn, and its box round both.
The host's loader and the guest's list both call this, so the box a game reads is the same on either side.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
thing | WorldThing | undefined | The thing; changed in place. |
position | Vec3 | undefined | The middle of its base. |
rotation | Quat | undefined | How it is turned. |
moved | boolean | true | Whether this counts as having moved from where it was made. |
Returns
void
Nothing.
Example
ts
import { moveThing } from 'gameable';
moveThing(thing, { x: 1, y: 0, z: -2 }, { x: 0, y: 0, z: 0, w: 1 });
console.log(thing.min, thing.max); // the box where it is nowmoveTo()
ts
function moveTo(
ctx,
ai,
target,
opts?
): void;Begin a navigation move (straight-line when no bounds exist), aborting an existing request first.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
ai | ActorHandle |
target | Vec3 | ActorHandle<object> |
opts? | { acceptanceRadius?: number; } |
opts.acceptanceRadius? | number |
Returns
void
Example
ts
moveTo(ctx, ai, { x: 5, y: 0, z: 2 });navigationOf()
ts
function navigationOf(): NavGrid | null;The shared grid covers the axis-aligned union of bounds volumes; the first supplies tuning. Returns null until the first bounds volume steps. Rotations do not rotate the grid.
Returns
NavGrid | null
Example
ts
const grid = navigationOf();navigationReady()
ts
function navigationReady(): boolean;Whether flat ground or a successful physics bake is available.
Returns
boolean
Example
ts
if (navigationReady()) moveTo(ctx, ai, goal);onTrigger()
ts
function onTrigger(
ctx,
name,
handlers
): () => void;Subscribe during init or a system to an instance name. Returns an unsubscribe function. Registration belongs to the current guest; callbacks are code and are not snapshotted.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current context. |
name | string | Trigger instance name. |
handlers | TriggerHandlers | Entry and exit callbacks. |
Returns
Unsubscribe function.
() => void
Example
ts
onTrigger(ctx, 'gate', { enter: (other, c) => c.hud.set({ gate: true }) });openDoor()
ts
function openDoor(ctx, door): void;Request opening; a locked door must be unlocked first.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current guest context. |
door | ActorHandle<DoorCoreProps> | Kit door instance. |
Returns
void
Example
ts
openDoor(ctx, door);orderMove()
ts
function orderMove(
ctx,
pawns,
target,
opts?
): void;Order selected pawns to a world-aligned grid around target (default spacing 1.5m). Targets are copied into each pawn's request; the supplied selection is not retained.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current game context. |
pawns | readonly number[] | Selected character actor root entities. |
target | Vec3 | World-space formation centre. |
opts? | { acceptanceRadius?: number; spacing?: number; } | Formation and arrival options. |
opts.acceptanceRadius? | number | Arrival distance in metres (default 0.1). |
opts.spacing? | number | Distance between slots in metres (default 1.5). |
Returns
void
Example
ts
orderMove(ctx, selected.entities, goal, { spacing: 2 });particleEffect()
ts
function particleEffect(preset, opts?): ActorComponent;Attach a persistent built-in preset to this component's entity on its first step. The game must declare features: { vfx: true }.
Parameters
| Parameter | Type | Description |
|---|---|---|
preset | VfxPreset | Built-in particle preset. |
opts | ParticleEffectOptions | Emitter and attachment overrides. |
Returns
Scene component owning the emitter handle.
Example
ts
const flame = particleEffect('fire', { offset: [0, 1, 0] });pathLength()
ts
function pathLength(path, count): number;Total three-dimensional distance of count packed XYZ points.
Parameters
| Parameter | Type | Description |
|---|---|---|
path | Float32Array | Packed XYZ path buffer. |
count | number | Number of points to measure. |
Returns
number
Total segment length in metres.
Example
ts
const length = pathLength(new Float32Array([0, 0, 0, 3, 0, 4]), 2);pawnOf()
ts
function pawnOf(controller): number;Parameters
| Parameter | Type | Description |
|---|---|---|
controller | ActorHandle | A controller actor. |
Returns
number
The entity it possesses, or 0.
Example
ts
const pawn = pawnOf(controller);pawnVelocity()
ts
function pawnVelocity(actor): Readonly<Vec3>;Read the component's saved velocity, or zero before initialization.
Parameters
| Parameter | Type |
|---|---|
actor | ActorHandle |
Returns
Readonly<Vec3>
Example
ts
const velocity = pawnVelocity(pawn);peekSnapshotHeader()
ts
function peekSnapshotHeader(state): SnapshotPeek;Read only the JSON header of a snapshot, without restoring anything: the page's editor lists the guest's actors this way (user.actors.rows), since actor names, classes and props live in the guest.
Parameters
| Parameter | Type | Description |
|---|---|---|
state | ArrayLike<number> | The bytes snapshot returned. |
Returns
The header's frame, elapsed time, player and folded game state.
Throws
A GameError-shaped record when the magic or version does not match.
Example
ts
const { user } = peekSnapshotHeader(sandbox.snapshot());physicsJoint()
ts
function physicsJoint(opts): ActorComponent;Join named actor roots, or this actor's root to the world when names are empty. Creation is attempted once on the first authority step. Snapshots retain the joint ID and attempted flag, just as ECS retains body IDs: guest restore rebinds body handles and restores joint-kind bookkeeping, without emitting body/joint creation commands. Restore the matching host physics world separately; this component never duplicates it.
Parameters
| Parameter | Type | Description |
|---|---|---|
opts | PhysicsJointOptions | Joint and local transform settings. |
Returns
Example
ts
const hinge = physicsJoint({ kind: 'hinge', actorA: 'door', min: -90, max: 90 });physicsVolumeAt()
ts
function physicsVolumeAt(_ctx, entity): ActorHandle<object & object> | null;Find the highest-priority volume containing an entity's root point.
Parameters
| Parameter | Type | Description |
|---|---|---|
_ctx | GameContext | Current context. |
entity | number | Entity to test; need not be an overlap watcher. |
Returns
ActorHandle<object & object> | null
Volume handle or null. Results use current transforms, not last frame's events.
Example
ts
const water = physicsVolumeAt(ctx, ctx.player)?.props.water ?? false;playAmbientSound()
ts
function playAmbientSound(ctx, actor): number;Play once, retaining the legacy helper's idempotence.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current context. |
actor | ActorHandle<AmbientProps> | Ambient actor. |
Returns
number
The live sound id, or zero.
Example
ts
playAmbientSound(ctx, ambient);playerControllerOf()
ts
function playerControllerOf(seat): ActorHandle<object> | null;The logged-in seat's controller.
Parameters
| Parameter | Type |
|---|---|
seat | number |
Returns
ActorHandle<object> | null
Example
ts
const controller = playerControllerOf(0);playerStateOf()
ts
function playerStateOf(seat):
| ActorHandle<PlayerStateProps>
| null;The logged-in seat's statistics.
Parameters
| Parameter | Type |
|---|---|
seat | number |
Returns
| ActorHandle<PlayerStateProps> | null
Example
ts
const score = playerStateOf(0)?.props.score;playSound()
ts
function playSound(
ctx,
actor,
component?
): void;Restart a sound, selecting the first audio component by default.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current context. |
actor | ActorHandle | Owning actor. |
component? | string | Audio component name. |
Returns
void
Example
ts
playSound(ctx, actor);pointAlongPath()
ts
function pointAlongPath(
path,
count,
d,
out
): Vec3;Write the point at clamped distance d; an empty path writes the origin.
Parameters
| Parameter | Type | Description |
|---|---|---|
path | Float32Array | Packed XYZ path buffer. |
count | number | Number of path points. |
d | number | Distance in metres from the first point. |
out | Vec3 | Caller-owned result vector. |
Returns
The supplied result vector.
Example
ts
pointAlongPath(path, count, 2, marker);possess()
ts
function possess(
ctx,
controller,
pawn
): void;Make a controller drive a pawn. Any pawn it drove, and any controller that drove this pawn, let go first. A player's controller moves that player's control to the pawn.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | The game context. |
controller | ActorHandle | The controller actor. |
pawn | number | ActorHandle<object> | The pawn: an entity (a definition.player body works) or an actor. |
Returns
void
Example
ts
possess(ctx, controller, spawnActor(ctx, FlyingPawn, { position }));prefab()
ts
function prefab(spec): PrefabDef & PlaceholderSpec;Declare a prefab.
Safe at module scope: nothing is resolved until the first spawn.
Parameters
| Parameter | Type | Description |
|---|---|---|
spec | PrefabSpec & PlaceholderSpec | What the entity is made of. |
Returns
The prefab, ready to spawn.
Example
ts
import { prefab } from 'gameable';
export const Crate = prefab({
asset: 'crate',
body: { shape: 'box', dims: [0.5, 0.5, 0.5], kind: 'dynamic', mass: 20 },
});previewPath()
ts
function previewPath(
_ctx,
from,
to,
out,
result,
opts?
): PathPreview;Query navigation into caller-owned storage, or a straight segment without bounds. Unready navigation, unreachable goals and truncated paths report reachable=false. Budgets are metres (negative budgets clamp to zero); no query allocations.
Parameters
| Parameter | Type | Description |
|---|---|---|
_ctx | GameContext | Current game context. |
from | Vec3 | World-space starting point. |
to | Vec3 | World-space destination. |
out | Float32Array | Caller-owned packed XYZ path storage. |
result | PathPreview | Caller-owned preview result. |
opts? | { budget?: number; } | Preview options. |
opts.budget? | number | Movement budget in metres (default Infinity). |
Returns
The supplied preview result.
Example
ts
previewPath(ctx, start, goal, path, result, { budget: 5 });projectileMovement()
ts
function projectileMovement(source, onHit?): ActorComponent;Sweep a ray along each fixed-step displacement; ignores its own body and the owner entity (or itself when unowned). Ray results allocate in the host API.
Parameters
| Parameter | Type | Description |
|---|---|---|
source | | ProjectileOptions | ((actor) => ProjectileOptions) | Static options or an allocation-free per-actor selector. |
onHit? | (self, hit, ctx, stopped) => void | Optional reusable hit callback. |
Returns
The projectile integration component.
Example
ts
const flight = projectileMovement({ speed: 30, gravityScale: 0, bounces: 0 });projectToScreen()
ts
function projectToScreen(
camera,
viewport,
point,
out
): boolean;Project a world point without allocation. Depth is distance along the view axis. Returns false for an unusable camera/point or a perspective point on the eye plane; visible is false on failure, behind the camera, or outside the viewport. Uses the same arm approximation and orthographic size as rayFromCamera.
Parameters
| Parameter | Type |
|---|---|
camera | CameraState |
viewport | Viewport |
point | Vec3 |
out | ScreenPoint |
Returns
boolean
Example
ts
projectToScreen(camera.state, view, worldPoint, screenPoint);quatFromYawPitch()
ts
function quatFromYawPitch(
out,
yaw,
pitch
): void;Write a yaw/pitch pair into a quaternion, in the engine's Y-up convention.
Parameters
| Parameter | Type | Description |
|---|---|---|
out | Quat | Quaternion to overwrite. |
yaw | number | Yaw in radians, around +Y. |
pitch | number | Pitch in radians, around the camera's local +X. |
Returns
void
Nothing; out is mutated.
radialForce()
ts
function radialForce(opts?): ActorComponent;Add outward impulses and optional continuous force to an actor.
Parameters
| Parameter | Type |
|---|---|
opts | RadialForceOptions |
Returns
Example
ts
const force = radialForce({ radius: 5, forceStrength: 10 });rayFromCamera()
ts
function rayFromCamera(
camera,
viewport,
x,
y,
out
): boolean;Ray through a top-left-origin screen point (y down), without allocation. Third-person follow uses the unshortened arm; host collision can move the real eye. Orthographic half height is armLength, independent of fovYDeg: the host currently defines no orthographic frustum. Invalid cameras/coordinates leave out unchanged.
Parameters
| Parameter | Type |
|---|---|
camera | CameraState |
viewport | Viewport |
x | number |
y | number |
out | ScreenRay |
Returns
boolean
Example
ts
rayFromCamera(camera.state, { width: 800, height: 600 }, 400, 300, ray);rayToGround()
ts
function rayToGround(
ray,
planeY,
out
): boolean;Intersect a forward ray with y = planeY. Parallel rays and intersections behind the origin return false and leave out unchanged.
Parameters
| Parameter | Type |
|---|---|
ray | ScreenRay |
planeY | number |
out | Vec3 |
Returns
boolean
Example
ts
if (rayToGround(ray, 0, destination)) console.log(destination);readKeyBit()
ts
function readKeyBit(words, index): boolean;Read one bit out of an 8-word key bitset.
Parameters
| Parameter | Type | Description |
|---|---|---|
words | ArrayLike<number> | The bitset, exactly KEY_WORDS long. |
index | number | A bit index from keyIndex. |
Returns
boolean
True when the bit is set.
readSnapshot()
ts
function readSnapshot(rt, state): unknown;Restore a state previously produced by writeSnapshot from the same build.
Parameters
| Parameter | Type | Description |
|---|---|---|
rt | RuntimeState | The runtime to overwrite. |
state | ArrayLike<number> | The bytes. |
Returns
unknown
The user state from defineGame({ snapshot }), if any.
Throws
A GameError-shaped object when the magic or version does not match.
readWorldList()
ts
function readWorldList(text): WorldList;Read the list a world-event of kind loaded carries.
The world facade does this for a game; the function is here for a host, a test, or a tool that holds the same text.
Parameters
| Parameter | Type | Description |
|---|---|---|
text | string | The event's text: the list as JSON. |
Returns
The list.
Throws
When the text is not a world list, or is of a newer format.
Example
ts
import { readWorldList } from 'gameable';
const list = readWorldList(event.val.text);
console.log(list.name, list.things.length);registerActorPart()
ts
function registerActorPart(name, part): void;Register a guest-local part for automatic actor snapshot composition. Register during init.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Unique guest-local part key. |
part | GameplayPart | Snapshot lifecycle implementation. |
Returns
void
Example
ts
registerActorPart('inventory', bags);removeEffect()
ts
function removeEffect(actor, id): void;Remove every stack with this id and emit one expiry per stack.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor handle. |
id | string | Registered effect or ability id. |
Returns
void
Example
ts
removeEffect(hero, 'armor');removeItem()
ts
function removeItem(
actor,
item,
amount?
): boolean;Remove atomically from highest bag slots; equipment is excluded.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
actor | ActorHandle | undefined | Owning actor. |
item | string | undefined | Catalog id. |
amount | number | 1 | Nonnegative safe integer; defaults to one. |
Returns
boolean
Whether the entire amount was removed.
Example
ts
const removed = removeItem(actor, 'coin', 2);removeTag()
ts
function removeTag(actor, tag): void;Remove only the exact manual tag; effects and abilities retain their own grants.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor handle. |
tag | string | Exact manual tag or hierarchical query. |
Returns
void
Example
ts
removeTag(hero, 'state.ready');reportNoise()
ts
function reportNoise(
ctx,
location,
loudness,
instigator?
): void;Report an authority noise event. Listeners consume it on their next sensing update; records more than one fixed frame old expire. The location is copied. Inbox slots are reused after their high-water mark.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
ctx | GameContext | undefined | Fixed-step context. |
location | Vec3 | undefined | World position in metres. |
loudness | number | undefined | Nonnegative distance multiplier. |
instigator | number | 0 | Source pawn entity, or zero when unspecified. |
Returns
void
Example
ts
reportNoise(ctx, self.position, 1, self.entity);requestGridMove()
ts
function requestGridMove(
entity,
dir,
run?
): void;Request this tick's direction; repeat while held, from an actor tick or system.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
entity | number | undefined | Walker entity. |
dir | GridDirection | undefined | Compass direction. |
run | boolean | false | Use the run multiplier. |
Returns
void
Example
ts
requestGridMove(hero.entity, 'east', true);resetAbilitiesRegistry()
ts
function resetAbilitiesRegistry(): void;Clear module declarations and runtime definition caches for isolated tests. Existing active slots keep their serialized definitions until expiry.
Returns
void
Example
ts
resetAbilitiesRegistry();resetActorRegistry()
ts
function resetActorRegistry(): void;Clear actor declarations for isolated tests.
Returns
void
Example
ts
resetActorRegistry();resetDataTableRegistry()
ts
function resetDataTableRegistry(): void;Clear content declarations between isolated runtimes/tests, matching resetActorRegistry. Existing table references stay immutable but are no longer registered.
Returns
void
Example
ts
resetDataTableRegistry();resetPrefabRegistry()
ts
function resetPrefabRegistry(): void;Reset prefab numbering. Tests only — a game never calls this.
Returns
void
Nothing.
resetVehicle()
ts
function resetVehicle(
ctx,
pawn,
position,
yaw
): void;Teleport, clear handling/motion/input and snap the chase arm. Yaw is radians.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Context. |
pawn | ActorHandle | Vehicle pawn. |
position | Vec3 | World position. |
yaw | number | Heading. |
Returns
void
Example
ts
resetVehicle(ctx, pawn, { x: 0, y: 1, z: 0 }, 0);resolveRow()
ts
function resolveRow<Row>(handle): FrozenData<Row> | undefined;Resolve a reference without allocating; missing tables or rows return undefined.
Type Parameters
| Type Parameter | Default type |
|---|---|
Row extends object | Record<string, unknown> |
Parameters
| Parameter | Type | Description |
|---|---|---|
handle | DataRowHandle | A table/row reference, possibly restored from JSON. |
Returns
FrozenData<Row> | undefined
The frozen row, or undefined.
Example
ts
const potion = resolveRow<{ cost: number }>(rowHandle('Items', 'potion'));respawnPlayer()
ts
function respawnPlayer(
ctx,
entity,
options?
): void;Teleport a player to its checkpoint or chosen PlayerStart, clear velocity and reset facing. An explicit tag selects a PlayerStart instead of the checkpoint. No starts probes the ground under the origin.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
ctx | GameContext | undefined | Current context. |
entity | number | undefined | Player entity. |
options | { tag?: string; } | EMPTY_OPTIONS | Optional preferred marker tag. |
options.tag? | string | undefined | Preferred PlayerStart tag, overriding a checkpoint. |
Returns
void
Example
ts
respawnPlayer(ctx, ctx.player, { tag: 'red' });responseBetween()
ts
function responseBetween(a, b): CollisionResponse;Resolve the symmetric minimum response. Disabled components always ignore.
Parameters
| Parameter | Type | Description |
|---|---|---|
a | CollisionSetup | First component. |
b | CollisionSetup | Second component. |
Returns
The weaker response.
Example
ts
responseBetween(collisionProfile('Pawn'), collisionProfile('Trigger')); // overlaprestartPlayer()
ts
function restartPlayer(ctx, seat): void;Respawn the existing body at a PlayerStart and restore full health.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
seat | number |
Returns
void
Example
ts
restartPlayer(ctx, 0);roomSeats()
ts
function roomSeats(definition): number | undefined;The seats a game declares: features.multiplayer.maxPlayers. Seats are ids 0..seats - 1. The guest makes exactly that many player slots and ignores (with one warning) a join or input past them; a room built by createEngineRoomGame refuses the next joiner with full. Both read this function, so the two cannot disagree.
Parameters
| Parameter | Type | Description |
|---|---|---|
definition | GameDefinition | The defineGame result. |
Returns
number | undefined
The seat count, DEFAULT_ROOM_SEATS for multiplayer: true, or undefined when the game does not declare features.multiplayer.
Throws
When maxPlayers is not a whole number from 1 to 4097.
Example
ts
import { defineGame, roomSeats } from 'gameable';
const game = defineGame({ features: { multiplayer: { maxPlayers: 6 } } });
roomSeats(game); // 6: seats 0 to 5roomSendHz()
ts
function roomSendHz(definition): number;The rows rate a game declares, checked: features.multiplayer.sendHz, from 1 to 60 per second (60 is the simulation rate, so more would repeat rows).
Parameters
| Parameter | Type | Description |
|---|---|---|
definition | GameDefinition | The defineGame result. |
Returns
number
The declared rate, or 20 when none is declared.
Throws
When sendHz is declared but is not a number from 1 to 60.
Example
ts
import { defineGame, roomSendHz } from 'gameable';
roomSendHz(defineGame({ features: { multiplayer: { sendHz: 10 } } })); // 10
roomSendHz(defineGame({ features: { multiplayer: true } })); // 20rotatingMovement()
ts
function rotatingMovement(source): ActorComponent;Rotate the root about its local axes each authority step. Rates are degrees/second.
Parameters
| Parameter | Type | Description |
|---|---|---|
source | | { degreesPerSecond: readonly [number, number, number]; } | ((actor) => object) | Static degrees-per-second rates or an allocation-free per-actor selector. |
Returns
The reusable rotation component.
Example
ts
const spin = rotatingMovement({ degreesPerSecond: [0, 90, 0] });rowHandle()
ts
function rowHandle(table, key): DataRowHandle;Make a JSON-safe reference. Resolution is deferred so declarations may be ordered freely.
Parameters
| Parameter | Type | Description |
|---|---|---|
table | string | Target table name. |
key | string | Target row key. |
Returns
A frozen reference.
Example
ts
const potion = rowHandle('Items', 'potion');runBehaviorTree()
ts
function runBehaviorTree(
ctx,
ai,
tree
): void;Tick a tree for the possessed pawn after controller movement on authority steps. Trees are runtime resources; calling again replaces and resets the previous tree. Restoring stops the tree because BehaviorTree has no snapshot API. The game must run it again after restore, for example from the AI's restoreState hook or game code.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
ai | ActorHandle |
tree | BehaviorTree<GameContext> |
Returns
void
Example
ts
runBehaviorTree(ctx, ai, createBehaviorTree(bt.wait(1)));sameTeam()
ts
function sameTeam(a, b): boolean;Compare assigned teams; unassigned players are never teammates.
Parameters
| Parameter | Type | Description |
|---|---|---|
a | number | First player seat. |
b | number | Second player seat. |
Returns
boolean
Whether both players share an assigned team.
Example
ts
const friendly = sameTeam(0, 1);scene()
ts
function scene(opts?): ActorComponent;A transform without rendering or collision.
Parameters
| Parameter | Type | Description |
|---|---|---|
opts | ComponentOptions | Local transform or spawn options. |
Returns
The component declaration.
Example
ts
import { scene } from 'gameable';
const root = scene();screenRay()
ts
function screenRay(
ctx,
x,
y,
out
): boolean;Ray through a screen point using this frame's camera and guest viewport.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
x | number |
y | number |
out | ScreenRay |
Returns
boolean
Example
ts
screenRay(ctx, ctx.input.mouse.x, ctx.input.mouse.y, ray);seatOf()
ts
function seatOf(controller): number;Parameters
| Parameter | Type | Description |
|---|---|---|
controller | ActorHandle | A controller actor. |
Returns
number
Its player's seat, or NO_SEAT for an AI controller.
Example
ts
const seat = seatOf(controller);secondsToSteps()
ts
function secondsToSteps(seconds, dt): number;How many fixed steps last seconds: rounded to the nearest step, at least one.
Parameters
| Parameter | Type | Description |
|---|---|---|
seconds | number | The duration in simulated seconds. Zero or less is one step. |
dt | number | The fixed timestep, ctx.dt. |
Returns
number
A whole number of steps, at least 1.
Example
ts
import { secondsToSteps } from 'gameable';
console.log(secondsToSteps(0.5, 1 / 60)); // 30sectionDistance()
ts
function sectionDistance(point, line): number;Clamped arc progress on a section's polyline, never another section of the track.
Parameters
| Parameter | Type | Description |
|---|---|---|
point | CircuitPoint | Current position. |
line | readonly CircuitPoint[] | Ordered section vertices, including both gate centres. |
Returns
number
Arc distance at the closest section point; equal distances prefer earlier arc.
Example
ts
console.log(sectionDistance([0,0,3], [[0,0,0],[0,0,10]]));senses()
ts
function senses(opts?): ActorComponent;Sense player pawns, optionally all possessed pawns, from component-local +Z. Callbacks live on the component so replacing actor hooks preserves sensing. Timers and noise inboxes are JSON-safe actor state. No external handles are owned.
Parameters
| Parameter | Type | Description |
|---|---|---|
opts | SensesOptions | Transform, metre/degree/second tuning and callbacks. |
Returns
Example
ts
const eyes = senses({ onSeePawn(self, pawn, ctx) { self.state.target = pawn; } });setAttributeBase()
ts
function setAttributeBase(
actor,
name,
value
): void;Set the clamped permanent base; notifications settle at the next component step.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor handle. |
name | string | Declared attribute name. |
value | number | Proposed numeric value. |
Returns
void
Example
ts
setAttributeBase(hero, 'health', 50);setConstraintMotor()
ts
function setConstraintMotor(
ctx,
actor,
motor,
component?
): void;Set a live joint's motor using facade units (degrees or metres).
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Game context. |
actor | ActorHandle | Owning actor. |
motor | { maxForce?: number; mode: MotorMode; target: number; } | Motor mode, target and optional force cap. |
motor.maxForce? | number | - |
motor.mode? | MotorMode | - |
motor.target? | number | - |
component? | string | Component name; defaults to the first constraint. |
Returns
void
Example
ts
setConstraintMotor(ctx, door, { mode: 'position', target: 90 });setDesiredRotation()
ts
function setDesiredRotation(entity, yaw): void;Hold a world yaw independently of velocity when orientRotationToMovement is false. The hold persists until cleared with undefined; rotationRate limits the capsule turn.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Actor root entity. |
yaw | number | undefined | Held yaw in radians about +Y, or undefined to release it. |
Returns
void
Example
ts
setDesiredRotation(player, Math.PI / 2);setFocus()
ts
function setFocus(
_ctx,
ai,
target
): void;Turn toward a point or living actor; null clears the focus.
Parameters
| Parameter | Type |
|---|---|
_ctx | GameContext |
ai | ActorHandle |
target | Vec3 | ActorHandle<object> | null |
Returns
void
Example
ts
setFocus(ctx, ai, target);setMovementWish()
ts
function setMovementWish(
actor,
x,
y,
z
): void;Set an AI's world-space movement wish; magnitudes above one are clamped.
Parameters
| Parameter | Type |
|---|---|
actor | ActorHandle |
x | number |
y | number |
z | number |
Returns
void
Example
ts
setMovementWish(pawn, 1, 0, 0);setRespawnPoint()
ts
function setRespawnPoint(
entity,
position,
yaw
): void;Remember a checkpoint for this entity, honoured before PlayerStarts. Yaw is radians. Call inside init or a system. Checkpoints are saved with defineGame snapshots.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Player entity. |
position | Vec3 | World position (copied). |
yaw | number | Facing in radians, zero faces +Z. |
Returns
void
Example
ts
setRespawnPoint(ctx.player, { x: 2, y: 0, z: 3 }, Math.PI);setSeat()
ts
function setSeat(controller, seat): void;Give a controller a player's seat; a PlayerController gets one at login.
Parameters
| Parameter | Type | Description |
|---|---|---|
controller | ActorHandle | A controller actor. |
seat | number | The player's seat (0 in a single-player game). |
Returns
void
Example
ts
setSeat(controller, player.id);setSignal()
ts
function setSignal(self, on): void;Set a signal; allocate its record only during actor construction.
Parameters
| Parameter | Type | Description |
|---|---|---|
self | ActorHandle | Signal source actor. |
on | boolean | Whether the signal reports on. |
Returns
void
Example
ts
setSignal(self, true);setTeam()
ts
function setTeam(
ctx,
seat,
team
): boolean;Set a team by id (one based) or configured name, respecting capacity.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current authority context. |
seat | number | Logged-in player seat. |
team | string | number | Configured team name or one-based id; zero clears membership. |
Returns
boolean
Whether the requested membership is valid and fits.
Example
ts
setTeam(ctx, 0, 'blue');setText()
ts
function setText(
actor,
text,
component?
): void;Change a text widget, preserving its style, stable id and world anchor.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor. |
text | string | number | New text or number. |
component? | string | Component name; defaults to the first text widget. |
Returns
void
Example
ts
setText(actor, 100, 'label');setVehicleGrip()
ts
function setVehicleGrip(
ctx,
pawn,
sourceId,
scale,
until
): void;Set/refresh one grip source until absolute simulated seconds (ctx.elapsed). Scales are clamped to [0,1]; concurrent sources combine by minimum. Expired sources are reusable. Each chassis preallocates world.maxEntities source slots at creation. Authority/solo only; reset and respawn clear every source.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Frame context. |
pawn | ActorHandle | Vehicle pawn. |
sourceId | string | number | Stable identifier unique to the effect source. |
scale | number | Grip multiplier. |
until | number | Absolute expiry in simulated seconds. |
Returns
void
Example
ts
setVehicleGrip(ctx, car, 'rocket', 0.3, ctx.elapsed + 0.6);setVehicleInput()
ts
function setVehicleInput(pawn, input): void;Submit finite intent, consumed once on the next component step.
Parameters
| Parameter | Type | Description |
|---|---|---|
pawn | ActorHandle | Vehicle pawn. |
input | Readonly<VehicleInput> | Normalized controls. |
Returns
void
Example
ts
setVehicleInput(pawn, { throttle: 1, steer: 0, brake: 0, handbrake: 0 });setViewTarget()
ts
function setViewTarget(
ctx,
seat,
target
): void;Select a seated controller's view target; null restores its pawn's camera.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current context. |
seat | number | Player seat. |
target | ActorHandle<object> | null | Actor to view through, or null. |
Returns
void
Example
ts
setViewTarget(ctx, 0, securityCamera);setWidget()
ts
function setWidget(
actor,
node,
component?
): void;Replace a widget's contents, retaining its component anchor and default identity.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor. |
node | UiNode | New contents. |
component? | string | Component name; defaults to the first widget. |
Returns
void
Example
ts
setWidget(actor, { type: 'text', text: 'Ready' }, 'label');setWidgetVisible()
ts
function setWidgetVisible(
actor,
visible,
component?
): void;Include or omit a widget when the game next composes its UI model.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor. |
visible | boolean | Whether to include the node. |
component? | string | Component name; defaults to the first widget. |
Returns
void
Example
ts
setWidgetVisible(actor, false, 'label');setYaw()
ts
function setYaw(entity, yaw): void;Turn an entity to a yaw: its whole rotation becomes that turn about +Y (upright), and it is marked moved.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | The entity. |
yaw | number | Radians about +Y; 0 faces +Z. |
Returns
void
Example
ts
import { setYaw } from 'gameable';
declare const guard: number;
setYaw(guard, Math.PI); // facing -ZshapeForQuery()
ts
function shapeForQuery<T>(setup): T;Select query geometry without creating a duplicate simulation collider.
Type Parameters
| Type Parameter |
|---|
T |
Parameters
| Parameter | Type | Description |
|---|---|---|
setup | CollisionShapeSetup<T> | Shapes, trace flag and query complexity. |
Returns
T
The selected simple aggregate or triangle geometry.
Example
ts
shapeForQuery({ simple: 'box', complex: 'mesh', collisionTraceFlag: 'simpleAsComplex' });shapeForSimulation()
ts
function shapeForSimulation<T>(setup): T;Select simulation geometry. ComplexAsSimple requires fixed/kinematic triangle surfaces; this helper does not enable dynamic concave simulation.
Type Parameters
| Type Parameter |
|---|
T |
Parameters
| Parameter | Type | Description |
|---|---|---|
setup | CollisionShapeSetup<T> | Separate simple and complex geometries with routing policy. |
Returns
T
The geometry intended for simulation.
Example
ts
shapeForSimulation({ simple: 'box', complex: 'mesh', collisionTraceFlag: 'simpleAndComplex' });sideScrollCamera()
ts
function sideScrollCamera(options): object;Create a fixed side view with soft directional lead and a vertical dead zone. Call reset at init or respawn. All update scratch is owned by the rig.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | SideScrollCameraOptions | Camera centre bounds and response. |
Returns
object
Reusable camera controller.
reset()
ts
reset(point): void;Parameters
| Parameter | Type |
|---|---|
point | Vec3 |
Returns
void
update()
ts
update(
ctx,
point,
velocity
): void;Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
point | Vec3 |
velocity | Readonly<Vec3> |
Returns
void
Example
ts
const rig = sideScrollCamera({ minX: 0, maxX: 40 });
rig.reset({ x: 0, y: 1, z: 0 });
// In a system: rig.update(ctx, hero.position, movementOf(hero.entity)!.velocity);simpleMoveTo()
ts
function simpleMoveTo(
_ctx,
pawn,
target,
opts?
): void;Replace a pawn's walking order, independently of possession. Requires characterMovement. Request storage allocates on the first order; tick processing reuses it. State is saved with the actor and query buffers are rebuilt on restore.
Parameters
| Parameter | Type | Description |
|---|---|---|
_ctx | GameContext | Current game context. |
pawn | number | Character actor root entity. |
target | Vec3 | World-space destination, copied into the request. |
opts? | { acceptanceRadius?: number; speedScale?: number; } | Walking options. |
opts.acceptanceRadius? | number | Arrival distance in metres (default 0.1). |
opts.speedScale? | number | Multiplier of the character's base walking speed (default 1). |
Returns
void
Example
ts
simpleMoveTo(ctx, player, { x: 8, y: 0, z: 4 });spawn()
ts
function spawn(
def,
position,
rotation?
): number;Instantiate a prefab.
Mints the entity id, writes the built-in components and queues the spawn / add-body / spawn-character commands the host needs.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
def | PrefabDef | undefined | A prefab from prefab(). |
position | Vec3 | undefined | World position. |
rotation | Quat | IDENTITY | World rotation, xyzw. Defaults to identity. |
Returns
number
The new entity id, or zero when the spawn budget is exhausted.
Example
ts
import { spawn } from 'gameable';
const crate = spawn(Crate, { x: 0, y: 2, z: -5 });spawnActor()
ts
function spawnActor<P>(
ctx,
cls,
opts
): ActorHandle<P>;Spawn every component, apply overrides, then run construct on authority/solo. beginPlay waits for the next actor step, including spawns inside a hook.
Type Parameters
| Type Parameter |
|---|
P extends object |
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current game context. |
cls | ActorClass<P> | Registered actor class. |
opts | ActorSpawnOptions<P> | Local transform or spawn options. |
Returns
ActorHandle<P>
The new actor handle, or an inert handle when a spawn budget limit is reached.
Throws
The original construction or validation error after rolling back the actor.
Example
ts
const crate = spawnActor(ctx, Crate, { position: { x: 0, y: 2, z: 0 }, yaw: 90 });spawnEmitterAtLocation()
ts
function spawnEmitterAtLocation(
ctx,
preset,
at,
opts?
): void;SpawnEmitterAtLocation: emit a one-shot preset without acquiring a handle.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current context. |
preset | VfxPreset | Built-in preset. |
at | Vec3 | World position in metres. |
opts? | { intensity?: number; scale?: number; tint?: readonly [number, number, number]; } | Particle overrides. |
opts.intensity? | number | Particle count and brightness multiplier. |
opts.scale? | number | Particle size multiplier. |
opts.tint? | readonly [number, number, number] | Linear RGB particle color. |
Returns
void
Example
ts
spawnEmitterAtLocation(ctx, 'explosion', self.position);spawnerWaves()
ts
function spawnerWaves(self): Waves;Borrow a spawner's waves controller, for manual start/stop and progress queries.
Parameters
| Parameter | Type | Description |
|---|---|---|
self | ActorHandle | Actor instance. |
Returns
The waves controller for this instance.
Example
ts
spawnerWaves(spawner).start(ctx);spawnTileColliders()
ts
function spawnTileColliders(
ctx,
cells,
options?
): number[];Spawn merged tile boxes as fixed bodies. The current SDK has no aggregate-body spawn command: each merged rectangle is one body, rather than Paper2D's compound. Call during initialization, never each tick.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | Pick<GameContext, "spawn"> | Game context providing spawn. |
cells | readonly CollisionCell[] | Solid cells to merge. |
options | TileColliderOptions | Horizontal spacing and collision policy (default BlockAll). |
Returns
number[]
Spawned entity ids.
Example
ts
const entities = spawnTileColliders(ctx, [{ x: 0, z: 0, height: 1 }]);sphere()
ts
function sphere(dims, opts?): ActorComponent;A sphere specified by radius.
Parameters
| Parameter | Type | Description |
|---|---|---|
dims | readonly [number] | Shape dimensions in metres. |
opts | ShapeOptions | Local transform or spawn options. |
Returns
The component declaration.
Example
ts
import { sphere } from 'gameable';
const root = sphere([1], { collision: 'overlap' });spline()
ts
function spline(points, opts?): ActorComponent;Author a local linear or uniformly sampled Catmull-Rom path.
Parameters
| Parameter | Type |
|---|---|
points | readonly readonly [number, number, number][] |
opts | ComponentOptions & object |
Returns
Example
ts
const path = spline([[0, 0, 0], [0, 0, 5]]);splineOf()
ts
function splineOf(actor, component): SplinePath;Get a component's world-space spline queries; rejects other component types.
Parameters
| Parameter | Type |
|---|---|
actor | ActorHandle |
component | string |
Returns
Example
ts
splineOf(actor, 'path').pointAt(2, position);spotOf()
ts
function spotOf(
thing,
name,
out
): WorldSpotNow | null;Where one of a thing's rider spots is now, in the world: the seat, a grip, a foot rest.
A spot is on a part and moves with it, so a grip turns with the handlebars: the spot goes through each joint between its part and the thing's root at the value the joint stands at (thing.joints[i].value), then to where the thing is and how it is turned. Allocates nothing when out is reused.
Parameters
| Parameter | Type | Description |
|---|---|---|
thing | WorldThing | The thing. |
name | string | The spot's name: seat, gripLeft, gripRight, footLeft, footRight. |
out | WorldSpotNow | The record to fill. |
Returns
WorldSpotNow | null
out, or null when the thing has no such spot.
Example
ts
import { spotOf, type WorldSpotNow } from 'gameable';
const seat: WorldSpotNow = {
position: { x: 0, y: 0, z: 0 },
forward: { x: 0, y: 0, z: 1 },
up: { x: 0, y: 1, z: 0 },
};
if (spotOf(bike, 'seat', seat)) console.log(seat.position); // where the seat is nowstamina()
ts
function stamina(options?): ActorComponent;Drain while requested; recover slowly after a delay. Exhaustion locks sprint until full. Requests are sampled on the next component step. State survives actor snapshots.
Parameters
| Parameter | Type |
|---|---|
options | StaminaOptions |
Returns
Example
ts
const components = { root: scene(), stamina: stamina({ maximum: 5 }) };staminaOf()
ts
function staminaOf(actor, name?): StaminaState;Read a stamina component without allocating.
Parameters
| Parameter | Type | Default value |
|---|---|---|
actor | ActorHandle | undefined |
name | string | 'stamina' |
Returns
Example
ts
const energy = staminaOf(hero);standFor()
ts
function standFor(
thing,
from?,
out?
): WorldStand;Where to stand to use a thing, and which way to face.
The package's own spot while the thing is where it was made. For a thing that has moved, or one the package gave no spot, a spot beside it, facing it: on the side of from when given (the nearest side to whoever asks), else on the side the package's spot was, else on its +z side.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
thing | WorldThing | undefined | The thing. |
from | Vec3 | null | null | Where the asker is, or null. |
out | WorldStand | ... | The record to fill. |
Returns
out.
Example
ts
import { findThing, standFor } from 'gameable';
const trunk = findThing(things, 'the trunk');
if (trunk) {
const spot = standFor(trunk, null);
console.log(spot.x, spot.z, spot.facing); // walk here, turn to this
}startMatch()
ts
function startMatch(ctx): void;Start a waiting match.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
Returns
void
Example
ts
startMatch(ctx);stepCharacterMovement()
ts
function stepCharacterMovement(
cm,
q,
capsule,
position,
input,
dt
): void;Advance a capsule centre with bounded simulation substeps. Input is normalized world acceleration.
Parameters
| Parameter | Type | Description |
|---|---|---|
cm | CharacterMovement | Mover state and preallocated scratch. |
q | MoveQuery | Blocking-world query adapter. |
capsule | Capsule | Full movement capsule dimensions. |
position | Vec3 | Mutable capsule centre in metres. |
input | { acceleration: Vec3; jump?: boolean; } | Normalized world-space acceleration and optional jump. |
input.acceleration | Vec3 | Optional acceleration value. |
input.jump? | boolean | Optional jump value. |
dt | number | Simulation duration in seconds. |
Returns
void
Example
ts
const cm = createCharacterMovement();
const p = { x: 0, y: 2, z: 0 };
const empty = { sweep: () => null, overlap: () => [] };
stepCharacterMovement(cm, empty, { radius: 0.35, halfHeight: 0.55 }, p, { acceleration: {x:0,y:0,z:0} }, 1/60);stepMoves()
ts
function stepMoves(ctx): void;Advance walking orders once per tick, using addMovementInput for the next actor step. Add to defineGame systems; avoid simultaneously submitting manual or AI walking input.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current frame context. |
Returns
void
Example
ts
defineGame({ systems: [stepMoves] });stopAmbientSound()
ts
function stopAmbientSound(ctx, actor): void;Stop the ambient component once.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current context. |
actor | ActorHandle<AmbientProps> | Ambient actor. |
Returns
void
Example
ts
stopAmbientSound(ctx, ambient);stopBehaviorTree()
ts
function stopBehaviorTree(ai): void;Stop and reset the pawn's tree state.
Parameters
| Parameter | Type |
|---|---|
ai | ActorHandle |
Returns
void
Example
ts
stopBehaviorTree(ai);stopDriving()
ts
function stopDriving(ctx, ai): void;Abort a drive once and submit neutral controls to its previous pawn.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Frame context. |
ai | ActorHandle | AI controller. |
Returns
void
Example
ts
stopDriving(ctx, ai);stopMove()
ts
function stopMove(_ctx, pawn): void;Cancel an order and clear accumulated input and velocity immediately.
Parameters
| Parameter | Type | Description |
|---|---|---|
_ctx | GameContext | Current game context. |
pawn | number | Character actor root entity. |
Returns
void
Example
ts
stopMove(ctx, player);stopMovement()
ts
function stopMovement(ctx, ai): void;Abort the current request exactly once.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
ai | ActorHandle |
Returns
void
Example
ts
stopMovement(ctx, ai);stopMovementImmediately()
ts
function stopMovementImmediately(entity): void;Clear velocity, accumulated input and a pending jump.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Actor root entity. |
Returns
void
Example
ts
stopMovementImmediately(player);stopSound()
ts
function stopSound(
ctx,
actor,
component?,
fadeMs?
): void;Stop once, optionally fading out; also cancels pending autoplay.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
ctx | GameContext | undefined | Current context. |
actor | ActorHandle | undefined | Owning actor. |
component? | string | undefined | Audio component name. |
fadeMs? | number | 0 | Fade duration in milliseconds. |
Returns
void
Example
ts
stopSound(ctx, actor, 'sound', 100);suggestActorClass()
ts
function suggestActorClass(name, names?): string[];Suggest registered actor names from typos or descriptive aliases, including TriggerVolume.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Class name supplied by an author. |
names | readonly string[] | Available classes; defaults to the live registry. |
Returns
string[]
Up to three closest names, ordered by name for ties; empty when no match is close.
Example
ts
const names = suggestActorClass('PlayrStart'); // ['PlayerStart']teamOf()
ts
function teamOf(seat): number;Read a player's team id, zero when unassigned.
Parameters
| Parameter | Type | Description |
|---|---|---|
seat | number | Logged-in player seat. |
Returns
number
Team id, or zero when unassigned.
Example
ts
const team = teamOf(0);teamScore()
ts
function teamScore(team): number;Read accumulated team points, including points awarded directly to a team.
Parameters
| Parameter | Type | Description |
|---|---|---|
team | string | number | Configured team name or one-based id; zero clears membership. |
Returns
number
Accumulated match points for this team.
Example
ts
const points = teamScore('blue');teleportToTile()
ts
function teleportToTile(entity, tile): void;Place on a tile, cancelling a step and releasing its reservation. Destination must be clear.
Parameters
| Parameter | Type | Description |
|---|---|---|
entity | number | Walker entity. |
tile | Readonly<GridTile> | Destination tile. |
Returns
void
Example
ts
teleportToTile(hero.entity, { x: 0, z: 0 });thingsNear()
ts
function thingsNear(
things,
point,
radius,
out?
): WorldThing[];What is near a point: every thing whose box is within radius, the nearest first.
Allocates nothing when out is reused, so a system may ask every step.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
things | readonly WorldThing[] | undefined | The world's things. |
point | Vec3 | undefined | The point, for example the player's feet. |
radius | number | undefined | Metres. |
out | WorldThing[] | [] | The array to fill; emptied first. |
Returns
out.
Example
ts
import { thingsNear, type WorldThing } from 'gameable';
const near: WorldThing[] = [];
thingsNear(things, { x: 0, y: 0, z: -2 }, 1.5, near);
console.log(near[0]?.label); // the nearest thing within a metre and a halftopDownCamera()
ts
function topDownCamera(options?): ActorComponent;Pan/rotate/zoom a focus point while this actor is the active camera. Attach to a CameraActor subclass and use activateCamera; omit player.camera. Pose and follow bookkeeping live in actor state and survive snapshot restore.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | TopDownCameraOptions | Rig controls and limits. |
Returns
A top-down camera scene component.
Example
ts
const view = defineActor('MapCamera', { ...CameraActor.spec, components: { root: scene(), view: topDownCamera() } });topDownEye()
ts
function topDownEye(state, out): Vec3;Compute the eye from focus, yaw, downward pitch and boom distance without allocating.
Parameters
| Parameter | Type | Description |
|---|---|---|
state | TopDownCameraState | Camera pose. |
out | Vec3 | Caller-owned result. |
Returns
out.
Example
ts
topDownEye(createTopDownCamera().state, { x: 0, y: 0, z: 0 });topDownForward()
ts
function topDownForward(yaw, out): Vec3;Compute unit ground-plane pan forward; yaw zero points toward -Z.
Parameters
| Parameter | Type | Description |
|---|---|---|
yaw | number | Radians about +Y. |
out | Vec3 | Caller-owned result. |
Returns
out.
Example
ts
topDownForward(0, { x: 0, y: 0, z: 0 });traceMask()
ts
function traceMask(responses, channel): CollisionLayers;Build a trace mask from the policies of candidate bodies. A single response container cannot describe which object types answer a trace; supply the registry of setups used in the scene. Bodies sharing a layer still need post-filtering.
Parameters
| Parameter | Type | Description |
|---|---|---|
responses | readonly CollisionSetup[] | Candidate body collision setups. |
channel | "camera" | "visibility" | Trace channel to test. |
Returns
Layers whose bodies permit this query (block or overlap).
Example
ts
const mask = traceMask([collisionProfile('Pawn')], 'camera');transferItem()
ts
function transferItem(
from,
to,
item,
amount
): boolean;Transfer all requested items or none; both bags commit before notifications. Across schemas, match items by id and use the destination stack limits. A missing destination id or insufficient space fails without changing either bag.
Parameters
| Parameter | Type | Description |
|---|---|---|
from | ActorHandle | Source actor. |
to | ActorHandle | Destination actor. |
item | string | Catalog id. |
amount | number | Nonnegative safe integer. |
Returns
boolean
Whether the entire transfer succeeded.
Example
ts
const transferred = transferItem(chest, player, 'coin', 5);trySpawnActor()
ts
function trySpawnActor<P>(
ctx,
cls,
opts
): ActorHandle<P> | null;Try to spawn an actor atomically within the guest's per-step and live limits.
Type Parameters
| Type Parameter |
|---|
P extends object |
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | Current game context. |
cls | ActorClass<P> | Registered actor class. |
opts | ActorSpawnOptions<P> | Instance transform and overrides. |
Returns
ActorHandle<P> | null
The new handle, or null when allocation or construction fails or a limit is reached.
Example
ts
const crate = trySpawnActor(ctx, Crate, { position: { x: 0, y: 2, z: 0 } });unequipItem()
ts
function unequipItem(actor, slot): boolean;Return equipment to the bag atomically; an empty slot succeeds without events.
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | ActorHandle | Owning actor. |
slot | string | Named equipment slot. |
Returns
boolean
Whether the item was returned or the slot was empty.
Example
ts
const returned = unequipItem(actor, 'hand');unlockDoor()
ts
function unlockDoor(door): void;Clear the required key. Player unlocks additionally fire onUnlocked.
Parameters
| Parameter | Type | Description |
|---|---|---|
door | ActorHandle<DoorCoreProps> | Kit door instance. |
Returns
void
Example
ts
unlockDoor(door);unPossess()
ts
function unPossess(ctx, controller): void;Make a controller let its pawn go. Its player then controls nothing until the next possess.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | GameContext | The game context. |
controller | ActorHandle | The controller actor. |
Returns
void
Example
ts
unPossess(ctx, controller);utf8Decode()
ts
function utf8Decode(
b,
start?,
end?
): string;Decode UTF-8 bytes without TextDecoder.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
b | ArrayLike<number> | undefined | The bytes. Any ArrayLike<number> works, including the plain Array jco hands the guest. |
start | number | 0 | First byte to read. |
end? | number | undefined | One past the last byte to read; defaults to b.length. |
Returns
string
The decoded string.
utf8Encode()
ts
function utf8Encode(s): Uint8Array;Encode a JavaScript string as UTF-8 without TextEncoder.
Parameters
| Parameter | Type | Description |
|---|---|---|
s | string | The string to encode. |
Returns
Uint8Array
A freshly allocated UTF-8 byte array.
validateDataTables()
ts
function validateDataTables(): string[];Check deferred references in tables and assets after all declarations are loaded.
Returns
string[]
Problems naming the source row, field and missing target; empty means valid.
Example
ts
const problems = validateDataTables();validateLevel()
ts
function validateLevel(data, options?): LevelFile;Validate a level without spawning. All errors include their JSON path. Catalog types, bounds and allowed values provide authoring diagnostics.
Parameters
| Parameter | Type | Description |
|---|---|---|
data | unknown | Parsed JSON document. |
options | ValidateLevelOptions | The game's own classes, when they are not registered here. |
Returns
The validated document.
Example
ts
const level = validateLevel({ format: 1, actors: [] });vehicleMovement()
ts
function vehicleMovement(options?): ActorComponent;Dynamic box root with host arcade handling. Selector runs once at creation.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | | VehicleOptions | ((pawn) => VehicleOptions) | Preset and explicit overrides, or a pawn selector. |
Returns
Dynamic box root declaration.
Example
ts
const root = vehicleMovement(pawn => pawn.props);vehicleStateOf()
ts
function vehicleStateOf(pawn): Readonly<VehicleState> | undefined;Borrow post-step telemetry, or undefined for a non-vehicle.
Parameters
| Parameter | Type | Description |
|---|---|---|
pawn | ActorHandle | Vehicle pawn. |
Returns
Readonly<VehicleState> | undefined
Borrowed telemetry, or undefined for a non-vehicle.
Example
ts
const speed = vehicleStateOf(pawn)?.speed;viewport()
ts
function viewport(): Viewport;Current guest view dimensions; a borrowed record, treated as read-only. Hosts send a resized event on the first tick and after view resizes, so dimensions are CSS pixels before the first update. Until that event arrives, uses init dimensions divided by DPR when known, otherwise as given. The current GameConfig carries no DPR, so init dimensions are used as given. Input is client CSS coordinates: an embedded view also requires subtracting its client offset in page code.
Returns
Example
ts
const size = viewport(); console.log(size.width, size.height);viewTargetOf()
ts
function viewTargetOf(seat): ActorHandle<object> | null;Find the explicit living view target for a seat (null means use its pawn).
Parameters
| Parameter | Type | Description |
|---|---|---|
seat | number | Player seat. |
Returns
ActorHandle<object> | null
Explicit target, or null if unset or destroyed.
Example
ts
const target = viewTargetOf(0);waypointMovement()
ts
function waypointMovement(source): WaypointMovementComponent;Move the root using the actor API, which teleports kinematic bodies like race movers.
Parameters
| Parameter | Type | Description |
|---|---|---|
source | | WaypointMovementOptions | ((actor) => WaypointMovementOptions) | Static options or an allocation-free per-actor selector. |
Returns
The component and its per-actor control factory.
Example
ts
const movement = waypointMovement({ points: [{x: 3,y: 0,z: 0}], seconds: 2, mode: 'pingPong' });worldText()
ts
function worldText(text, opts?): ActorComponent;World text composed into the game's UI via actorWidgets().
Parameters
| Parameter | Type | Description |
|---|---|---|
text | string | Initial text. |
opts | ComponentOptions & object | Text style and component attachment options. |
Returns
Example
ts
const label = worldText('Shop', { size: 'lg', offset: [0, 2, 0] });worldToScreen()
ts
function worldToScreen(
ctx,
point,
out
): boolean;Project a world point using this frame's camera and guest viewport.
Parameters
| Parameter | Type |
|---|---|
ctx | GameContext |
point | Vec3 |
out | ScreenPoint |
Returns
boolean
Example
ts
worldToScreen(ctx, destination, labelPosition);worldWidget()
ts
function worldWidget(node, opts?): ActorComponent;Draw a UI node anchored to this component's entity without owning the UI model. Offset is the world anchor offset in metres, applied once; attachment rotation/scale remain local.
Parameters
| Parameter | Type | Description |
|---|---|---|
node | UiNode | Widget contents, copied separately for each actor. |
opts | ComponentOptions & object | Attachment and visibility options. |
Returns
Example
ts
const label = worldWidget({ type: 'bar', value: 10, max: 10 }, { offset: [0, 2, 0] });writeKeyBit()
ts
function writeKeyBit(
words,
index,
value
): void;Set or clear one bit in an 8-word key bitset, in place.
Parameters
| Parameter | Type | Description |
|---|---|---|
words | Uint32Array | The bitset, exactly KEY_WORDS long. |
index | number | A bit index from keyIndex. |
value | boolean | True to set the bit, false to clear it. |
Returns
void
Nothing; words is mutated.
writeSnapshot()
ts
function writeSnapshot(rt, userState?): Uint8Array;Serialise the whole guest state.
Parameters
| Parameter | Type | Description |
|---|---|---|
rt | RuntimeState | The runtime to serialise. |
userState? | unknown | Extra state from defineGame({ snapshot }). |
Returns
Uint8Array
A freshly allocated byte string. Opaque to the host.
yawRotation()
ts
function yawRotation(yaw): [number, number, number, number];A yaw as a rotation quaternion [x, y, z, w], for declarations: a spawn's rotation, a prefab placed at a heading. Allocates: make it once, not every step.
Parameters
| Parameter | Type | Description |
|---|---|---|
yaw | number | Radians about +Y; 0 faces +Z. |
Returns
[number, number, number, number]
The quaternion.
Example
ts
import { yawRotation } from 'gameable';
const spawn = { position: [0, 1, 4] as const, rotation: yawRotation(Math.PI) }; // facing -ZyawToward()
ts
function yawToward(from, to): number;The yaw that faces from one place to another on the ground plane.
Parameters
| Parameter | Type | Description |
|---|---|---|
from | number | FlatPoint | Where it stands: an entity, or a point. |
to | number | FlatPoint | What it faces: an entity, or a point. |
Returns
number
Radians about +Y; 0 faces +Z. 0 when the two are on top of each other.
Example
ts
import { yawToward } from 'gameable';
yawToward({ x: 0, z: 0 }, { x: 1, z: 0 }); // Math.PI / 2: facing +XReferences
abilitySystem
Renames and re-exports abilities
AbilitySystemOptions
Renames and re-exports AbilitiesOptions
childActor
Renames and re-exports attachedActor
childActorOf
Renames and re-exports attachedActorOf
DefaultPawn
Renames and re-exports FlyingPawn
ExponentialHeightFog
Renames and re-exports HeightFog
floatingPawnMovement
Renames and re-exports flyingMovement
InterpComponent
Renames and re-exports WaypointMovementComponent
InterpHandle
Renames and re-exports WaypointMovementHandle
InterpOptions
Renames and re-exports WaypointMovementOptions
interpToMovement
Renames and re-exports waypointMovement
KillZVolume
Renames and re-exports KillVolume
NavLinkProps
Renames and re-exports NavigationLinkProps
NavLinkProxy
Renames and re-exports NavigationLink
NavMeshBoundsProps
Renames and re-exports NavigationBoundsProps
NavMeshBoundsVolume
Renames and re-exports NavigationBounds
NavModifierProps
Renames and re-exports NavigationModifierProps
NavModifierVolume
Renames and re-exports NavigationModifier
NiagaraActor
Renames and re-exports ParticleEffect
niagaraComponent
Renames and re-exports particleEffect
NiagaraOptions
Renames and re-exports ParticleEffectOptions
PainCausingVolume
Renames and re-exports DamageVolume
pawnSensing
Renames and re-exports senses
PawnSensingOptions
Renames and re-exports SensesOptions
physicsConstraint
Renames and re-exports physicsJoint
PhysicsConstraintActor
Renames and re-exports PhysicsJoint
PhysicsConstraintOptions
Renames and re-exports PhysicsJointOptions
PhysicsConstraintProps
Renames and re-exports PhysicsJointProps
RadialForceActor
Renames and re-exports ForceField
RadialForceProps
Renames and re-exports ForceFieldProps
resetAbilitySystemRegistry
Renames and re-exports resetAbilitiesRegistry
resolveGameAddress
Renames and re-exports gameUrl
SpectatorPawn
Renames and re-exports Spectator
springArm
Renames and re-exports cameraArm
StaticMeshActor
Renames and re-exports MeshActor
textRender
Renames and re-exports worldText
TextRenderActor
Renames and re-exports WorldText
widgetComponent
Renames and re-exports worldWidget
WorldSettings
Renames and re-exports LevelSettings