Wire Protocol & Catalog
A compact binary stream a client decodes from a catalog it is sent, not from the server's types.
Status: โ Implemented ยท Visibility: Public ยท Level: ๐ฃ Advanced ยท Category: Subscriptions
๐ฏ What it solves
Replication bandwidth is the product's ceiling, and clients live in other languages and ship on other schedules. The wire must be dense, self-describing, versioned independently of the server's code, and exact across languages.
โ๏ธ How it works (in brief)
Messages โ one WebSocket binary message, or u32 len | message on TCP after a TYP2 preamble; the first byte is the type:
| Message | Direction | Carries |
|---|---|---|
HELLO |
client โ server | version, capabilities, kind, token (โค 8 KiB), known catalog hash, payload (โค 256 B) โ within 5 s |
WELCOME |
server โ client | granted capabilities, session id, tick, tick period, catalog hash, the catalog (omitted when the client already has it) |
TICK |
server โ client | tick number, flags (VIEW_COMPLETE, RESET, OVERLOAD, PERIOD), blocks |
COMMANDS |
client โ server | client tick, then typed commands with a u16 sequence each |
PING / PONG |
both | client clock and last applied tick (mandatory, 4 Hz) / server tick |
KICK / BYE |
server โ client / client โ server | a close code and reason / a clean leave |
Blocks inside a TICK, each length-prefixed so an unknown one is skipped: ENTITIES (one archetype's enters, updates, leaves),
EVENTS, SELF, AGG, STATS, DEBUG, ACKS, EXT.
The catalog is canonical JSON โ archetypes with their position and fields (codec, group, section), commands with their rate and roles, events, metrics, limits, the tick rate โ sorted so the same declarations in any order produce the same bytes and the same hash. Built-in commands, events and metrics sit at reserved indices, so enabling one never moves an application index.
Codecs โ integers, varu/vari, f16/f32, quantizers over a range, normalized values, angles, packed bits (โค 24 in a section's
pack), positions (24 bits per axis over the world bounds), velocities (displacement per tick in 1/16 position quanta), entity references
(netIds), text, blobs, lists, quaternions, tick offsets. The arithmetic is specified exactly and implemented identically in C# and
TypeScript.
Close codes:
| Code | Meaning | SDK reconnects |
|---|---|---|
| 1000 / 1001 | normal / server going away | app decides / yes |
| 1002 / 1007 / 1009 | protocol error / malformed payload / message too big | no |
| 1008 | policy violation: sustained refused commands | yes, backoff |
| 1011 | internal error (a flush failure closes every session) | yes |
| 1013 | try later: server full, or lagging | yes, backoff |
| 4001 / 4002 / 4003 | no acknowledgement / HELLO timeout / admission rejected |
yes / yes / no |
| 4100โ4999 | application (Kick, Admission.Reject) |
app-declared |
โ ๏ธ Guarantees & limits
- Versioned:
typhon.2+ a minor + capability bits; a client ignores unknown blocks and unknown fixed-size fields. - No 64-bit integer on the wire implicitly; strings and blobs are length-capped by the catalog.
- Records are absolute: a frame never depends on a frame the client might have missed.
resumeTokenis always 0 until resume is built.
๐งช Tests
- GoldenTickTests ยท GoldenRefusalTests โ committed golden vectors, shared with the TypeScript SDK
- CatalogBuilderTests โ the emitted catalog is valid and canonical
๐ Related
- Concept: Replication catalog
- Client SDKs