Games client plus its
publisher/subscription handles from there.
publishState ↔ publish_state) and in keyword
vs options style. Both use the same MoQT substrate, so a TS player and a Python
authority interoperate on the wire.
Games — the client
Use one Games instance per (room, player), or per (room, server) for the
authority. The client opens the session lazily on the first publish or
subscribe. It reuses the session for every channel.
- TypeScript
- Python
string
required
Bearer token for the relay session, scoped to
(tenant, room, player?).string
required
The room that every channel binds to. All three channels live under
game/<roomId>/….string
Player identity. Omit it for the authoritative server. It is required for
publishInput and publishEvent. It becomes the from header on every frame.string
Relay hostname. Defaults to the platform relay.
(state, reason?) => void
Connection-state callback.
state is a ConnectionState
(0 Connecting · 1 Connected · 2 Reconnecting · 3 Closed · 4 Failed).WebTransportFactory
Inject a custom WebTransport factory (for a Node polyfill or tests). Optional.
Namespace accessors
Use these read-only helpers to inspect the raw tracks or to interoperate with them:state — server → all
publishState(args?) → StatePublisher
Authority-only. Opens the state track and returns a StatePublisher. State
frames carry no from header, because the source is always the authority.
They use the datagram lane at priority 100.
- TypeScript
- Python
number
Tick-rate hint for the relay’s admission control and the recorder. It does
not pace your writes. You drive the loop. Optional.
subscribeState(cb) → GamesSubscription
Player-side. Subscribes to the authority’s state. It calls your callback with
each snapshot’s raw bytes. Returns a GamesSubscription that you can close().
StatePublisher
void
Publish one state snapshot.
priority defaults to 100. The SDK stamps
timestamps from a monotonic clock.void
Close the state track.
input — each player → server
publishInput() → FromPublisher
Player-only. Returns a FromPublisher that prefixes every frame with this
client’s playerId. Input uses the datagram lane at priority 100. The call
throws if the client has no playerId.
subscribeInputs(cb) → GamesSubscription
Authority-side. Receives every player’s input on one callback. The SDK
decodes the from header, so you get (playerId, bytes) for each frame. You
do not manage a subscription for each player.
The SDK silently drops malformed input frames (bad
from header). It does not
throw into your callback, so one bad packet cannot stall the tick loop. The
relay logs the dropped frames as wire-format rejects.event — any → any (reliable)
publishEvent(args) → FromPublisher
Either role. Opens a reliable, ordered event channel and returns a
FromPublisher. Events use a subgroup stream at priority 50. Delivery
is guaranteed and in order. The SDK stamps the server’s events with from = "_authority". A player’s events carry the player’s id.
- TypeScript
- Python
string
required
Event channel name, for example
chat, ready, or rpc.use_item. Each
channel is its own track under game/<room>/event/<channel>.subscribeEvents(args, cb) → GamesSubscription
Either role. Subscribes to one event channel. The callback gets the decoded
sender id and the raw event bytes.
FromPublisher
Both publishInput and publishEvent return this handle. It prefixes every
write with the caller’s from id.
void
Publish one frame.
priority defaults to the channel default (100 for input,
50 for events). The SDK adds the from header for you.void
Close the underlying track.
Handles & lifecycle
GamesSubscription
Every subscribe* method returns this handle. It has read-only ns / name
plus:
void
Stop receiving on this channel.
Games.close()
close(), the next publish or subscribe
opens a fresh session.
Connection events
There is no separate event emitter. TheonState / on_state callback that
you pass to the constructor delivers the connection lifecycle. The underlying
session auto-reconnects with capped backoff. It replays every publish
and subscribe on reconnect, so your channels reattach without code on your
side.
Wire helpers (advanced)
The SDK exports thefrom-header codec. Use it for interop tests, or for
callers that bypass the high-level client but stay wire-compatible:
Other languages
The Go and Rust SDKs expose the same(room, player) model and the same three
channels over the shared MoqtClient. Method names use each language’s
idiomatic case. Package coordinates: github.com/clutchcall/clutchcall-sdk/go, clutchcall. Unity
games use the Netcode transport drop-in. They
do not call this client directly.
