§ Deterministic multiplayer
Two clients, one sea — no wave data on the wire
Both panels are independent Tidewater instances with their own renderer, their own FFT and their own GPU. They share a seed and an integer tick, nothing else. The host broadcasts its tick through a simulated network with the latency and jitter you set; the client's NetClock estimates transit time and slews its clock toward the host's instead of snapping. Knock the client two seconds off and watch it glide back over the next few seconds — no pop.
client − host (ticks) –
NetClock error –
packets 0
state waiting for first packet
§ What this is doing
// host
const state = host.getSyncState(); // seed + spectrum + clock, ~300 bytes, once
setInterval(() => send({ tick: host.tick }), 250);
// client
client.applySyncState(state); // same sea, same clock
const clock = new NetClock({ stepSize: client.ocean.stepSize });
client.netClock = clock; // the element slews its own advance(dt)
onPacket(({ tick }) => clock.receive(tick, rttMs));
Determinism holds across quality tiers too: the phase hash is keyed on wavenumber, so a phone on Low and a workstation on Ultra compute the same long and mid waves. Buoyancy reads the same CPU mirror on both, so anything floating agrees as well.