Table of Contents

Client SDKs

Two clients, one catalog: the browser's and .NET's, both decoding against what the server says rather than its C# types.

Status: โœ… Implemented ยท Visibility: Public ยท Level: ๐Ÿ”ต Core ยท Category: Subscriptions

๐ŸŽฏ What it solves

A client has to decode a compact, quantized, versioned stream, keep a mirror of what its session holds, draw movers smoothly between frames, and send commands in the server's encoding โ€” without being regenerated every time the server's types change.

โš™๏ธ How it works (in brief)

TypeScript (@typhondb/client, src/Typhon.Client.TypeScript, ESM + .d.ts):

  • ReconnectingClient / Connection โ€” the handshake, catalog caching by hash, PING scheduling (PingScheduler), reconnection with backoff per close code.
  • FrameApplier โ€” applies each TICK into a WorldStore: per-archetype ArchetypeStores of typed columns (field(name)), live slots, and per-frame entered/updated/left lists; SelfState, acks, events and AggregateGrids beside them.
  • Clock + evaluateLive(store, renderTick, frac, out) โ€” render time and motion-segment extrapolation, including tick-period changes under overload.
  • CommandQueue (one batch per rendered frame) and RegionSender (ClientRegion footprints, โ‰ค 5 Hz).
  • StreamRecorder / replayStream โ€” record and replay a session.
  • typhon-codegen โ€” compiles a specialised decoder from /typhon/catalog.json for the hot path.

.NET (Typhon.Client):

  • TyphonClient over ws://, wss:// or tcp://: connect, reconnect policy, SendCommandAsync(name, values), a WorldStore with per-archetype columns and SelfState, a Recorder. Built for bots, tools, load tests and integration tests.

๐Ÿ’ป Usage

const client = new ReconnectingClient({
  url: 'wss://play.example.com/ws', kind: 'player', token, caps: Capabilities.Stats,
  handlers: {
    onWelcome: (session) => {
      applier = new FrameApplier(session.plan, { clock });
      queue = new CommandQueue({ plan: session.plan });
    },
    onTick: (message, recvMs) => applier.apply(message, recvMs),
  },
});
await using var bot = new TyphonClient(new ClientOptions
{
    Endpoint = new Uri("tcp://127.0.0.1:9100"),
    Kind = "player",
});
await bot.ConnectAsync();
await bot.SendCommandAsync("MoveTo", new RecordValues
{
    ["X"] = FieldValue.Of(10.0),
    ["Z"] = FieldValue.Of(20.0),
});

โš ๏ธ Guarantees & limits

  • Golden vectors pin the wire: the engine, the .NET client and the TypeScript SDK decode the committed vectors identically, bit for bit.
  • Forward compatible: a client skips blocks and fixed-size fields it does not know (AC-14).
  • Steady state: the TypeScript SDK shows no retained heap growth over a 10-minute replay; with code generation a steady-state frame of 10 k records decodes in โ‰ˆ 0.3 ms on the reference laptop.
  • Packaging: neither SDK is published to a package registry yet (NuGet / npm); use them from the repository.

๐Ÿงช Tests

  • src/Typhon.Client.TypeScript/test โ€” vitest suites: framing, apply, motion, reconnect, codegen, golden streams
  • EngineStreamGoldenTests โ€” the .NET client against the engine's golden stream