v0.6.1 (build 914)

A board is a unit of simulation with its own entities, physics world, networking state, and JavaScript context. The orchestrator manages board lifecycle and presentation. Import the board API as Syncromesh/Board.

Lifecycle #

import * as Board from 'Syncromesh/Board';

const boardId = await Board.create();
await Board.start(boardId, {bootstrap: 'world.js', args: ['region:one']});
// Later, from the orchestrator:
await Board.stop(boardId);
await Board.destroy(boardId);

The bootstrap module exports a default function receiving an argument array. Return promptly after setup. Timers and events drive ongoing work. Do not start, stop, or destroy the current board from its own context; request that operation from the orchestrator.

Attach a view #

import * as Board from 'Syncromesh/Board';
import * as Window from 'Syncromesh/Window';
import * as Camera from 'Syncromesh/Camera';

// Inside the orchestrator bootstrap, without --headless:
const windowId = await Window.window({width: 1280, height: 720, title: 'World'});
const boardId = await Board.create();
await Board.attach(boardId, windowId);
await Camera.setWindow(windowId);
await Board.start(boardId, {bootstrap: 'world.js'});

A window displays entity renderables from attached boards. Creating a window does not attach a board or create any visible entities. The first-simulation example needs render descriptors before it will draw anything.

await Board.detach(boardId) removes the view while the board keeps running. A window can combine multiple attached boards. Each board has one window attachment at a time; attaching it elsewhere moves the attachment. attachOffset applies a presentation offset, not an ownership boundary.

Messages between contexts #

// Orchestrator -> board (synchronous delivery request):
Board.post(boardId, 'player:command', {action: 'move', x: 10, y: 5});

// Board script:
Event.on('player:command', (command) => {
    // Validate the command and apply it to this board's entities.
});
Board.postHost('world:status', {ready: true});

Import Event from Helix/Event. post and postHost synchronously return a boolean indicating whether the message was queued, not whether its handler completed. Payloads cross contexts as JSON. Use them for commands and reports. Network peers use Network messages instead.

API reference #

CallResult / behaviour
Board.current()Synchronous current context board ID; the orchestrator's ID is not a child simulation to populate.
await Board.create()New board ID.
await Board.start(id, {bootstrap, args})Starts the board; returns a boolean.
await Board.stop(id)Stops the child board.
await Board.destroy(id)Removes the child board.
await Board.list()Lists board IDs.
await Board.isRunning(id)Returns whether the board is running.
await Board.attach(id, windowId)Attaches the board to a window.
await Board.attachOffset(id, windowId, {x, y})Attaches with a presentation offset.
await Board.detach(id)Removes its window attachment.
await Board.getWindow(id)Returns its window attachment, if any.
await Board.getWindowAttachments(windowId)Lists the window's board attachments.
await Board.signal(id, eventName)Signals a running board without a payload.
Board.post(id, eventName, payload)Queues a JSON event to a board; synchronous boolean.
Board.postHost(eventName, payload)Queues a JSON event to the orchestrator; synchronous boolean.

Execution rules #

  • Entity IDs and JavaScript state belong to their board. Do not use another board's local entity ID as a handle.
  • Use Entity, Navigation, and simulation entity operations inside child boards.
  • The orchestrator's Simulation module supplies lifecycle controls such as quit; it does not expose spawn.
  • Await runtime operations, but do not hold bootstrap open waiting for simulation or network progress.
  • Use native movement and physics for continuous motion; messages should express commands rather than shuttle every frame's positions.