Guide4 min read4 sections

Canonical remote actors

docs/REMOTE_ACTORS.mdSource updated 2026-10-24
Markdown
On this page 4 sections

The development player now projects remote travelers from Simulation.entities, the same entity store used by the local motor and authored world. The worker no longer builds presentation actors directly from RoomClient.state.peers. The admitted roster still supplies transport state; it is reconciled through an atomic ECS transaction before publication.

#Identity and lifetime

Each admitted remote connection has an entity ID remote.<peer>.<motion-stream>. Its components are Transform, PlaceMembership, InputOwner and the optional RemoteActor contract. RemoteActor@2 owns display name, color, peer ID, relay motion stamp and optional validated motor-relative locomotion. Version 1 migrates by preserving the prior fields without inventing motion state. Root transforms contain the latest admitted position and yaw, not interpolated rendering positions. The existing renderer interpolates those samples and blends the game-owned rig. This does not move smoothing or cosmetic gait into simulation truth.

The local peer is excluded because player.local already represents that motor. A new motion stream destroys the old remote entity and creates a new one, invalidating outstanding handles. Departure or loss of room connection removes admitted remote entities. A fresh connected baseline recreates the current roster. Peers in another place remain canonical entities but do not render in the current place. Interest filtering and remote collision bodies remain future work.

The shared schema reader bounds rosters at eight entries, rejects malformed/duplicate identities, unknown places, invalid coordinates, names, colors and motion stamps, and owns accepted input. The existing network API re-exports this reader. Reconciliation validates the entire roster and local admission identity before mutation. Within one stream, duplicate or older sequences do not refresh canonical motion. A newer sequence with a nonadvancing relay clock rejects the transaction. Roster updates are not local player input or permission to claim authority over remote physics.

#Invariants and projection

A reserved namespace and store invariant require complete actor dependencies, matching owner/peer/stream identities, one connection per peer, unit scale and yaw-only transforms. Other built-in components cannot be attached to these session roots yet. Local hierarchy dependencies on a remote root are rejected: session attachment cleanup must be designed before equipment or carried bodies can use that path.

The incremental ECS projection reads affected actor rows, filters by current place and emits format-6 actor records when locomotion is present, retaining format 5 for legacy stamped poses. Nameplates keep the stable peer ID; motion stream changes still reset renderer history. Ordinary local motor updates do not rescan every world entity for remote actors. Failed projection leaves its accepted rows, actor cache and cursor unchanged. Legacy explicitly supplied presentation actors remain supported for existing synthetic fixtures; they are no longer used by the production worker.

This is a kinematic admitted-pose view. It does not add trusted server simulation, generated packet codecs, full remote motor state, canonical replicated animation clips, actor equipment, per-place authority or gameplay collisions with peers. Those remain full-plan work.

#Checkpoints and reconnect

RemoteActor is an optional ephemeral contract alongside the seventeen existing built-in contracts. The live simulation manifest therefore has eighteen contracts. Native local checkpoint capture omits remote connection rows and that optional schema. No saved entity may parent to a remote row, preventing dangling dependencies when the session view is omitted.

This preserves the existing checkpoint boundary: remote room peers were not part of local saves before this integration. Native profile 5, the seventeen-contract durable manifest, replay fixture hashes, local save format 2 and room disk format 1 stay unchanged. Restoring a checkpoint cannot resurrect a remote player; the room must admit a fresh roster. A headless comparison checks complete checkpoint equality before and after adding remote peers, plus re-admission after restore. This policy applies to local native checkpoints; a future authoritative room snapshot has its own session/ownership requirements.

#Verification

Headless cases exercise owned input, no-op heartbeats, stale samples, atomic rejection, reconnect generation invalidation, namespace/attachment invariants, exact checkpoint preservation, current-place projection and fresh-baseline equivalence. The multiplayer browser scenario verifies that the canonical entity count increases by one when a real peer arrives and returns to baseline after departure, while still checking visible motion and nameplate removal. Shared interactions, recovery and actual pose-packet interruption use the same path.

End of Remote actors