Configuration Reference
Complete reference for every configurable option in the CarverJS multiplayer system. All options have sensible defaults — you only need to override what you want to change.
import { useMultiplayer, useRoom } from "@carverjs/multiplayer";useMultiplayer Options #
Pass these options to useMultiplayer() to control synchronization behaviour.
const multiplayer = useMultiplayer({
mode: "prediction",
tickRate: 60,
broadcastRate: 20,
keyframeInterval: 60,
quantize: { position: 0.01 },
prediction: { enabled: true },
interpolation: { delay: 100 },
});Top-Level Options #
| Option | Type | Default | Description |
|---|---|---|---|
mode | 'events' | 'snapshot' | 'prediction' | 'snapshot' | Sync strategy. events sends only inputs; snapshot sends full state; prediction adds client-side prediction and reconciliation |
tickRate | number | 60 | Fixed-timestep simulation rate in Hz. Higher = more precise physics but more CPU |
broadcastRate | number | 20 | How often the host sends state updates per second. Independent of tickRate |
keyframeInterval | number | 60 | Number of ticks between full keyframe snapshots. Between keyframes, only deltas are sent |
quantize | QuantizeOptions | — | Reduce floating-point precision to save bandwidth |
deltaThresholds | DeltaThresholds | — | Minimum change required before a field is included in a delta update |
prediction | PredictionOptions | — | Client-side prediction and server reconciliation settings |
interpolation | InterpolationOptions | — | How remote entities are smoothed between updates |
interestManagement | InterestManagementOptions | — | Area-of-interest filtering for large worlds |
debug | DebugOptions | — | Debug overlay and network simulation tools |
onPhysicsStep | (dt: number) => void | — | Callback invoked each physics tick. Required for prediction mode to replay inputs |
QuantizeOptions #
Quantization rounds values to a fixed step size, reducing the number of bits needed on the wire.
| Field | Type | Default | Description |
|---|---|---|---|
position | number | — | Step size for position axes. 0.01 = centimetre precision |
rotation | number | — | Step size for rotation (radians). 0.001 is typically sufficient |
velocity | number | — | Step size for linear/angular velocity |
quantize: {
position: 0.01, // ~1cm accuracy
rotation: 0.001, // ~0.06° accuracy
velocity: 0.05,
}DeltaThresholds #
Only include a field in the delta if it changed by more than the threshold since the last broadcast.
| Field | Type | Default | Description |
|---|---|---|---|
position | number | 0.001 | Minimum positional change (world units) |
rotation | number | 0.001 | Minimum rotational change (radians) |
velocity | number | 0.01 | Minimum velocity change |
deltaThresholds: {
position: 0.001,
rotation: 0.001,
velocity: 0.01,
}PredictionOptions #
Controls client-side prediction and server reconciliation. Only relevant when mode is 'prediction'.
| Field | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Enable client-side prediction |
maxRewindTicks | number | 30 | Maximum number of ticks the client will rewind and replay during reconciliation |
correctionSmoothing | number | 0.2 | Blend factor for correction (0 = instant snap, 1 = no correction). 0.2 gives a smooth visual correction over ~5 frames |
inputBufferSize | number | 60 | Number of past input frames stored for replay during reconciliation |
prediction: {
enabled: true,
maxRewindTicks: 30,
correctionSmoothing: 0.2,
inputBufferSize: 60,
}InterpolationOptions #
Controls how remote (non-local) entities are smoothed between network updates.
| Field | Type | Default | Description |
|---|---|---|---|
delay | number | 100 | Interpolation delay in milliseconds. Higher = smoother but more latency |
maxExtrapolation | number | 200 | Maximum time (ms) to extrapolate beyond the last received state before freezing |
method | 'linear' | 'hermite' | 'linear' | Interpolation curve. Hermite produces smoother motion for accelerating objects |
interpolation: {
delay: 100,
maxExtrapolation: 200,
method: "hermite",
}InterestManagementOptions #
Area-of-interest filtering. Only entities within range of the player are synchronized, dramatically reducing bandwidth in large worlds.
| Field | Type | Default | Description |
|---|---|---|---|
enabled | boolean | false | Enable spatial interest management |
cellSize | number | 50 | Spatial hash cell size in world units |
viewDistance | number | 200 | Maximum distance (world units) at which entities are synced to a client |
hysteresis | number | 20 | Buffer zone to prevent entities flickering in/out at the boundary |
interestManagement: {
enabled: true,
cellSize: 50,
viewDistance: 200,
hysteresis: 20,
}DebugOptions #
Developer tools for visualizing and simulating network conditions.
| Field | Type | Default | Description |
|---|---|---|---|
overlay | boolean | false | Show the on-screen debug overlay with live stats |
simulatedLatencyMs | number | 0 | Artificial one-way latency added to every message (ms) |
simulatedPacketLoss | number | 0 | Fraction of packets to randomly drop (0–1). 0.05 = 5% loss |
logLevel | 'none' | 'error' | 'warn' | 'info' | 'debug' | 'warn' | Console log verbosity |
debug: {
overlay: true,
simulatedLatencyMs: 80,
simulatedPacketLoss: 0.02,
logLevel: "info",
}useRoom Options #
Pass these options to useRoom() to configure the connection and room behaviour.
const room = useRoom({
displayName: "Player1",
password: "secret",
hostMigration: true,
reconnectAttempts: 5,
privacy: "relay",
});| Option | Type | Default | Description |
|---|---|---|---|
transport | CarverTransport | -- | Pass a custom CarverTransport instance to bypass the built-in WebRTCTransport |
password | string | -- | Room password. Joining peers must provide the same value |
displayName | string | -- | Human-readable name shown in the player list |
playerMetadata | Record<string, unknown> | -- | Arbitrary metadata attached to this player (avatar, team, skin, etc.) |
iceServers | RTCIceServer[] | Provider defaults | Custom STUN/TURN servers for this room (overrides provider-level config) |
hostMigration | boolean | true | Automatically elect a new host when the current host disconnects |
reconnectAttempts | number | 3 | Number of automatic reconnection attempts on disconnect |
reconnectIntervalMs | number | 2000 | Delay between reconnection attempts (ms) |
privacy | 'all' | 'relay' | 'all' | Set to 'relay' to force all traffic through TURN servers (hides player IP addresses) |
onConnected | () => void | -- | Callback when successfully connected to the room |
onDisconnected | (reason: string) => void | -- | Callback when disconnected from the room |
onHostMigration | (newHostId: string) => void | -- | Callback when the host changes |
onError | (error: CarverMultiplayerError) => void | -- | Callback for any multiplayer error |
Networked Config Prop Reference #
The config prop on <Networked> controls per-entity sync behaviour.
<Networked id="player-1" config={{ sync: "transform", owner: peerId, interpolate: true }}>
<Actor type="primitive" shape="box" />
</Networked>| Field | Type | Default | Description |
|---|---|---|---|
sync | 'transform' | 'rigid-body' | 'custom' | 'transform' | What data is synchronized. transform syncs position/rotation/scale; rigid-body adds velocity and angular velocity; custom sends only what you provide |
owner | string | host peer ID | Peer ID that has authority over this entity. Only the owner can write state |
custom | Record<string, unknown> | — | Arbitrary key-value pairs synced alongside transform. Useful for health, score, animation state |
interpolate | boolean | true | Whether remote copies of this entity use interpolation. Disable for instant-snap objects like UI cursors |
Debug Tools #
DebugOverlay #
Enable the on-screen overlay to see live network statistics:
const multiplayer = useMultiplayer({
debug: { overlay: true },
});The overlay displays:
RTT — round-trip time to each peer (ms)
Bandwidth — inbound/outbound bytes per second
Tick — current simulation tick and drift
Entities — total synced entity count
Packet loss — detected packet loss percentage
Toggle the overlay at runtime by pressing F3.
Network Simulator #
Inject artificial latency and packet loss for testing poor network conditions:
debug: {
simulatedLatencyMs: 150, // 150ms one-way delay
simulatedPacketLoss: 0.05, // 5% random packet drop
}Error Codes #
All multiplayer errors use CarverError with a code field from the CarverErrorCode enum.
| Code | Meaning | Common Cause | Recovery |
|---|---|---|---|
ROOM_NOT_FOUND | The room ID does not exist | Typo in room ID, or room expired | Verify the room ID and retry |
ROOM_FULL | Room has reached max players | All player slots are taken | Show "room full" UI, retry later |
ROOM_LOCKED | Room is locked by the host | Host called room.lock() | Inform the user, wait for unlock |
INVALID_PASSWORD | Wrong room password | User entered incorrect password | Prompt for correct password |
CONNECTION_FAILED | Could not establish a connection | Firewall, NAT, or network issue | Retry, or set privacy: 'relay' to force TURN |
HOST_UNREACHABLE | Cannot reach the room host | Host went offline without migration | Wait for host migration, or rejoin |
KICKED | Kicked from the room by the host | Host called room.kick(peerId) | Show "kicked" message to the user |
SIGNALING_ERROR | Signaling strategy error | MQTT broker or Firebase unreachable | Check network, retry after a delay |
TURN_CREDENTIAL_ERROR | TURN server credential failure | Expired or invalid TURN credentials | Refresh credentials and retry |
TRANSPORT_ERROR | Low-level transport failure | WebRTC data channel closed unexpectedly | Automatic reconnection will attempt recovery |
MIGRATION_FAILED | Host migration did not complete | All candidate hosts disconnected simultaneously | Rejoin or create a new room |
const room = useRoom({
onError: (error) => {
switch (error.code) {
case "ROOM_FULL":
showToast("Room is full. Try again later.");
break;
case "INVALID_PASSWORD":
promptPassword();
break;
default:
console.error(`[Carver] ${error.code}: ${error.message}`);
}
},
});Type Definitions #
See Types for all type definitions including UseMultiplayerOptions, UseRoomOptions, NetworkedConfig, QuantizeOptions, PredictionOptions, InterpolationOptions, InterestManagementOptions, DebugOptions, CarverError, and CarverErrorCode.