DataSaver

DataSaver is the dedicated SyncNuke synchronization protocol. It’s main goal is to provide reliable synchronization with low communication overhead over connection-oriented communication.

Reference behavior

DataSaverClient implements protocol datasaver, version 0.1.0. It exchanges playback state and room membership information while filtering updates that match expected progress. The current client uses QuicClient with BaseCodec.

Session flow

  1. After the master-server connection, the client connects to the selected server and sends JOIN_ROOM with its username, room, and optional password.
  2. Local playback changes can produce UPDATE_STATE messages. Incoming state updates update the client’s expected state and are applied through PlayerManager.
  3. Incoming JOIN_ROOM and LEAVE_ROOM messages update the user list for the current room.
  4. A server CONNECT message redirects the client to another host and port. The client reconnects and sends JOIN_ROOM again with the stored session details.
  5. Closing the client sends LEAVE_ROOM before releasing the connection.

State updates

State messages carry play/pause state, position in seconds, and playback speed. They contain no timestamp; the client records its own current time when updating its expected state.

The first local observation and changes between playing and paused trigger an update. For other observations, Core applies these filters in order:

  • A position difference within MIN_PROG_CHANGE of the stored expected state is suppressed.
  • A larger difference while paused, or with no positive elapsed time, triggers an update.
  • While playing, the client compares actual progress with elapsed time multiplied by the observed playback speed. It sends an update when the relative error exceeds DRIFT_THRESHOLD. Expected advances that become zero after integer truncation are suppressed.

A speed-only change can therefore be suppressed by the position filter. The latest expected state is recorded after a successful local send or before applying an incoming update.

The default keep-alive interval is 10 seconds, defined by DEFAULT_KEEP_ALIVE_INTERVAL_MILLIS. At each scheduled check, if no message has been sent for that interval and an expected state is available, the client sends an UPDATE_STATE with its projected position.

Using a state update as the keep-alive keeps the connection active and regularly refreshes synchronization information. Relying only on change-triggered messages could allow a missed or suppressed update to cause drift that grows over time. Periodic state updates provide an ongoing synchronization reference to help prevent that divergence.

Message format

Messages are consecutive bytes on an ordered stream. The first byte identifies the command; its fields determine the message length. There is no outer length prefix or separator.

All multibyte values use big-endian byte order. u16 is an unsigned 16-bit integer; f64 is an eight-byte IEEE 754 double. string is a u16 UTF-8 byte count followed by that many bytes, with a maximum encoded length of 65,535 bytes.

An optional string starts with a one-byte presence marker: 0 means absent; 1 is followed by a string. An empty, present string has marker 1 and length 0.

Fields follow the command byte in the order shown below.

CommandCodeFields
CONNECT0x01host
string
port
u16
UPDATE_STATE0x02state
byte
position
f64
playbackSpeed
f64
JOIN_ROOM0x03username
string
room
string
password
optional string
LEAVE_ROOM0x04username
string
room
string
password
optional string
PING0x05None

Client behavior

  • CONNECT: Receives a server redirect. The client reconnects to the supplied endpoint and rejoins the room; its codec does not encode this command.
  • UPDATE_STATE: Sends local and keep-alive state updates, and applies incoming server state.
  • JOIN_ROOM: Sends a room join and receives membership notifications.
  • LEAVE_ROOM: Sends a departure and receives membership notifications.
  • PING: The decoder consumes the command without delivering a message to the client.

Playback state

State Code
PAUSED 0x00
PLAYING 0x01

An UPDATE_STATE message is exactly 18 bytes. For example, paused at position zero with normal speed is:

02 00 00 00 00 00 00 00 00 00 3f f0 00 00 00 00 00 00

Incoming room messages consume the optional password field but discard its value. The codec rejects unknown command/state codes, invalid optional-string markers, and truncated messages. Playback value validation is performed by PlayerManager.

The DataSaver CONNECT message carries only host and port. It is separate from the master protocol’s ConnectData, which also carries the synchronization protocol and version.

Reference material

SyncNuke Core’s DataSaver command model (internal).

DataSaver overview.

DataSaverClient and BaseCodec implement the behavior and message format described above.