Networking
TL;DR: From a WASM script you can send raw byte payloads to specific players (or broadcast) via CVR_Networking_SendMessage with one of three delivery modes. CVR batches your sends on the underlying DarkRift transport. Use WillMessageBeDropped before enqueueing large messages and back off when NetworkCloggedPercentage stays high.
Delivery modes
Section titled “Delivery modes”Source: CVR-GameFiles/WasmScripting/SendType.cs.
public enum SendType { Unreliable = 0, // fire and forget, possibly dropped, possibly reordered UnreliableSequenced = 1, // possibly dropped, but never reordered (old messages discarded) Reliable = 2, // guaranteed delivery and order; higher latency if packets are lost}Pick Unreliable for frequent state ticks where only the latest matters (positions). UnreliableSequenced for streams where gaps are fine but order is not (telemetry with sequence numbers). Reliable for discrete events (someone completed a lap, a button was pressed).
Host binding signature (NetworkingBindings.cs):
CVR_Networking_SendMessage( i32 messagePtr, i32 messageLength, i32 playerIdsPtr, i32 playerIdsLength, // array of i16 player IDs i32 sendType)message— the raw bytes to ship. Host copies out of guest linear memory immediately, so you can reuse the buffer after the call.playerIds— array of 16-bit player IDs. Pass length 0 to broadcast to all other players in the instance.sendType— integer value ofSendTypeabove.
The host-side routing lives in CVR-GameFiles/WasmScripting/WasmNetworkManager.cs. Messages are buffered per-VM (Sender struct) and flushed on DarkRift’s tick.
Receive
Section titled “Receive”Incoming messages arrive as a game-level event. The exact guest-side entry point depends on what the CCK WasmModule exposes; at the host boundary the dispatch uses the scripting_call_trigger_script_event_object mechanism with a wrapped message object.
Practically: define a method on your behaviour following the CCK WasmModule’s documented contract (typically a public method receiving a message object that wraps sender + byte payload). Consult your CCKWasmModule version — the private module currently at version 0.0.65 owns the exact API surface for parsing messages.
Probes
Section titled “Probes”| Binding | Signature | Purpose |
|---|---|---|
CVR_Networking_WillMessageBeDropped | (i32 size) -> i32 | Non-zero if queuedBytes + size > 65536 (MaxBytesQueued). Check before sending large Unreliable* payloads. |
CVR_Networking_NetworkCloggedPercentage | () -> f32 | Returns bytesSent / 16384f — a fraction of the 16 KB spike budget (MaxBytesSendSpike). Not clamped: it may exceed 1.0 if the sustained budget drain hasn’t caught up. Back off writes when persistently above ~0.7. |
CVR_Networking_GetInstanceOwner | () -> i64 | Wrapped handle for the current instance owner Player. Useful for authoritative-owner patterns. |
CVR_Networking_GetPing | () -> i32 | NetworkManager.Instance.GameNetworkPing in ms. |
CVR_Networking_GetServerStartTime | () -> i64 | Unix timestamp (ms) the game server started. CCK source only — not in the shipped decompile yet. |
CVR_Networking_GetServerUptime | () -> i64 | Game server uptime in ms. CCK source only. |
Addressing
Section titled “Addressing”Players are referenced by 16-bit (short) instance-local IDs. Enumerate them via CVR_Player_GetAllPlayers / CVR_Player_GetRemotePlayers (returning wrapped Player handles). Map each Player handle through the CCK WasmModule’s shim to get the short network ID for the playerIds array.
Broadcasts
Section titled “Broadcasts”Passing an empty playerIds slice broadcasts to everyone in the instance except the sender. For “send to me too” patterns, invoke the handler directly on the local side in addition to sending.
Authority patterns
Section titled “Authority patterns”CVR instances have a notional instance owner (the player who created the instance, or the one who inherited on disconnect). Common networking patterns:
- Owner-only writes — each client checks
CVR_Networking_GetInstanceOwneragainst its own player; only the owner sends authoritative updates. Subscribe toOnInstanceOwnerChangeto handle handoff. - Leaderless — every client sends its own state. Cheap but racey; use
UnreliableSequencedand include timestamps. - RPC over reliable — send discrete events reliably; each client integrates them into local state.
Size budget
Section titled “Size budget”Concrete constants (CVR-GameFiles/WasmScripting/WasmNetworkManager.cs):
| Name | Value | Semantics |
|---|---|---|
MaxBytesPerSecond | 4096 | Sustained per-VM send rate, drained per second of wall clock. |
MaxBytesSendSpike | 16384 | In-flight cap. The flush loop refuses to dispatch a message whose size would push the running total above this. |
MaxBytesQueued | 65536 | Upper bound on bytes queued but not yet flushed. WillMessageBeDropped(size) compares queuedBytes + size to this. |
Any outbound message larger than MaxBytesSendSpike (16 KB incl. its 22+playerIds.Length*4+"CVR.TN:1.0.0".Length*2 header) is dropped silently by WasmNetworkManager.SendMessage without touching the queue. Chunk payloads into pieces below that cap.
Pragmatic rules of thumb:
- Small messages (< ~200 bytes) — send freely.
- Medium messages (~200 bytes – 1 KB) — call
WillMessageBeDropped(size)first when the queue may already be busy. - Large payloads — stay well under 16 KB per call. Split larger payloads across frames and stitch them on the receiver with a tag byte + sequence number.
Permission model
Section titled “Permission model”NetworkingBindings.cs does not call CheckAccess explicitly on any of these functions, so they are reachable from any ObjectContext (Avatar, Prop, World). In practice networking from an avatar script is still per-instance and won’t cross to other worlds or players outside the instance — CVR’s networking isolation is enforced at the transport layer.
World-permissioned external HTTP is entirely separate — see World Permissions.
Source
Section titled “Source”CVR-GameFiles/WasmScripting/NetworkingBindings.cs—CVR_Networking_*host bindings.CVR-GameFiles/WasmScripting/WasmNetworkManager.cs— per-VMSenderqueue, budget constants,SendMessage,OnReceiveMessage,FlushMessagesruns in theInitializationPlayerLoopSystem.CVR-GameFiles/WasmScripting/SendType.cs— three-value enum.
Related
Section titled “Related”- World Permissions — HTTP allowed-domains flag.
- Events —
OnInstanceOwnerChangehook for authority handoff. - Limits — epoch deadline considerations when composing messages.