Network transport
Usage guide of net.transport: the session layer under every net.* sync kit (WebSocket, WebRTC, direct IP), its settings and defaults, the session service, events, variables and the errors a bad config gives.
The network transport of your game (net.transport) #
The connection layer under every multiplayer kit: how a client reaches the server, how long a silent link is kept, how a dropped player comes back, how fast a peer may talk. For the choice of the sync kit and the server program, read the multiplayer guide. Readable offline: gripforge docs net-transport, or the MCP tool gripforge_docs (topic net-transport).
What it is for #
net.transport owns the configuration of the connection and the status shown to the player. The sync kits (net.state, net.claim, net.authoritative, net.rollback, net.async) ask it for a session and never open a socket themselves. It checks your settings against the table of the network core, fills in the defaults, and hands them to that core: the same Rust core in the browser, in Godot, Unity, Unreal and in the dedicated server. It draws nothing. A game has exactly one transport kit; installing any sync kit brings it in.
Turn it on #
gripforge_gamekit_install { project_id: "gkp_…", id: "net.transport" }
gripforge_gamekit_configure { project_id: "gkp_…", id: "net.transport",
config: { "app": "my-game@1", "url": "wss://play.example.com/gfnet" } }
Write only the keys that differ from the defaults. gripforge kit api net.transport lists every key with its type and bounds.
First example #
<!-- test: kits/game_engine/host/tests/net_kits.rs::a_bad_transport_option_is_named_and_leaves_networking_off --> A wrong setting is named by its path, and networking stays off instead of running half configured:
{ "heartbeatMs": 5, "nope": true, "rate": { "burst": 0.5 } }
The log gets config.transport.heartbeatMs: expected >= 100, config.transport.nope: unknown property and config.transport.rate.burst: expected integer. The service still answers its defaults, and open fails with the same message.
Settings and defaults #
| Setting | Default | Meaning |
|---|---|---|
transport | auto | auto, websocket, webrtc, tcp_udp or enet. auto is the WebSocket on the web (WebRTC when a room is set) |
role | client | host (web only): the page runs the server and accepts the WebRTC clients of room |
url | "" | WebSocket address of the server; empty means the host of the page, path /gfnet |
host, port, udpPort, path | 127.0.0.1, 27015, 0, /gfnet | address of the server for native clients; udpPort 0 is announced by the server |
signalUrl, room, iceServers | "", "", a public STUN server | WebRTC signalling and relay servers; a production game needs its own TURN server |
app | gripforge-game@1 | application id and build: a client of another build is refused. Bump it when two builds can no longer play together |
name | unset | player name sent in the handshake |
fallback | true | native auto: fall back to the WebSocket bridge when direct IP fails |
maxPeers, maxPeersPerIp | 16, 8 | server capacity, and sessions per remote address (0 = no cap) |
heartbeatMs, timeoutMs, resumeMs | 1000, 5000, 10000 | ping period, silence that loses a link, time a dropped peer keeps its id and slot |
connectTimeoutMs, welcomeTimeoutMs, handshakeMs | 3000, 0 (auto), 5000 | connect, welcome and hello delays |
maxMessageBytes, maxViolations | 65536, 20 | largest message; invalid messages tolerated before a peer is closed |
rate | 120/s, burst 240, 262144 bytes/s | per-peer limits (messagesPerSecond, burst, bytesPerSecond, bytesBurst) |
reconnect | on, 500 to 8000 ms, 10 tries, jitter 0.25 | client backoff (enabled, minMs, maxMs, maxTries, jitter); 0 tries is unlimited |
relay | limits of the engine bridge (maxPayload, and its own rate) | |
eventQueueMax | 4096 | events kept unread before the oldest are dropped |
trustForwardedFor | false | read the client address from X-Forwarded-For; only behind a proxy you run |
Constraints: heartbeatMs must be below timeoutMs; reconnect.minMs at most reconnect.maxMs; sendSoftBufferBytes at most sendHardBufferBytes; relay.maxPayload at most maxMessageBytes. Keys marked hot in gripforge kit api net.transport can change on a running session; the others apply at the next connection. The remaining keys tune the sockets of a server (listenHost, listenWebSocket, listenTcp, sniffMs, the pending-connection caps, the send buffers) and the direct-IP client (udpHelloMs, udpHelloTries, udpKeepaliveMs).
Services, events, variables #
net.transport(service):config()the settings with their defaults,app()the application id of the handshake,open(model, sync, extra?)a session for a sync kit,host(model, sync, physics?)andhosted()the in-page server (role: "host"),listen(callback)andunlisten(id)its events.net.session(service): the session the sync kits plug into.net.connected(event):{ id, resumed, transport }, the welcome arrived.net.disconnected(event):{ reason, final };finalwhen no reconnection follows.net.peer(event):{ id, on }, another peer joined or left.net.refused(event):{ code, msg }, the handshake was refused (version,app, full,mods…).net.overflow(event):{ dropped, total, cap }, events were dropped pasteventQueueMax.net.status,net.rtt,net.peers(variables): connection state (idle,connecting,connected,reconnecting,closed), smoothed ping in ms, players online. Bind them to a HUD label.
Hooks and modding #
The kit declares no hook and no setting is open to mods: two machines of a match must agree on addresses, limits and rates. With mods applied, the application id sent in the handshake is app followed by ~mods.<fingerprint>, so a peer running other mods is refused with net.refused { code: "mods" }.
Engines #
The web uses WebSocket and WebRTC; Godot, Unity and Unreal use direct IP (tcp_udp; enet is treated as tcp_udp) with the WebSocket bridge as a fallback. role: "host" is available on the web only.
When it does not do what you expect #
- Networking never starts and the log names
config.transport.<key>: that setting is unknown or out of bounds; fix it. openorhostfails with a message aboutnet.core: the host does not provide the network core, so no session can open.net.refusedwith codeapp: client and server have differentappvalues; withmods: their mods differ.role: "host"withoutsignalUrlandroomaccepts only the local player (a warning is logged).hostsays the page already hosts another model: one in-page server per page.per-connection overrides require role client:openwas given transport overrides whileroleishost.
Limits #
No game rules, no matchmaking and no authentication: rooms, lobbies and logins belong to other kits. Rate limits are per peer, not per account. Direct IP needs an open port; the WebSocket bridge works through web proxies.
Versions #
Kit 1.3.1, protocol gfnet/1. 1.3 added the mods fingerprint to the handshake; 1.3.1 lets the caller of host choose the WebRTC room.