Networking
vgai has no networking wrapper: client code calls Colyseus directly. vgai owns no
replication layer of its own — Colyseus is the replication layer — so wrapping it would just
be a pass-through the editor never exploited. @colyseus/sdk is dynamically imported
(await import('@colyseus/sdk')) so single-player game bundles don’t pull in multiplayer code.
Connecting: typed joinOrCreate<T>
Section titled “Connecting: typed joinOrCreate<T>”const { Client, Callbacks } = await import('@colyseus/sdk');const client = new Client(serverUrl);const room = await client.joinOrCreate<ArenaRoomState>('arena_room', joinOptions);ArenaRoomState types room.state and, through it, every Callbacks-API field below. The
server’s Schema classes use @colyseus/schema’s legacy decorators (a server-only tsconfig
flag) — the client shouldn’t import them as values. Instead, mirror the server schema’s SHAPE
as an ambient, type-only declaration (ships zero runtime code):
import type { MapSchema, Schema } from '@colyseus/schema';
declare class ArenaPlayerSchema extends Schema { sessionId: string; x: number; y: number; z: number; score: number;}declare class ArenaRoomState extends Schema { players: MapSchema<ArenaPlayerSchema>; phase: string;}third-person-arena/network.ts is the worked reference for this pattern.
The Callbacks API
Section titled “The Callbacks API”Callbacks.get(room) returns the Colyseus v0.17 Callbacks API:
onAdd(collection, handler)— fires for existing AND future entries in a keyed collection (e.g.players).onRemove(collection, handler)— fires when an entry leaves.onChange(item, handler)— fires when any field of a replicated item changes.listen(property, handler)— per-field listener, for root-level (non-collection) fields likephaseor a timer.bindTo(fromSchemaInstance, toPlainObject, properties?)— mirrors named fields onto a plain object immediately and on every change, so you don’t hand-write a per-field copy loop when you just need a snapshot (e.g. for a React HUD).
Server-authoritative pattern
Section titled “Server-authoritative pattern”The typical shape: clients send() input up; the server room mutates authoritative
@colyseus/schema state; that state syncs down and your onAdd / onChange / listen
handlers update the local scene. Defining a room and connecting a client is walked through in
the Multiplayer guide.
Editor network inspector
Section titled “Editor network inspector”The editor never imports Colyseus. It asks a mounted game’s NetworkingAdapter
(SystemAdapters.networking) for connection state, room info, and replication stats —
createColyseusNetworkingAdapter builds the first-party implementation from accessor
callbacks over your game’s live network client. See third-person-arena/network-adapter.ts
for the worked example, and the play panel’s network inspector section.
See also
Section titled “See also”- Multiplayer — add a room, connect a client, the shipped examples.
- Entities & components — applying synced state to entities.