/** * PhysicsSyncProtocol — WebRTC binary protocol for two-tier physics sync. * * Tier 1 (Logic): CRDT state sync at ~10 Hz via WorldState (Loro) * Tier 2 (Physics): Raw binary particle sync at ~60 Hz via DataChannel * * This module handles Tier 2. The binary protocol is designed for minimal * overhead over unreliable DataChannels: * - No JSON, no protobuf — pure typed arrays * - Delta compression: only send changed particles * - Quantized positions: 16-bit half-float for bandwidth (optional) * - Sequence numbers for jitter buffer / interpolation * * Wire format: * Header (16 bytes): * [0-3] magic: 0x48505350 ('HPSP') * [4-5] version: u16 * [6-7] sequence: u16 (wraps at 65535) * [8-11] timestamp: u32 (ms since session start) * [12-13] particleCount: u16 * [14] flags: u8 (bit 0: delta, bit 1: quantized) * [15] reserved: u8 * * Body (per particle, full mode = 25 bytes): * [0-3] x: f32 * [4-7] y: f32 * [8-11] z: f32 * [12-15] vx: f32 * [16-19] vy: f32 * [20-23] vz: f32 * [24] type: u8 (ParticleType enum) * * Body (per particle, delta mode = 13 bytes): * [0-1] index: u16 (particle index in unified buffer) * [2-5] dx: f32 (position delta) * [6-9] dy: f32 * [10-13] dz: f32 * * @module physics * @see P.GAPS.09: Two-tier sync * @see G.GAPS.07: NEVER use CRDT for particle sync */ import type { UnifiedParticleBuffer } from './UnifiedParticleBuffer'; export interface PhysicsSyncConfig { /** Target send rate in Hz (default: 60) */ sendRate: number; /** Delta threshold — only send particles that moved more than this (default: 0.001) */ deltaThreshold: number; /** Max particles per packet (default: 1000, ~25KB full / ~14KB delta) */ maxParticlesPerPacket: number; /** Whether to use delta compression (default: true) */ useDelta: boolean; /** Jitter buffer size in frames (default: 3) */ jitterBufferSize: number; /** Interpolation method: 'none' | 'linear' | 'hermite' (default: 'linear') */ interpolation: 'none' | 'linear' | 'hermite'; } export interface SyncPacketHeader { magic: number; version: number; sequence: number; timestamp: number; particleCount: number; flags: number; } export interface SyncStats { packetsSent: number; packetsReceived: number; bytesPerSecond: number; averageLatencyMs: number; deltaRatio: number; droppedPackets: number; } /** * Encodes physics state from a UnifiedParticleBuffer into binary packets * and sends them over a WebRTC DataChannel. */ export declare class PhysicsSyncSender { private config; private sequence; private sessionStartMs; private lastPositions; private packetsSent; private bytesSent; private lastStatResetMs; private sendInterval; constructor(config?: Partial); /** * Start periodic sending. Calls encode() and sends over the channel. */ startSending(buffer: UnifiedParticleBuffer, channel: { send(data: ArrayBuffer): void; readyState: string; }): void; /** Stop periodic sending. */ stopSending(): void; /** * Encode current buffer state into a binary packet. * Returns null if no particles need sending. */ encode(buffer: UnifiedParticleBuffer): ArrayBuffer | null; private encodeFull; private encodeDelta; private writeHeader; getStats(): Pick; resetStats(): void; dispose(): void; } /** * Decodes binary physics packets and applies them to a local UnifiedParticleBuffer. * Provides a jitter buffer for smooth interpolation. */ export declare class PhysicsSyncReceiver { private config; private jitterBuffer; private lastSequence; private packetsReceived; private droppedPackets; private latencySum; private sessionStartMs; constructor(config?: Partial); /** * Feed a raw packet from a DataChannel message event. * Decodes the header and body, pushes to jitter buffer. */ receivePacket(data: ArrayBuffer, buffer: UnifiedParticleBuffer): void; private applyFull; private applyDelta; private pushToJitterBuffer; /** * Interpolate between buffered frames for smooth rendering. * Call this at render time with the current render timestamp. * * @param renderTimestamp - ms since session start at render time * @param buffer - target buffer to write interpolated state into */ interpolate(renderTimestamp: number, buffer: UnifiedParticleBuffer): void; getStats(): SyncStats; dispose(): void; } /** * Parse just the header of a physics sync packet. * Useful for routing or filtering before full decode. */ export declare function parsePacketHeader(data: ArrayBuffer): SyncPacketHeader | null; //# sourceMappingURL=PhysicsSyncProtocol.d.ts.map