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.

tsx
import { useMultiplayer, useRoom } from "@carverjs/multiplayer";

useMultiplayer Options #

Pass these options to useMultiplayer() to control synchronization behaviour.

tsx
const multiplayer = useMultiplayer({
  mode: "prediction",
  tickRate: 60,
  broadcastRate: 20,
  keyframeInterval: 60,
  quantize: { position: 0.01 },
  prediction: { enabled: true },
  interpolation: { delay: 100 },
});

Top-Level Options #

OptionTypeDefaultDescription
mode'events' | 'snapshot' | 'prediction''snapshot'Sync strategy. events sends only inputs; snapshot sends full state; prediction adds client-side prediction and reconciliation
tickRatenumber60Fixed-timestep simulation rate in Hz. Higher = more precise physics but more CPU
broadcastRatenumber20How often the host sends state updates per second. Independent of tickRate
keyframeIntervalnumber60Number of ticks between full keyframe snapshots. Between keyframes, only deltas are sent
quantizeQuantizeOptionsReduce floating-point precision to save bandwidth
deltaThresholdsDeltaThresholdsMinimum change required before a field is included in a delta update
predictionPredictionOptionsClient-side prediction and server reconciliation settings
interpolationInterpolationOptionsHow remote entities are smoothed between updates
interestManagementInterestManagementOptionsArea-of-interest filtering for large worlds
debugDebugOptionsDebug overlay and network simulation tools
onPhysicsStep(dt: number) => voidCallback 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.

FieldTypeDefaultDescription
positionnumberStep size for position axes. 0.01 = centimetre precision
rotationnumberStep size for rotation (radians). 0.001 is typically sufficient
velocitynumberStep size for linear/angular velocity
tsx
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.

FieldTypeDefaultDescription
positionnumber0.001Minimum positional change (world units)
rotationnumber0.001Minimum rotational change (radians)
velocitynumber0.01Minimum velocity change
tsx
deltaThresholds: {
  position: 0.001,
  rotation: 0.001,
  velocity: 0.01,
}

PredictionOptions #

Controls client-side prediction and server reconciliation. Only relevant when mode is 'prediction'.

FieldTypeDefaultDescription
enabledbooleantrueEnable client-side prediction
maxRewindTicksnumber30Maximum number of ticks the client will rewind and replay during reconciliation
correctionSmoothingnumber0.2Blend factor for correction (0 = instant snap, 1 = no correction). 0.2 gives a smooth visual correction over ~5 frames
inputBufferSizenumber60Number of past input frames stored for replay during reconciliation
tsx
prediction: {
  enabled: true,
  maxRewindTicks: 30,
  correctionSmoothing: 0.2,
  inputBufferSize: 60,
}

InterpolationOptions #

Controls how remote (non-local) entities are smoothed between network updates.

FieldTypeDefaultDescription
delaynumber100Interpolation delay in milliseconds. Higher = smoother but more latency
maxExtrapolationnumber200Maximum time (ms) to extrapolate beyond the last received state before freezing
method'linear' | 'hermite''linear'Interpolation curve. Hermite produces smoother motion for accelerating objects
tsx
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.

FieldTypeDefaultDescription
enabledbooleanfalseEnable spatial interest management
cellSizenumber50Spatial hash cell size in world units
viewDistancenumber200Maximum distance (world units) at which entities are synced to a client
hysteresisnumber20Buffer zone to prevent entities flickering in/out at the boundary
tsx
interestManagement: {
  enabled: true,
  cellSize: 50,
  viewDistance: 200,
  hysteresis: 20,
}

DebugOptions #

Developer tools for visualizing and simulating network conditions.

FieldTypeDefaultDescription
overlaybooleanfalseShow the on-screen debug overlay with live stats
simulatedLatencyMsnumber0Artificial one-way latency added to every message (ms)
simulatedPacketLossnumber0Fraction of packets to randomly drop (0–1). 0.05 = 5% loss
logLevel'none' | 'error' | 'warn' | 'info' | 'debug''warn'Console log verbosity
tsx
debug: {
  overlay: true,
  simulatedLatencyMs: 80,
  simulatedPacketLoss: 0.02,
  logLevel: "info",
}

useRoom Options #

Pass these options to useRoom() to configure the connection and room behaviour.

tsx
const room = useRoom({
  displayName: "Player1",
  password: "secret",
  hostMigration: true,
  reconnectAttempts: 5,
  privacy: "relay",
});
OptionTypeDefaultDescription
transportCarverTransport--Pass a custom CarverTransport instance to bypass the built-in WebRTCTransport
passwordstring--Room password. Joining peers must provide the same value
displayNamestring--Human-readable name shown in the player list
playerMetadataRecord<string, unknown>--Arbitrary metadata attached to this player (avatar, team, skin, etc.)
iceServersRTCIceServer[]Provider defaultsCustom STUN/TURN servers for this room (overrides provider-level config)
hostMigrationbooleantrueAutomatically elect a new host when the current host disconnects
reconnectAttemptsnumber3Number of automatic reconnection attempts on disconnect
reconnectIntervalMsnumber2000Delay 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.

tsx
<Networked id="player-1" config={{ sync: "transform", owner: peerId, interpolate: true }}>
  <Actor type="primitive" shape="box" />
</Networked>
FieldTypeDefaultDescription
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
ownerstringhost peer IDPeer ID that has authority over this entity. Only the owner can write state
customRecord<string, unknown>Arbitrary key-value pairs synced alongside transform. Useful for health, score, animation state
interpolatebooleantrueWhether 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:

tsx
const multiplayer = useMultiplayer({
  debug: { overlay: true },
});

The overlay displays:

Toggle the overlay at runtime by pressing F3.

Network Simulator #

Inject artificial latency and packet loss for testing poor network conditions:

tsx
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.

CodeMeaningCommon CauseRecovery
ROOM_NOT_FOUNDThe room ID does not existTypo in room ID, or room expiredVerify the room ID and retry
ROOM_FULLRoom has reached max playersAll player slots are takenShow "room full" UI, retry later
ROOM_LOCKEDRoom is locked by the hostHost called room.lock()Inform the user, wait for unlock
INVALID_PASSWORDWrong room passwordUser entered incorrect passwordPrompt for correct password
CONNECTION_FAILEDCould not establish a connectionFirewall, NAT, or network issueRetry, or set privacy: 'relay' to force TURN
HOST_UNREACHABLECannot reach the room hostHost went offline without migrationWait for host migration, or rejoin
KICKEDKicked from the room by the hostHost called room.kick(peerId)Show "kicked" message to the user
SIGNALING_ERRORSignaling strategy errorMQTT broker or Firebase unreachableCheck network, retry after a delay
TURN_CREDENTIAL_ERRORTURN server credential failureExpired or invalid TURN credentialsRefresh credentials and retry
TRANSPORT_ERRORLow-level transport failureWebRTC data channel closed unexpectedlyAutomatic reconnection will attempt recovery
MIGRATION_FAILEDHost migration did not completeAll candidate hosts disconnected simultaneouslyRejoin or create a new room
tsx
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.