@gameable/presentation
Interfaces
FreezeMessage
Existing targeted client movement freeze.
Properties
frozen
ts
frozen: boolean;LoadedRequest
Existing loaded acknowledgement; authority validates this round token.
Properties
round
ts
round: number;LoadingModel
Loading stages retain their source, outcome and optional byte progress.
Example
ts
import type { LoadingModel } from 'gameable/presentation';
const state: LoadingModel = { source: 'engine', stage: 'Starting', ready: false, failed: false };
console.log(state.source);Properties
failed
ts
failed: boolean;loaded?
ts
optional loaded?: number;ready
ts
ready: boolean;source
ts
source: "character" | "bundle" | "round" | "engine";stage
ts
stage: string;total?
ts
optional total?: number;MatchCue
Bounded private-seat cue history; sequence is monotonic across seat replacement.
Properties
sequence
ts
sequence: number;sound
ts
sound:
| "click"
| "tick"
| "go"
| "checkpoint"
| "fall"
| "jump"
| "land"
| "bump"
| "respawn"
| "finish"
| "readyOn"
| "readyOff";MatchModel
Authority HUD payload. Revision must change when reused arrays mutate.
Properties
grounded
ts
grounded: boolean;me
ts
me: number;phase
ts
phase: MatchPhase;revision
ts
revision: number;roster
ts
roster: readonly MatchSeat[];round
ts
round: number;seconds
ts
seconds: number;sfx
ts
sfx: object;events
ts
events: readonly MatchCue[];sequence
ts
sequence: number;MatchSeat
One occupied or spectator seat in an authority-produced roster.
Properties
entity
ts
entity: number;loaded
ts
loaded: boolean;name
ts
name: string;place
ts
place: number;ready
ts
ready: boolean;seat
ts
seat: number;spectator
ts
spectator: boolean;PlayerSettings
Validated portable settings; absent schemaVersion is the legacy host-only format.
Properties
features
ts
features: FeatureSpec;gameplay?
ts
optional gameplay?: object;characters
ts
characters: string[];checkpoints
ts
checkpoints: object;checkpoints.axis
ts
axis: "z";checkpoints.direction
ts
direction: "decreasing";checkpoints.fallY
ts
fallY: number = finite;checkpoints.lobbyRespawn
ts
lobbyRespawn: "seat-start";checkpoints.maxAbsX
ts
maxAbsX: number = nonnegative;checkpoints.minY
ts
minY: number = finite;checkpoints.points
ts
points: number[][];checkpoints.resetKnock
ts
resetKnock: boolean = boolean;checkpoints.thresholds
ts
thresholds: number[];contact
ts
contact: object;contact.carryTolerance
ts
carryTolerance: number = nonnegative;contact.foot
ts
foot: number = nonnegative;floors
ts
floors: number[][];knock
ts
knock: object;knock.cooldown
ts
cooldown: number = seconds;knock.duration
ts
duration: number = seconds;knock.margin
ts
margin: number = nonnegative;knock.speed
ts
speed: number = nonnegative;match
ts
match: object;match.afterFirstSeconds
ts
afterFirstSeconds: number = seconds;match.cardSeconds
ts
cardSeconds: number = seconds;match.countdownSeconds
ts
countdownSeconds: number = seconds;match.lateJoin
ts
lateJoin: "spectate-after-loading";match.limitSeconds
ts
limitSeconds: number = seconds;match.loadingSeconds
ts
loadingSeconds: number = seconds;match.minPlayers
ts
minPlayers: number = seats;match.resultsSeconds
ts
resultsSeconds: number = seconds;match.soloMinPlayers
ts
soloMinPlayers: number = seats;match.spectatorSpawnZ
ts
spectatorSpawnZ: number = finite;match.start
ts
start: "all-ready";movers
ts
movers: object[];placing
ts
placing: object;placing.at
ts
at: number = finite;placing.axis
ts
axis: "z";placing.direction
ts
direction: "decreasing";placing.freezeFinishers
ts
freezeFinishers: boolean = boolean;placing.maxAbsX
ts
maxAbsX: number = nonnegative;placing.maxY
ts
maxY: number = finite;placing.minY
ts
minY: number = finite;placing.requiresAllCheckpoints
ts
requiresAllCheckpoints: false;placing.tieBreak
ts
tieBreak: "seat";spawns
ts
spawns: number[][];walk
ts
walk: object;walk.body
ts
body: object;walk.body.dims
ts
dims: number[];walk.body.flags
ts
flags: object;walk.body.flags.asleep
ts
asleep: boolean | undefined;walk.body.flags.ccd
ts
ccd: boolean | undefined;walk.body.flags.lockRotation
ts
lockRotation: boolean | undefined;walk.body.flags.noSleep
ts
noSleep: boolean | undefined;walk.body.flags.reportContacts
ts
reportContacts: boolean | undefined;walk.body.flags.reportStay
ts
reportStay: boolean | undefined;walk.body.flags.sensor
ts
sensor: boolean | undefined;walk.body.kind
ts
kind: "character";walk.body.layer
ts
layer: object = layers;Index Signature
ts
[key: string]: boolean | undefinedwalk.body.mask
ts
mask: object = layers;Index Signature
ts
[key: string]: boolean | undefinedwalk.body.mass
ts
mass: number = positive;walk.body.shape
ts
shape: "capsule";walk.cameraMaxPitch
ts
cameraMaxPitch: number = finite;walk.cameraMinPitch
ts
cameraMinPitch: number = finite;walk.cameraPitch
ts
cameraPitch: number = finite;walk.jumpSpeed
ts
jumpSpeed: number = nonnegative;walk.prediction
ts
prediction: "own-body";walk.runSpeed
ts
runSpeed: number = nonnegative;walk.scheme
ts
scheme: "third-person";walk.walkSpeed
ts
walkSpeed: number = nonnegative;input?
ts
optional input?: object;touch
ts
touch: "gestures" | "sticks";maxPlayers
ts
maxPlayers: number;name?
ts
optional name?: string;physics
ts
physics: Omit<PhysicsOptions, "wasmUrl">;player?
ts
optional player?: Omit<PlayerSpec, "character" | "spawn" | "prefab">;scene?
ts
optional scene?: object;arches
ts
arches: object;arches.finish
ts
finish: object = arch;arches.finish.pillarX
ts
pillarX: number = positive;arches.finish.top
ts
top: number = positive;arches.finish.z
ts
z: number = finite;arches.start
ts
start: object = arch;arches.start.pillarX
ts
pillarX: number = positive;arches.start.top
ts
top: number = positive;arches.start.z
ts
z: number = finite;arrows
ts
arrows: object;arrows.halfLength
ts
halfLength: number = positive;arrows.halfWidth
ts
halfWidth: number = positive;arrows.margin
ts
margin: number = nonnegative;gapEdges
ts
gapEdges: number[];palette
ts
palette: number[][];renderer
ts
renderer: "raceCandy";sea
ts
sea: object;sea.size
ts
size: number = positive;sea.y
ts
y: number = finite;version
ts
version: 1 | undefined;schemaVersion?
ts
optional schemaVersion?: 1;sendHz
ts
sendHz: number;ui?
ts
optional ui?: object;actions
ts
actions: ("leave" | "ready" | "change-character")[] | undefined;characters
ts
characters:
| {
allowDefault: boolean;
allowPaste: boolean;
changePolicy: "lobby-unready-swap";
endpoint: string;
storageKey: string;
studio: string;
}
| undefined;connection
ts
connection:
| {
refusalReasons: ("full" | "capacity" | "busy")[];
rejoinReasons: ("idle" | "version")[];
retrySeconds: number;
}
| undefined;controls
ts
controls:
| {
cancel: string;
failed: "stand-in";
localLoadTimeoutSeconds: number;
ready: string;
readyKey: "KeyR";
roundProgress: boolean;
}
| undefined;cues
ts
cues:
| {
effects: {
fallFlashMs: number;
finish: "confetti";
};
history: 8;
localJump: "space-grounded";
source: string;
synth: "race-v1";
}
| undefined;errors
ts
errors:
| {
causes: number;
warnings: boolean;
}
| undefined;hint
ts
hint:
| {
text: string;
}
| undefined;hud
ts
hud:
| {
capacity: number;
countdown: {
cardSeconds: number;
from: number;
goSeconds: number;
instruction: string;
};
labels: {
lobby: string;
};
results: {
missingPlace: string;
returnLabel: string;
sort: "place";
spectator: string;
};
source: string;
type: "match";
version: 1 | undefined;
}
| undefined;loading
ts
loading:
| {
characterStatus: boolean;
renderer: "status";
roundBarrier: boolean;
version: 1 | undefined;
}
| undefined;menu
ts
menu:
| {
code: {
max: number;
min: number;
uppercase: true;
};
labels: {
new: string;
quick: string;
solo: string;
};
modes: ("solo" | "join" | "new" | "quick")[];
title: string;
}
| undefined;modules
ts
modules: object[] | undefined;players
ts
players:
| {
arrivalMs: number;
contactDiscs: boolean;
names: boolean;
standInPalette: "race";
}
| undefined;rooms
ts
rooms:
| {
activeLabel: string;
activePhases: ("lobby" | "loading" | "countdown" | "racing" | "results")[];
idleLabel: string;
public: boolean;
}
| undefined;session
ts
session:
| {
rejoin: boolean;
returnTo: "menu";
}
| undefined;theme
ts
theme:
| {
gameplay: "gameable" | "raceCandy";
shell: "gameable";
}
| undefined;world
ts
world: WorldSpec;StartIntent
Session intent selected before engine boot.
Example
ts
import type { StartIntent } from 'gameable/presentation';
const intent: StartIntent = { kind: 'solo' };
console.log(intent.kind);Properties
code?
ts
optional code?: string;kind
ts
kind: "solo" | "join" | "new" | "quick";look?
ts
optional look?: string;Type Aliases
GameplaySettings
ts
type GameplaySettings = ReturnType<typeof gameplaySchema>;Authored race module data embedded in the guest's rules.gameplay.
MatchPhase
ts
type MatchPhase = "lobby" | "loading" | "countdown" | "racing" | "results";Semantic match phases carried in the HUD namespace.
PresentationModule
ts
type PresentationModule = ReturnType<typeof moduleSchema>;Versioned engine-owned module selection; no code URLs cross this contract.
ReadyRequest
ts
type ReadyRequest = null;Existing ready request: null payload, eight-byte transport limit.
SceneSettings
ts
type SceneSettings = ReturnType<typeof sceneSchema>;Named engine-owned scene preset options.
UISettings
ts
type UISettings = ReturnType<typeof uiSchema>;Closed, engine-owned presentation selections.
Functions
assertDefinitionSettings()
ts
function assertDefinitionSettings(settings, definition): void;Reject authored host/guest drift, including module data embedded as rules.gameplay.
Parameters
| Parameter | Type | Description |
|---|---|---|
settings | PlayerSettings | Validated authored settings. |
definition | GameDefinition | The guest game declaration loaded by the CLI. |
Returns
void
Example
ts
const settings = parseSettings({ features: {}, world: {}, physics: {}, maxPlayers: 1, sendHz: 20 });
assertDefinitionSettings(settings, {});canChangeCharacter()
ts
function canChangeCharacter(
phase,
ready,
spectator?
): boolean;Character swaps preserve the room and are available only while unready in lobby.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
phase | string | undefined | undefined | Authoritative match phase. |
ready | boolean | undefined | undefined | Local seat readiness. |
spectator | boolean | false | Whether the local seat is spectating. |
Returns
boolean
Whether an in-place lobby swap is allowed.
characterName()
ts
function characterName(result, look?): string;Resolve the display name without exposing a source URL.
Parameters
| Parameter | Type | Description |
|---|---|---|
result | MyCharactersResult | null | Catalog result, or null before it arrives. |
look? | string | Canonical character source, or undefined for the default character. |
Returns
string
The selected name or a stable fallback.
characterPanel()
ts
function characterPanel(result): "signed-out" | "unavailable" | "loading" | "cards" | "empty";Project catalog state without DOM or transport.
Parameters
| Parameter | Type | Description |
|---|---|---|
result | MyCharactersResult | null | Catalog result, or null before it arrives. |
Returns
"signed-out" | "unavailable" | "loading" | "cards" | "empty"
The catalog panel state.
characterSelection()
ts
function characterSelection(look?): CharacterSelection;Default is an explicit choice, separate from no selection.
Parameters
| Parameter | Type | Description |
|---|---|---|
look? | string | Canonical character source, or undefined for the default character. |
Returns
CharacterSelection
An explicit selection state, distinct from choosing the default.
connectionModel()
ts
function connectionModel(
state,
reason,
until,
now,
settings
): object;Pure connection projection; the caller records the first refusal deadline.
Parameters
| Parameter | Type | Description |
|---|---|---|
state | string | Current connection state. |
reason | string | Transport closure reason. |
until | number | First refusal deadline in milliseconds. |
now | number | Current time in milliseconds. |
settings | { refusalReasons: ("full" | "capacity" | "busy")[]; rejoinReasons: ("idle" | "version")[]; retrySeconds: number; } | Validated presentation settings. |
settings.refusalReasons | ("full" | "capacity" | "busy")[] | - |
settings.rejoinReasons | ("idle" | "version")[] | - |
settings.retrySeconds | number | - |
Returns
object
Connection text, visibility, cooldown and permitted actions.
message
ts
message: string;refused
ts
refused: boolean;rejoin
ts
rejoin: boolean;retry
ts
retry: boolean;seconds
ts
seconds: number;visible
ts
visible: boolean = closed;controlsModel()
ts
function controlsModel(
model,
character,
settings
): object;Resolve readiness controls without DOM or transport access.
Parameters
| Parameter | Type | Description |
|---|---|---|
model | MatchModel | null | Authority snapshot, if received. |
character | CharacterLoad | Local visual readiness. |
settings | { cancel: string; failed: "stand-in"; localLoadTimeoutSeconds: number; ready: string; readyKey: "KeyR"; roundProgress: boolean; } | Authored control labels. |
settings.cancel | string | - |
settings.failed | "stand-in" | - |
settings.localLoadTimeoutSeconds | number | - |
settings.ready | string | - |
settings.readyKey | "KeyR" | - |
settings.roundProgress | boolean | - |
Returns
object
Button visibility, text and status.
label
ts
label: string;progress
ts
progress: number | null;shown
ts
shown: boolean;status
ts
status: string;createConnectionScreen()
ts
function createConnectionScreen(options): object;Render network closure with a single refusal deadline and removable timer/listener.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | { allowRejoin: boolean; mount: HTMLElement; net: { closeReason: string; state: string; onChange: () => void; }; settings: { refusalReasons: ("full" | "capacity" | "busy")[]; rejoinReasons: ("idle" | "version")[]; retrySeconds: number; }; closeLobby: void; menu: void; rejoin: void; } | Validated configuration and caller-owned host callbacks. |
options.allowRejoin | boolean | Whether the session allows rejoining. |
options.mount | HTMLElement | Caller-owned screen container. |
options.net | { closeReason: string; state: string; onChange: () => void; } | Observable connection state. |
options.net.closeReason | string | Final closure or refusal reason. |
options.net.state | string | Current transport state. |
options.net.onChange | Subscribe to transport state changes. | |
options.settings | { refusalReasons: ("full" | "capacity" | "busy")[]; rejoinReasons: ("idle" | "version")[]; retrySeconds: number; } | Validated presentation settings. |
options.settings.refusalReasons | ("full" | "capacity" | "busy")[] | - |
options.settings.rejoinReasons | ("idle" | "version")[] | - |
options.settings.retrySeconds | number | - |
options.closeLobby | Hide lobby actions when the connection closes. | |
options.menu | Return to the menu after cleanup. | |
options.rejoin | Restart with the same session intent after cleanup. |
Returns
object
The mounted screen and its timer/subscription cleanup.
element
ts
element: HTMLElement;dispose()
ts
dispose(): void;Returns
void
createControls()
ts
function createControls(
doc,
settings,
toggle,
loadingSeconds
): object;Build persistent controls; updates never detach a pressed button.
Parameters
| Parameter | Type | Description |
|---|---|---|
doc | Document | Drawing document. |
settings | { cancel: string; failed: "stand-in"; localLoadTimeoutSeconds: number; ready: string; readyKey: "KeyR"; roundProgress: boolean; } | Authored labels and key binding. |
settings.cancel | string | - |
settings.failed | "stand-in" | - |
settings.localLoadTimeoutSeconds | number | - |
settings.ready | string | - |
settings.readyKey | "KeyR" | - |
settings.roundProgress | boolean | - |
toggle | () => void | Send the readiness action. |
loadingSeconds | number | Round barrier duration. |
Returns
object
Replaceable controls drawing and disposal.
button
ts
button: HTMLButtonElement;element
ts
element: HTMLDivElement;dispose()
ts
dispose(): void;Returns
void
render()
ts
render(model, character): void;Parameters
| Parameter | Type |
|---|---|
model | MatchModel | null |
character | CharacterLoad |
Returns
void
createCues()
ts
function createCues(sink?): object;Own a replaceable sound/effect sink for exactly one session.
Parameters
| Parameter | Type | Description |
|---|---|---|
sink? | { dispose: void | Promise<void>; emit: void; } | Sound or drawing implementation; omitted for silent presentation. |
sink.dispose? | Release drawing or audio resources. | |
sink.emit? | Deliver a sound or effect once. |
Returns
object
Cue delivery and idempotent teardown.
dispose()
ts
dispose(): void | Promise<void>;Returns
void | Promise<void>
set()
ts
set(model): void;Parameters
| Parameter | Type |
|---|---|
model | MatchModel |
Returns
void
createCuesModel()
ts
function createCuesModel(emit): (model) => void;Consume sequence history independently of snapshots, rounds and DOM replacement.
Parameters
| Parameter | Type | Description |
|---|---|---|
emit | (cue) => void | Replaceable cue sink. |
Returns
A consumer retaining its cursor until the session ends.
(model) => void
createErrorScreen()
ts
function createErrorScreen(options): object;Separate fatal and warning channels; drawing can be replaced without changing the projection.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | { menu?: () => void; mount: HTMLElement; settings: { causes: number; warnings: boolean; }; } | Validated configuration and caller-owned host callbacks. |
options.menu? | () => void | Return to the menu after cleanup. |
options.mount | HTMLElement | Caller-owned screen container. |
options.settings | { causes: number; warnings: boolean; } | Validated presentation settings. |
options.settings.causes | number | - |
options.settings.warnings | boolean | - |
Returns
object
Independent fatal and warning drawing channels and their cleanup.
element
ts
element: HTMLElement;dispose()
ts
dispose(): void;Returns
void
show()
ts
show(error, severity): void;Parameters
| Parameter | Type |
|---|---|
error | unknown |
severity | "fatal" | "warning" |
Returns
void
createLoadingScreen()
ts
function createLoadingScreen(mount): object;Replaceable status drawing for any loading source.
Parameters
| Parameter | Type | Description |
|---|---|---|
mount | HTMLElement | Caller-owned screen container. |
Returns
object
A replaceable loading renderer and its cleanup.
element
ts
element: HTMLParagraphElement;dispose()
ts
dispose(): void;Returns
void
render()
ts
render(model): void;Parameters
| Parameter | Type |
|---|---|
model | LoadingModel |
Returns
void
createMatchHud()
ts
function createMatchHud(options): object;Draw a match namespace through the host's replaceable HUD seam.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | { character: (model) => CharacterLoad; controls?: { cancel: string; failed: "stand-in"; localLoadTimeoutSeconds: number; ready: string; readyKey: "KeyR"; roundProgress: boolean; }; cues?: { dispose: void | Promise<void>; emit: void; }; cueSettings?: { effects: { fallFlashMs: number; finish: "confetti"; }; history: 8; localJump: "space-grounded"; source: string; synth: "race-v1"; }; hint?: string; hud: { capacity: number; countdown: { cardSeconds: number; from: number; goSeconds: number; instruction: string; }; labels: { lobby: string; }; results: { missingPlace: string; returnLabel: string; sort: "place"; spectator: string; }; source: string; type: "match"; version: 1 | undefined; }; loadingSeconds: number; mount: HTMLElement; ready: () => void; theme?: "gameable" | "raceCandy"; } | Authored configuration, mount and page-owned actions. |
options.character | (model) => CharacterLoad | Read character visual readiness. |
options.controls? | { cancel: string; failed: "stand-in"; localLoadTimeoutSeconds: number; ready: string; readyKey: "KeyR"; roundProgress: boolean; } | Optional readiness controls. |
options.controls.cancel | string | - |
options.controls.failed | "stand-in" | - |
options.controls.localLoadTimeoutSeconds | number | - |
options.controls.ready | string | - |
options.controls.readyKey | "KeyR" | - |
options.controls.roundProgress | boolean | - |
options.cues? | { dispose: void | Promise<void>; emit: void; } | Replaceable sound and effect implementation. |
options.cues.dispose | Release sound and effect resources. | |
options.cues.emit | Deliver an unseen authority cue. | |
options.cueSettings? | { effects: { fallFlashMs: number; finish: "confetti"; }; history: 8; localJump: "space-grounded"; source: string; synth: "race-v1"; } | Optional engine-owned race-v1 synth and effects. |
options.cueSettings.effects | { fallFlashMs: number; finish: "confetti"; } | - |
options.cueSettings.effects.fallFlashMs | number | - |
options.cueSettings.effects.finish | "confetti" | - |
options.cueSettings.history | 8 | - |
options.cueSettings.localJump | "space-grounded" | - |
options.cueSettings.source | string | - |
options.cueSettings.synth | "race-v1" | - |
options.hint? | string | Optional movement instructions. |
options.hud | { capacity: number; countdown: { cardSeconds: number; from: number; goSeconds: number; instruction: string; }; labels: { lobby: string; }; results: { missingPlace: string; returnLabel: string; sort: "place"; spectator: string; }; source: string; type: "match"; version: 1 | undefined; } | Validated match namespace and text settings. |
options.hud.capacity | number | - |
options.hud.countdown | { cardSeconds: number; from: number; goSeconds: number; instruction: string; } | - |
options.hud.countdown.cardSeconds | number | - |
options.hud.countdown.from | number | - |
options.hud.countdown.goSeconds | number | - |
options.hud.countdown.instruction | string | - |
options.hud.labels | { lobby: string; } | - |
options.hud.labels.lobby | string | - |
options.hud.results | { missingPlace: string; returnLabel: string; sort: "place"; spectator: string; } | - |
options.hud.results.missingPlace | string | - |
options.hud.results.returnLabel | string | - |
options.hud.results.sort | "place" | - |
options.hud.results.spectator | string | - |
options.hud.source | string | - |
options.hud.type | "match" | - |
options.hud.version | 1 | undefined | - |
options.loadingSeconds | number | Authority loading deadline in seconds. |
options.mount | HTMLElement | Caller-owned overlay container. |
options.ready | () => void | Request a readiness toggle. |
options.theme? | "gameable" | "raceCandy" | Named engine-owned gameplay theme. |
Returns
HUD renderer plus a frame refresh for asynchronous character loading.
element
ts
element: HTMLElement;refresh
ts
refresh: () => void;Refresh controls after asynchronous loading, including unchanged HUD frames.
Returns
void
current
Get Signature
ts
get current(): MatchModel | null;Returns
MatchModel | null
model
Get Signature
ts
get model():
| {
[key: string]: string | MatchModel;
message: string;
}
| null;Returns
| { [key: string]: string | MatchModel; message: string; } | null
clear()
ts
clear(): void;Returns
void
dispose()
ts
dispose(): void | Promise<void>;Returns
void | Promise<void>
set()
ts
set(json): boolean;Parameters
| Parameter | Type |
|---|---|
json | string | undefined |
Returns
boolean
createMatchModel()
ts
function createMatchModel(source): object;Replace snapshots even when the authority reuses its roster and cue arrays.
Parameters
| Parameter | Type | Description |
|---|---|---|
source | string | Configured HUD namespace. |
Returns
object
A DOM-free model sink. Undefined frames preserve the snapshot; clear removes it.
current
Get Signature
ts
get current(): MatchModel | null;Returns
MatchModel | null
clear()
ts
clear(): void;Returns
void
set()
ts
set(json): boolean;Parameters
| Parameter | Type |
|---|---|
json | string | undefined |
Returns
boolean
createRoomsScreen()
ts
function createRoomsScreen(options): object;Subscribe to a replaceable transport and close late results after unmount.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | { mount: HTMLElement; settings: { activeLabel: string; activePhases: ("lobby" | "loading" | "countdown" | "racing" | "results")[]; idleLabel: string; public: boolean; }; version: string; join: void; load: Promise<LiveRoomList>; } | Validated configuration and caller-owned host callbacks. |
options.mount | HTMLElement | Caller-owned screen container. |
options.settings | { activeLabel: string; activePhases: ("lobby" | "loading" | "countdown" | "racing" | "results")[]; idleLabel: string; public: boolean; } | Validated presentation settings. |
options.settings.activeLabel | string | - |
options.settings.activePhases | ("lobby" | "loading" | "countdown" | "racing" | "results")[] | - |
options.settings.idleLabel | string | - |
options.settings.public | boolean | - |
options.version | string | Immutable game version to browse. |
options.join | Join the selected room code. | |
options.load | Open a replaceable catalog or room-list transport. |
Returns
object
A live room-list screen and its transport cleanup.
element
ts
element: HTMLElement;dispose()
ts
dispose(): void;Returns
void
createSession()
ts
function createSession(): object;Reverse-order asynchronous cleanup, also used for failed boots.
Returns
object
A lifetime whose disposal runs once and awaits every registered cleanup.
dispose()
ts
dispose(): Promise<void>;Returns
Promise<void>
use()
ts
use(cleanup): void;Parameters
| Parameter | Type |
|---|---|
cleanup | () => void | Promise<void> |
Returns
void
createSessionLifetime()
ts
function createSessionLifetime(options): object;Track loading and round acknowledgements without depending on HUD emission cadence. Missing entries wait locally but do not block the round, matching the reference policy.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | { character: (entity) => CharacterLoad | "missing"; now?: () => number; send: (name, payload) => boolean; timeoutSeconds: number; } | Replaceable clock, load lookup and transport bindings. |
options.character | (entity) => CharacterLoad | "missing" | Read visual readiness; missing entries are allowed at the round barrier. |
options.now? | () => number | Clock in milliseconds. |
options.send | (name, payload) => boolean | Send an existing match protocol message; false retries. |
options.timeoutSeconds | number | Maximum visual loading time before using a stand-in. |
Returns
object
A per-session frame reader and action binding.
character()
ts
character(model): CharacterLoad;Parameters
| Parameter | Type |
|---|---|
model | MatchModel | null |
Returns
CharacterLoad
dispose()
ts
dispose(): void;Returns
void
frame()
ts
frame(model): void;Parameters
| Parameter | Type |
|---|---|
model | MatchModel | null |
Returns
void
ready()
ts
ready(): void;Returns
void
reset()
ts
reset(entity): void;Parameters
| Parameter | Type |
|---|---|
entity | number |
Returns
void
createStartMenu()
ts
function createStartMenu(options): object;Draw mode choices; the caller owns character selection and room transport.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | { change?: () => void; mount: HTMLElement; name: string; settings: { code: { max: number; min: number; uppercase: true; }; labels: { new: string; quick: string; solo: string; }; modes: ("solo" | "join" | "new" | "quick")[]; title: string; }; choose: void; } | Validated configuration and caller-owned host callbacks. |
options.change? | () => void | Open the character picker. |
options.mount | HTMLElement | Caller-owned screen container. |
options.name | string | Selected character display name. |
options.settings | { code: { max: number; min: number; uppercase: true; }; labels: { new: string; quick: string; solo: string; }; modes: ("solo" | "join" | "new" | "quick")[]; title: string; } | Validated presentation settings. |
options.settings.code | { max: number; min: number; uppercase: true; } | - |
options.settings.code.max | number | - |
options.settings.code.min | number | - |
options.settings.code.uppercase | true | - |
options.settings.labels | { new: string; quick: string; solo: string; } | - |
options.settings.labels.new | string | - |
options.settings.labels.quick | string | - |
options.settings.labels.solo | string | - |
options.settings.modes | ("solo" | "join" | "new" | "quick")[] | - |
options.settings.title | string | - |
options.choose | Deliver the selected session intent, or end the loop with undefined. |
Returns
object
Mode and room-code controls with explicit disposal.
element
ts
element: HTMLElement;dispose()
ts
dispose(): void;Returns
void
definitionSettings()
ts
function definitionSettings(definition, physics): PlayerSettings;Derive the legacy host fields without executable prefab/spawn data.
Parameters
| Parameter | Type | Description |
|---|---|---|
definition | GameDefinition | The guest game declaration loaded by the CLI. |
physics | Omit<PhysicsOptions, "wasmUrl"> | Validated host physics options. |
Returns
Declarative settings derived from the definition.
Example
ts
console.log(definitionSettings({}, {}).maxPlayers); // 1directStart()
ts
function directStart(code?): StartIntent | undefined;Direct links skip mode selection, after character selection.
Parameters
| Parameter | Type | Description |
|---|---|---|
code? | string | Direct room-link value. |
Returns
StartIntent | undefined
The direct session intent, or undefined to open the menu.
errorModel()
ts
function errorModel(error, causes): string;Bound fatal cause chains, including cyclic causes.
Parameters
| Parameter | Type | Description |
|---|---|---|
error | unknown | Host failure or warning. |
causes | number | Maximum nested causes to include. |
Returns
string
A bounded readable cause chain.
errorView()
ts
function errorView(
error,
severity,
settings
): object;Project fatal errors and optional warnings independently of their renderer.
Parameters
| Parameter | Type | Description |
|---|---|---|
error | unknown | Host failure or warning. |
severity | "fatal" | "warning" | Fatal failure or recoverable warning channel. |
settings | { causes: number; warnings: boolean; } | Validated presentation settings. |
settings.causes | number | - |
settings.warnings | boolean | - |
Returns
object
Severity, visibility and readable error text.
message
ts
message: string;severity
ts
severity: "fatal" | "warning";visible
ts
visible: boolean;installCourseScene()
ts
function installCourseScene(
engine,
gameplay,
scene,
localEntity?
): () => void;Install the page's candy course once after boot.
Parameters
| Parameter | Type | Description |
|---|---|---|
engine | Engine | Booted host and rendering services. |
gameplay | { characters: string[]; checkpoints: { axis: "z"; direction: "decreasing"; fallY: number; lobbyRespawn: "seat-start"; maxAbsX: number; minY: number; points: number[][]; resetKnock: boolean; thresholds: number[]; }; contact: { carryTolerance: number; foot: number; }; floors: number[][]; knock: { cooldown: number; duration: number; margin: number; speed: number; }; match: { afterFirstSeconds: number; cardSeconds: number; countdownSeconds: number; lateJoin: "spectate-after-loading"; limitSeconds: number; loadingSeconds: number; minPlayers: number; resultsSeconds: number; soloMinPlayers: number; spectatorSpawnZ: number; start: "all-ready"; }; movers: object[]; placing: { at: number; axis: "z"; direction: "decreasing"; freezeFinishers: boolean; maxAbsX: number; maxY: number; minY: number; requiresAllCheckpoints: false; tieBreak: "seat"; }; spawns: number[][]; walk: { body: { dims: number[]; flags: { asleep: boolean | undefined; ccd: boolean | undefined; lockRotation: boolean | undefined; noSleep: boolean | undefined; reportContacts: boolean | undefined; reportStay: boolean | undefined; sensor: boolean | undefined; }; kind: "character"; layer: { [key: string]: boolean | undefined; }; mask: { [key: string]: boolean | undefined; }; mass: number; shape: "capsule"; }; cameraMaxPitch: number; cameraMinPitch: number; cameraPitch: number; jumpSpeed: number; prediction: "own-body"; runSpeed: number; scheme: "third-person"; walkSpeed: number; }; } | Validated course collision and mover data. |
gameplay.characters | string[] | - |
gameplay.checkpoints | { axis: "z"; direction: "decreasing"; fallY: number; lobbyRespawn: "seat-start"; maxAbsX: number; minY: number; points: number[][]; resetKnock: boolean; thresholds: number[]; } | - |
gameplay.checkpoints.axis? | "z" | - |
gameplay.checkpoints.direction? | "decreasing" | - |
gameplay.checkpoints.fallY? | number | - |
gameplay.checkpoints.lobbyRespawn? | "seat-start" | - |
gameplay.checkpoints.maxAbsX? | number | - |
gameplay.checkpoints.minY? | number | - |
gameplay.checkpoints.points? | number[][] | - |
gameplay.checkpoints.resetKnock? | boolean | - |
gameplay.checkpoints.thresholds? | number[] | - |
gameplay.contact? | { carryTolerance: number; foot: number; } | - |
gameplay.contact.carryTolerance? | number | - |
gameplay.contact.foot? | number | - |
gameplay.floors? | number[][] | - |
gameplay.knock? | { cooldown: number; duration: number; margin: number; speed: number; } | - |
gameplay.knock.cooldown? | number | - |
gameplay.knock.duration? | number | - |
gameplay.knock.margin? | number | - |
gameplay.knock.speed? | number | - |
gameplay.match? | { afterFirstSeconds: number; cardSeconds: number; countdownSeconds: number; lateJoin: "spectate-after-loading"; limitSeconds: number; loadingSeconds: number; minPlayers: number; resultsSeconds: number; soloMinPlayers: number; spectatorSpawnZ: number; start: "all-ready"; } | - |
gameplay.match.afterFirstSeconds? | number | - |
gameplay.match.cardSeconds? | number | - |
gameplay.match.countdownSeconds? | number | - |
gameplay.match.lateJoin? | "spectate-after-loading" | - |
gameplay.match.limitSeconds? | number | - |
gameplay.match.loadingSeconds? | number | - |
gameplay.match.minPlayers? | number | - |
gameplay.match.resultsSeconds? | number | - |
gameplay.match.soloMinPlayers? | number | - |
gameplay.match.spectatorSpawnZ? | number | - |
gameplay.match.start? | "all-ready" | - |
gameplay.movers? | object[] | - |
gameplay.placing? | { at: number; axis: "z"; direction: "decreasing"; freezeFinishers: boolean; maxAbsX: number; maxY: number; minY: number; requiresAllCheckpoints: false; tieBreak: "seat"; } | - |
gameplay.placing.at? | number | - |
gameplay.placing.axis? | "z" | - |
gameplay.placing.direction? | "decreasing" | - |
gameplay.placing.freezeFinishers? | boolean | - |
gameplay.placing.maxAbsX? | number | - |
gameplay.placing.maxY? | number | - |
gameplay.placing.minY? | number | - |
gameplay.placing.requiresAllCheckpoints? | false | - |
gameplay.placing.tieBreak? | "seat" | - |
gameplay.spawns? | number[][] | - |
gameplay.walk? | { body: { dims: number[]; flags: { asleep: boolean | undefined; ccd: boolean | undefined; lockRotation: boolean | undefined; noSleep: boolean | undefined; reportContacts: boolean | undefined; reportStay: boolean | undefined; sensor: boolean | undefined; }; kind: "character"; layer: { [key: string]: boolean | undefined; }; mask: { [key: string]: boolean | undefined; }; mass: number; shape: "capsule"; }; cameraMaxPitch: number; cameraMinPitch: number; cameraPitch: number; jumpSpeed: number; prediction: "own-body"; runSpeed: number; scheme: "third-person"; walkSpeed: number; } | - |
gameplay.walk.body? | { dims: number[]; flags: { asleep: boolean | undefined; ccd: boolean | undefined; lockRotation: boolean | undefined; noSleep: boolean | undefined; reportContacts: boolean | undefined; reportStay: boolean | undefined; sensor: boolean | undefined; }; kind: "character"; layer: { [key: string]: boolean | undefined; }; mask: { [key: string]: boolean | undefined; }; mass: number; shape: "capsule"; } | - |
gameplay.walk.body.dims? | number[] | - |
gameplay.walk.body.flags? | { asleep: boolean | undefined; ccd: boolean | undefined; lockRotation: boolean | undefined; noSleep: boolean | undefined; reportContacts: boolean | undefined; reportStay: boolean | undefined; sensor: boolean | undefined; } | - |
gameplay.walk.body.flags.asleep? | boolean | undefined | - |
gameplay.walk.body.flags.ccd? | boolean | undefined | - |
gameplay.walk.body.flags.lockRotation? | boolean | undefined | - |
gameplay.walk.body.flags.noSleep? | boolean | undefined | - |
gameplay.walk.body.flags.reportContacts? | boolean | undefined | - |
gameplay.walk.body.flags.reportStay? | boolean | undefined | - |
gameplay.walk.body.flags.sensor? | boolean | undefined | - |
gameplay.walk.body.kind? | "character" | - |
gameplay.walk.body.layer? | { [key: string]: boolean | undefined; } | - |
gameplay.walk.body.mask? | { [key: string]: boolean | undefined; } | - |
gameplay.walk.body.mass? | number | - |
gameplay.walk.body.shape? | "capsule" | - |
gameplay.walk.cameraMaxPitch? | number | - |
gameplay.walk.cameraMinPitch? | number | - |
gameplay.walk.cameraPitch? | number | - |
gameplay.walk.jumpSpeed? | number | - |
gameplay.walk.prediction? | "own-body" | - |
gameplay.walk.runSpeed? | number | - |
gameplay.walk.scheme? | "third-person" | - |
gameplay.walk.walkSpeed? | number | - |
scene? | { arches: { finish: { pillarX: number; top: number; z: number; }; start: { pillarX: number; top: number; z: number; }; }; arrows: { halfLength: number; halfWidth: number; margin: number; }; gapEdges: number[]; palette: number[][]; renderer: "raceCandy"; sea: { size: number; y: number; }; version: 1 | undefined; } | Validated named scene preset settings. |
scene.arches? | { finish: { pillarX: number; top: number; z: number; }; start: { pillarX: number; top: number; z: number; }; } | - |
scene.arches.finish? | { pillarX: number; top: number; z: number; } | - |
scene.arches.finish.pillarX? | number | - |
scene.arches.finish.top? | number | - |
scene.arches.finish.z? | number | - |
scene.arches.start? | { pillarX: number; top: number; z: number; } | - |
scene.arches.start.pillarX? | number | - |
scene.arches.start.top? | number | - |
scene.arches.start.z? | number | - |
scene.arrows? | { halfLength: number; halfWidth: number; margin: number; } | - |
scene.arrows.halfLength? | number | - |
scene.arrows.halfWidth? | number | - |
scene.arrows.margin? | number | - |
scene.gapEdges? | number[] | - |
scene.palette? | number[][] | - |
scene.renderer? | "raceCandy" | - |
scene.sea? | { size: number; y: number; } | - |
scene.sea.size? | number | - |
scene.sea.y? | number | - |
scene.version? | 1 | undefined | - |
localEntity? | () => number | Read the local roster entity, zero before joining. |
Returns
Idempotent cleanup restoring the previous scene.
() => void
Example
ts
console.log(typeof installCourseScene);installPlayerVisuals()
ts
function installPlayerVisuals(
engine,
characters,
read,
gameplay,
options,
mount,
now?
): () => void;Draw stand-ins, names and contact discs on roster draw roots.
Parameters
| Parameter | Type | Description |
|---|---|---|
engine | Engine | Booted host and rendering services. |
characters | | { entryOf: | { ready: boolean; } | null | undefined; } | undefined | Optional character readiness reader. |
read | () => MatchModel | null | Read the latest authority match snapshot. |
gameplay | { characters: string[]; checkpoints: { axis: "z"; direction: "decreasing"; fallY: number; lobbyRespawn: "seat-start"; maxAbsX: number; minY: number; points: number[][]; resetKnock: boolean; thresholds: number[]; }; contact: { carryTolerance: number; foot: number; }; floors: number[][]; knock: { cooldown: number; duration: number; margin: number; speed: number; }; match: { afterFirstSeconds: number; cardSeconds: number; countdownSeconds: number; lateJoin: "spectate-after-loading"; limitSeconds: number; loadingSeconds: number; minPlayers: number; resultsSeconds: number; soloMinPlayers: number; spectatorSpawnZ: number; start: "all-ready"; }; movers: object[]; placing: { at: number; axis: "z"; direction: "decreasing"; freezeFinishers: boolean; maxAbsX: number; maxY: number; minY: number; requiresAllCheckpoints: false; tieBreak: "seat"; }; spawns: number[][]; walk: { body: { dims: number[]; flags: { asleep: boolean | undefined; ccd: boolean | undefined; lockRotation: boolean | undefined; noSleep: boolean | undefined; reportContacts: boolean | undefined; reportStay: boolean | undefined; sensor: boolean | undefined; }; kind: "character"; layer: { [key: string]: boolean | undefined; }; mask: { [key: string]: boolean | undefined; }; mass: number; shape: "capsule"; }; cameraMaxPitch: number; cameraMinPitch: number; cameraPitch: number; jumpSpeed: number; prediction: "own-body"; runSpeed: number; scheme: "third-person"; walkSpeed: number; }; } | Validated course collision and mover data. |
gameplay.characters | string[] | - |
gameplay.checkpoints | { axis: "z"; direction: "decreasing"; fallY: number; lobbyRespawn: "seat-start"; maxAbsX: number; minY: number; points: number[][]; resetKnock: boolean; thresholds: number[]; } | - |
gameplay.checkpoints.axis | "z" | - |
gameplay.checkpoints.direction | "decreasing" | - |
gameplay.checkpoints.fallY | number | - |
gameplay.checkpoints.lobbyRespawn | "seat-start" | - |
gameplay.checkpoints.maxAbsX | number | - |
gameplay.checkpoints.minY | number | - |
gameplay.checkpoints.points | number[][] | - |
gameplay.checkpoints.resetKnock | boolean | - |
gameplay.checkpoints.thresholds | number[] | - |
gameplay.contact | { carryTolerance: number; foot: number; } | - |
gameplay.contact.carryTolerance | number | - |
gameplay.contact.foot | number | - |
gameplay.floors | number[][] | - |
gameplay.knock | { cooldown: number; duration: number; margin: number; speed: number; } | - |
gameplay.knock.cooldown | number | - |
gameplay.knock.duration | number | - |
gameplay.knock.margin | number | - |
gameplay.knock.speed | number | - |
gameplay.match | { afterFirstSeconds: number; cardSeconds: number; countdownSeconds: number; lateJoin: "spectate-after-loading"; limitSeconds: number; loadingSeconds: number; minPlayers: number; resultsSeconds: number; soloMinPlayers: number; spectatorSpawnZ: number; start: "all-ready"; } | - |
gameplay.match.afterFirstSeconds | number | - |
gameplay.match.cardSeconds | number | - |
gameplay.match.countdownSeconds | number | - |
gameplay.match.lateJoin | "spectate-after-loading" | - |
gameplay.match.limitSeconds | number | - |
gameplay.match.loadingSeconds | number | - |
gameplay.match.minPlayers | number | - |
gameplay.match.resultsSeconds | number | - |
gameplay.match.soloMinPlayers | number | - |
gameplay.match.spectatorSpawnZ | number | - |
gameplay.match.start | "all-ready" | - |
gameplay.movers | object[] | - |
gameplay.placing | { at: number; axis: "z"; direction: "decreasing"; freezeFinishers: boolean; maxAbsX: number; maxY: number; minY: number; requiresAllCheckpoints: false; tieBreak: "seat"; } | - |
gameplay.placing.at | number | - |
gameplay.placing.axis | "z" | - |
gameplay.placing.direction | "decreasing" | - |
gameplay.placing.freezeFinishers | boolean | - |
gameplay.placing.maxAbsX | number | - |
gameplay.placing.maxY | number | - |
gameplay.placing.minY | number | - |
gameplay.placing.requiresAllCheckpoints | false | - |
gameplay.placing.tieBreak | "seat" | - |
gameplay.spawns | number[][] | - |
gameplay.walk | { body: { dims: number[]; flags: { asleep: boolean | undefined; ccd: boolean | undefined; lockRotation: boolean | undefined; noSleep: boolean | undefined; reportContacts: boolean | undefined; reportStay: boolean | undefined; sensor: boolean | undefined; }; kind: "character"; layer: { [key: string]: boolean | undefined; }; mask: { [key: string]: boolean | undefined; }; mass: number; shape: "capsule"; }; cameraMaxPitch: number; cameraMinPitch: number; cameraPitch: number; jumpSpeed: number; prediction: "own-body"; runSpeed: number; scheme: "third-person"; walkSpeed: number; } | - |
gameplay.walk.body | { dims: number[]; flags: { asleep: boolean | undefined; ccd: boolean | undefined; lockRotation: boolean | undefined; noSleep: boolean | undefined; reportContacts: boolean | undefined; reportStay: boolean | undefined; sensor: boolean | undefined; }; kind: "character"; layer: { [key: string]: boolean | undefined; }; mask: { [key: string]: boolean | undefined; }; mass: number; shape: "capsule"; } | - |
gameplay.walk.body.dims | number[] | - |
gameplay.walk.body.flags | { asleep: boolean | undefined; ccd: boolean | undefined; lockRotation: boolean | undefined; noSleep: boolean | undefined; reportContacts: boolean | undefined; reportStay: boolean | undefined; sensor: boolean | undefined; } | - |
gameplay.walk.body.flags.asleep | boolean | undefined | - |
gameplay.walk.body.flags.ccd | boolean | undefined | - |
gameplay.walk.body.flags.lockRotation | boolean | undefined | - |
gameplay.walk.body.flags.noSleep | boolean | undefined | - |
gameplay.walk.body.flags.reportContacts | boolean | undefined | - |
gameplay.walk.body.flags.reportStay | boolean | undefined | - |
gameplay.walk.body.flags.sensor | boolean | undefined | - |
gameplay.walk.body.kind | "character" | - |
gameplay.walk.body.layer | { [key: string]: boolean | undefined; } | - |
gameplay.walk.body.mask | { [key: string]: boolean | undefined; } | - |
gameplay.walk.body.mass | number | - |
gameplay.walk.body.shape | "capsule" | - |
gameplay.walk.cameraMaxPitch | number | - |
gameplay.walk.cameraMinPitch | number | - |
gameplay.walk.cameraPitch | number | - |
gameplay.walk.jumpSpeed | number | - |
gameplay.walk.prediction | "own-body" | - |
gameplay.walk.runSpeed | number | - |
gameplay.walk.scheme | "third-person" | - |
gameplay.walk.walkSpeed | number | - |
options | { arrivalMs: number; contactDiscs: boolean; names: boolean; standInPalette: "race"; } | Validated player presentation settings. |
options.arrivalMs | number | - |
options.contactDiscs | boolean | - |
options.names | boolean | - |
options.standInPalette | "race" | - |
mount | HTMLElement | Caller-owned overlay container. |
now | () => number | Monotonic clock in milliseconds. |
Returns
Idempotent cleanup of labels, tints and discs.
() => void
Example
ts
console.log(typeof installPlayerVisuals);loadingModel()
ts
function loadingModel(model): object;Keep byte progress and authoritative round loading as distinct sources.
Parameters
| Parameter | Type | Description |
|---|---|---|
model | LoadingModel | Loading source, stage, outcome and optional byte counters. |
Returns
object
Loading state with normalized byte progress when available.
failed
ts
failed: boolean;loaded?
ts
optional loaded?: number;progress
ts
progress: number | undefined;ready
ts
ready: boolean;source
ts
source: "character" | "bundle" | "round" | "engine";stage
ts
stage: string;total?
ts
optional total?: number;matchView()
ts
function matchView(
model,
settings,
theme?
): object;Derive visible match text independently of the drawing implementation.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
model | MatchModel | undefined | Latest authority snapshot. |
settings | { capacity: number; countdown: { cardSeconds: number; from: number; goSeconds: number; instruction: string; }; labels: { lobby: string; }; results: { missingPlace: string; returnLabel: string; sort: "place"; spectator: string; }; source: string; type: "match"; version: 1 | undefined; } | undefined | Authored match labels and timing. |
settings.capacity | number | seats | - |
settings.countdown | { cardSeconds: number; from: number; goSeconds: number; instruction: string; } | ... | - |
settings.countdown.cardSeconds | number | seconds | - |
settings.countdown.from | number | ... | - |
settings.countdown.goSeconds | number | seconds | - |
settings.countdown.instruction | string | string | - |
settings.labels | { lobby: string; } | ... | - |
settings.labels.lobby | string | string | - |
settings.results | { missingPlace: string; returnLabel: string; sort: "place"; spectator: string; } | ... | - |
settings.results.missingPlace | string | string | - |
settings.results.returnLabel | string | string | - |
settings.results.sort | "place" | ... | - |
settings.results.spectator | string | string | - |
settings.source | string | id | - |
settings.type | "match" | ... | - |
settings.version | 1 | undefined | ... | - |
theme | "gameable" | "raceCandy" | 'gameable' | Named presentation preset for reference text and roster layout. |
Returns
object
Text rows and a countdown/result banner.
banner
ts
banner: string;roster
ts
roster: string[];rows
ts
rows: string[];openCharacterScreen()
ts
function openCharacterScreen(options): Promise<CharacterChoice>;Replaceable character drawing; abort settles the choice and ignores late catalogs.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | { load?: () => Promise<MyCharactersResult>; mount: HTMLElement; openStudio?: () => void; overlay?: boolean; previous?: string; settings: { allowDefault: boolean; allowPaste: boolean; changePolicy: "lobby-unready-swap"; endpoint: string; storageKey: string; studio: string; }; signal?: AbortSignal; } | Validated configuration and caller-owned host callbacks. |
options.load? | () => Promise<MyCharactersResult> | Open a replaceable catalog or room-list transport. |
options.mount | HTMLElement | Caller-owned screen container. |
options.openStudio? | () => void | Delegate studio navigation to the embedding page. |
options.overlay? | boolean | Allow cancel and Escape while retaining the previous choice. |
options.previous? | string | Previously selected canonical character source. |
options.settings | { allowDefault: boolean; allowPaste: boolean; changePolicy: "lobby-unready-swap"; endpoint: string; storageKey: string; studio: string; } | Validated presentation settings. |
options.settings.allowDefault | boolean | - |
options.settings.allowPaste | boolean | - |
options.settings.changePolicy | "lobby-unready-swap" | - |
options.settings.endpoint | string | - |
options.settings.storageKey | string | - |
options.settings.studio | string | - |
options.signal? | AbortSignal | Cancel the picker and settle its pending choice. |
Returns
Promise<CharacterChoice>
The confirmed choice, or cancellation after dismissal or abort.
parseSettings()
ts
function parseSettings(value, assetIds?): PlayerSettings;Validate settings before allocating host resources. Returns an independent JSON data tree.
Parameters
| Parameter | Type | Description |
|---|---|---|
value | unknown | Untrusted settings JSON. |
assetIds? | readonly string[] | Available manifest IDs, when assets have been loaded. |
Returns
A validated independent settings tree.
Example
ts
const settings = parseSettings({ features: {}, world: {}, physics: {}, maxPlayers: 1, sendHz: 20 });
console.log(settings.maxPlayers);roomCode()
ts
function roomCode(value, settings): string | undefined;Normalize only valid room codes, using the authored limits.
Parameters
| Parameter | Type | Description |
|---|---|---|
value | string | User-entered room code. |
settings | { code: { max: number; min: number; uppercase: true; }; labels: { new: string; quick: string; solo: string; }; modes: ("solo" | "join" | "new" | "quick")[]; title: string; } | Validated presentation settings. |
settings.code | { max: number; min: number; uppercase: true; } | - |
settings.code.max | number | - |
settings.code.min | number | - |
settings.code.uppercase | true | - |
settings.labels | { new: string; quick: string; solo: string; } | - |
settings.labels.new | string | - |
settings.labels.quick | string | - |
settings.labels.solo | string | - |
settings.modes | ("solo" | "join" | "new" | "quick")[] | - |
settings.title | string | - |
Returns
string | undefined
The normalized valid code, or undefined.
roomsModel()
ts
function roomsModel(
rooms,
version,
settings
): object[];Project only rooms matching the immutable session version.
Parameters
| Parameter | Type | Description |
|---|---|---|
rooms | readonly PublicRoom[] | Live public room metadata. |
version | string | Pinned game version. |
settings | { activeLabel: string; activePhases: ("lobby" | "loading" | "countdown" | "racing" | "results")[]; idleLabel: string; public: boolean; } | Validated presentation settings. |
settings.activeLabel | string | - |
settings.activePhases | ("lobby" | "loading" | "countdown" | "racing" | "results")[] | - |
settings.idleLabel | string | - |
settings.public | boolean | - |
Returns
Sorted rows from only the pinned game version.
runSessions()
ts
function runSessions<T>(options): Promise<void>;Serialize menu, boot and complete cleanup; a rejoin retains the last intent.
Type Parameters
| Type Parameter |
|---|
T |
Parameters
| Parameter | Type | Description |
|---|---|---|
options | { initial?: T; boot: Promise<"stop" | "menu" | "rejoin">; choose: Promise<T | undefined>; failed: Promise<"stop" | "menu">; } | Validated configuration and caller-owned host callbacks. |
options.initial? | T | Direct-link intent, used before showing the menu. |
options.boot | Run one session and register resources as they are acquired. | |
options.choose | Deliver the selected session intent, or end the loop with undefined. | |
options.failed | Handle a failed boot after its cleanup has finished. |
Returns
Promise<void>