{"version":3,"file":"RoomClock.cjs","sources":["../src/RoomClock.ts"],"sourcesContent":["import { now } from './core/utils.ts';\n\n/**\n * Structural contract for anything USED as a clock — the loose type Predict\n * accepts, so bare test fakes may omit the optional members. What a\n * {@link Room} EXPOSES is the stricter {@link RoomClock}, which additionally\n * guarantees {@link renderNow}. The default implementation is\n * {@link RoomClockImpl} (test mocks, alternative RTT estimators, NTP-style\n * probe-driven clocks can replace it — see {@link Room.clock}).\n *\n * PURE TIME + LATENCY: the clock no longer tracks input acks. The input\n * round-trip (what you sent / what the server processed) lives on the\n * {@link InputHandle}; the Room feeds the clock a pre-computed RTT sample.\n */\nexport interface RoomClockLike {\n    /** Local monotonic clock (ms) — the un-offset base {@link serverNow} is built on.\n     *  For SELF-IMPOSED relative gates (a cooldown / fire-rate you started locally):\n     *  `now() - lastAction >= COOLDOWN_MS`. A relative measure cancels the clock offset,\n     *  so this needs no clock sync and dodges the offset-EMA jitter. Contrast\n     *  {@link serverNow}, which you want for server-STAMPED absolute deadlines\n     *  (invuln / respawn / buy-phase windows you compare an absolute instant against). */\n    now(): number;\n    /** Estimated server clock (ms since room start — see {@link RoomClockImpl.serverNow}). */\n    serverNow(): number;\n    /** Server clock like {@link serverNow}, but on a SLEW-LIMITED **render**\n     *  timeline: a clock advanced at 1 ms/ms and servoed gently toward\n     *  `serverNow()` (τ ≈ 250 ms). It strips the per-patch offset-EMA wobble\n     *  `serverNow()` carries, so DRAWING / dead-reckoning remote entities off\n     *  this avoids the `v·Δclock` jitter the raw estimate shows at speed (the\n     *  dominant remote-entity stutter). Optional — a clock with no offset noise\n     *  (or that doesn't care) may omit it, and Predict falls back to\n     *  {@link serverNow}. Do NOT use it for hit stamps / server-stamped\n     *  deadlines: those must match the server's rewind target, which the render\n     *  timeline deliberately lags during an offset correction. */\n    renderNow?(): number;\n    /** Last RTT sample (ms). */\n    rtt(): number;\n    /** EMA-smoothed RTT (ms). Preferred for forward-prediction. */\n    smoothedRtt(): number;\n    /** Connection *jitter* (ms): RFC 3550-style interarrival jitter — an EMA of how far\n     *  each patch's arrival interval strays from the advertised cadence. A connection-\n     *  quality signal (~0 on a steady link), independent of the latency level. A custom\n     *  clock with no patch cadence can return `0`. `0` until the cadence is known and two patches land. */\n    jitter(): number;\n    /** Server-encode time (ms since room start) of the MOST RECENT patch — the\n     *  raw `sNow` of the last TIMED sample, NOT offset-reconstructed. The state\n     *  you currently hold represents the server at this instant, so\n     *  `serverNow() − lastServerTime()` is the snapshot's age — the exact\n     *  forward horizon for dead-reckoning a remote entity to \"now\". `0` until\n     *  the first sample. */\n    lastServerTime(): number;\n    /** Server snapshot cadence (`patchRate`, ms) — the interval at which the\n     *  server broadcasts state, advertised in the input handshake. On the\n     *  jitter-free server-time axis a MOVING field gets a sample every patch, so\n     *  interpolation uses this to tell a delta-encoded IDLE gap (collapse it)\n     *  from the normal cadence. `0` when unknown (no input room / not advertised). */\n    patchInterval?(): number;\n    /** Feed the server's snapshot cadence (`patchRate`, ms), decoded once from\n     *  the input handshake — the producer side of {@link patchInterval}, and a\n     *  Room→clock feed like {@link sample}. Optional: a custom clock that doesn't\n     *  drive interpolation idle-gap detection need not implement it. */\n    setPatchInterval?(milliseconds: number): void;\n    /** Feed a decoded TIMED sample: `sNow` (ms since room start) updates the\n     *  clock offset; `rttSample` (ms round-trip from the input ack, or `<0` if\n     *  none this packet) updates the RTT estimate. */\n    sample(sNow: number, rttSample: number): void;\n}\n\n/**\n * The clock contract `Room.clock` guarantees: {@link RoomClockLike} with\n * {@link RoomClockLike.renderNow | renderNow} always present, so render code\n * calls `room.clock.renderNow()` with no optional chaining and no\n * `serverNow()` fallback. Both built-in clocks ({@link NULL_CLOCK},\n * {@link RoomClockImpl}) satisfy it; a custom replacement with no slew state\n * of its own aliases the estimate: `renderNow() { return this.serverNow(); }`.\n */\nexport interface RoomClock extends RoomClockLike {\n    renderNow(): number;\n}\n\n/**\n * Stub clock returned by {@link Room.clock} until the JOIN_ROOM handshake\n * reveals whether the room declared input.\n *\n * - `serverNow()` falls back to the client's own `performance.now()` — a\n *   monotonic, non-offset-corrected timestamp. Good enough for any consumer\n *   that just wants \"a monotonic ms reading.\"\n * - `rtt()` / `smoothedRtt()` return `0` (no samples available).\n * - `sample()` is a no-op.\n *\n * Shared, frozen singleton — costs nothing to keep around for rooms that\n * never call `defineInput()`. The Room replaces it with a real\n * {@link RoomClockImpl} during handshake when input is declared.\n */\nexport const NULL_CLOCK: RoomClock = Object.freeze({\n    now: () => now(),\n    serverNow: () => now(),\n    renderNow: () => now(),\n    rtt: () => 0,\n    smoothedRtt: () => 0,\n    jitter: () => 0,\n    lastServerTime: () => 0,\n    patchInterval: () => 0,\n    setPatchInterval: (_ms?: number) => { /* no-op */ },\n    sample: (_sNow?: number, _rttSample?: number) => { /* no-op */ },\n});\n\n/**\n * Per-room clock-sync + RTT estimator, fed by the {@link ProtocolModifier.TIMED}\n * prefix the server prepends to state messages when the room declared input\n * via `defineInput()`.\n *\n * Two independent estimates are tracked:\n *\n * - **Clock offset** (`serverNow()`): the delta between server `performance.now()`\n *   and the client's. Seeded by the first sample (offset-only or RTT-valid)\n *   then EMA-smoothed. Used so client-side comparisons against\n *   server-stamped deadlines (`invulnUntil`, `hitTime`, etc.) line up.\n *\n * - **Round-trip time** (`rtt()` / `smoothedRtt()`): computed by correlating\n *   the server-echoed `lastInputSeq` with the client's own send-time table.\n *   Seeded *only* by the first RTT-valid sample (separate from the offset\n *   seed) — otherwise the first valid sample would EMA-blend from 0 and\n *   strand the smoothed value at ~10% of reality, after which the outlier\n *   guard would reject every subsequent real sample.\n *\n * Doesn't know about transports, schemas, input, or Room internals — the Room\n * calls {@link sample} when a TIMED prefix arrives, passing a pre-computed RTT\n * sample (the input round-trip is tracked by the InputHandle). Pure math.\n */\nexport class RoomClockImpl implements RoomClock {\n    /** Default exponential-smoothing weight for offset + RTT EMA. */\n    private static readonly EMA_ALPHA = 0.1;\n\n    /** Default slew time-constant (ms) for {@link renderNow}. ~250 ms: offset\n     *  corrections smear over a few frames instead of popping, while the render\n     *  timeline still tracks `serverNow()` closely in steady state. */\n    private static readonly RENDER_TAU = 250;\n    /** Gap (ms) past which {@link renderNow} SNAPS to `serverNow()` instead of\n     *  slewing. Slewing a large gap (join warmup while the offset EMA is still\n     *  converging, a route-change offset jump, a tab-resume stall) would render\n     *  a visible standing lag; only wobble-scale gaps get smoothed. */\n    private static readonly RENDER_SNAP = 250;\n\n    /**\n     * RTT samples greater than `outlierFactor × smoothedRtt` are rejected.\n     * Catches tab-resume spikes once the smoothed value has converged; the\n     * separate `_rttHasSample` seed prevents this from clamping early\n     * legitimate samples to a stranded baseline.\n     */\n    private static readonly RTT_OUTLIER_X = 4;\n\n    /** RFC 3550 jitter EMA gain (1/16) — slower than the RTT/offset EMA so the\n     *  reported jitter is a steady readout rather than a per-patch flicker. */\n    private static readonly JITTER_GAIN = 1 / 16;\n    /** Arrival gaps beyond `JITTER_STALL_X ×` the cadence (a tab-resume stall), and\n     *  sub-cadence bursts (mult 0), are skipped so they don't spike the jitter EMA. */\n    private static readonly JITTER_STALL_X = 4;\n\n    /**\n     * Clock-offset jitter gate. An offset sample is only folded into the EMA when\n     * its RTT is within `RTT_GATE_FACTOR ×` the windowed-minimum RTT — i.e. the\n     * packet traversed near-empty queues, so its `rtt/2` one-way estimate (and\n     * thus the offset) is least corrupted by jitter. Higher-RTT samples carry\n     * proportionally more jitter and are dropped (the offset just holds). This is\n     * the NTP/QUIC pattern: EMA-smooth the value you report, but filter the input\n     * by the low-delay floor — purely a VARIANCE reduction on `serverNow()`, which\n     * is what steadies the stamped reckonTime. The held offset's small bias is\n     * harmless (it cancels: predict + rewind share the stamped instant).\n     */\n    private static readonly RTT_GATE_FACTOR = 1.2;\n    /** Sliding window (ms) over which the RTT floor (gate reference) is tracked.\n     *  Long enough to hold a good low-jitter sample; on a route change the stale\n     *  floor expires within this horizon and the gate re-opens. */\n    private static readonly RTT_GATE_WINDOW = 10_000;\n    /** Post-reset warmup: the first `RTT_GATE_WARMUP` RTT-valid samples BYPASS the\n     *  gate (pure EMA), so the offset converges at baseline speed after a reset /\n     *  reconnect. The gate drops samples, which otherwise stretches convergence —\n     *  worst at high RTT, where it showed as an inflated offset.std until settled.\n     *  ~3× the EMA time-constant (1/α = 10) ⇒ converged before the gate engages for\n     *  steady-state variance reduction. `0` disables the warmup (gate from sample 1). */\n    private static readonly RTT_GATE_WARMUP = 30;\n\n    private _clockOffset = 0;       // serverTime - clientTime at sample time\n    private _clockHasSample = false;\n    private _offsetCount = 0;       // RTT-valid offset samples since reset (gate warmup)\n\n    // Sliding-window-minimum of RTT (monotonic deque: values increasing front→back,\n    // front = windowed min). Parallel number arrays → no per-sample object alloc.\n    private _rttFloorT: number[] = []; // sample arrival times (tNow), aligned with _rttFloorV\n    private _rttFloorV: number[] = []; // RTT values, monotonically increasing\n\n    private _rtt = 0;               // most recent RTT sample (ms)\n    private _smoothedRtt = 0;       // EMA over RTT samples\n    private _rttHasSample = false;\n\n    private _jitter = 0;            // EMA of patch-arrival deviation from the cadence (ms)\n    private _lastRecvTime = -1;     // arrival time of the previous patch; -1 until the first\n\n    private _lastServerTime = 0;    // raw sNow of the last patch (snapshot stamp)\n    private _patchInterval = 0;     // server patchRate (ms); 0 until advertised\n\n    private _renderTau = RoomClockImpl.RENDER_TAU; // slew time-constant (ms); 0 disables\n    private _renderSn = 0;          // slew-limited render-clock reading (ms since room start)\n    private _renderSnAt = 0;        // local time (now()) the render clock last advanced\n\n    /** Estimated server clock: **milliseconds since room start** (the server's\n     *  `clock.elapsedTime`, reconstructed via the wire `sNow` + local offset).\n     *  NOT raw `performance.now()` — a portable integer-ms timeline the server's\n     *  own time-keyed logic shares, so client-side reckon stays in phase.\n     *  Returns the local clock until the first sample lands. */\n    public serverNow(): number {\n        return now() + this._clockOffset;\n    }\n\n    /** Slew-limited render timeline — see {@link RoomClockLike.renderNow}.\n     *  Free-runs at 1 ms/ms and servos toward {@link serverNow} with the\n     *  time-constant set by {@link setRenderTau} (default {@link RENDER_TAU});\n     *  `τ ≤ 0` disables the slew and returns `serverNow()` verbatim. Idempotent\n     *  within a frame: it advances only on the first call each frame (guarded on\n     *  the local clock), so reading it once per tracked entity doesn't over-step\n     *  it. */\n    public renderNow(): number {\n        const target = this.serverNow();\n        if (this._renderTau <= 0) { return target; }\n        const t = now();\n        // Seed on first use — jump straight to the current server-present.\n        if (this._renderSn === 0) { this._renderSn = target; this._renderSnAt = t; return this._renderSn; }\n        const dt = Math.min(t - this._renderSnAt, 100); // clamp tab-resume stalls\n        if (dt < 0.5) { return this._renderSn; }         // same frame — advance once\n        this._renderSnAt = t;\n        this._renderSn += dt;                            // free-run at 1 ms/ms\n        // Snap past large gaps rather than slew them (see RENDER_SNAP) — a\n        // standing lag reads worse than one clean jump.\n        if (Math.abs(target - this._renderSn) > RoomClockImpl.RENDER_SNAP) { this._renderSn = target; return this._renderSn; }\n        this._renderSn += (target - this._renderSn) * (1 - Math.exp(-dt / this._renderTau)); // servo toward server-present\n        return this._renderSn;\n    }\n\n    /** Set the {@link renderNow} slew time-constant (ms). `≤ 0` disables slewing\n     *  (renderNow == serverNow). Larger = smoother, but offset corrections lag\n     *  longer. */\n    public setRenderTau(milliseconds: number): void {\n        this._renderTau = milliseconds > 0 ? milliseconds : 0;\n    }\n\n    /** Local monotonic clock (ms): the client's own reading WITHOUT the server\n     *  offset — the base {@link serverNow} adds the offset to. Use it for\n     *  self-imposed relative cooldowns (`now() - lastAction >= COOLDOWN_MS`): they\n     *  need only a steady rate, not clock sync, so this avoids the offset-EMA\n     *  jitter `serverNow()` carries. @see RoomClockLike.now */\n    public now(): number {\n        return now();\n    }\n\n    /** Most recent RTT sample (ms). `0` until the first RTT-valid sample lands. */\n    public rtt(): number {\n        return this._rtt;\n    }\n\n    /** EMA-smoothed RTT (ms). `0` until the first RTT-valid sample lands. Prefer this for forward-prediction. */\n    public smoothedRtt(): number {\n        return this._smoothedRtt;\n    }\n\n    /** Connection jitter (ms): RFC 3550-style interarrival jitter — see\n     *  {@link RoomClockLike.jitter}. `0` until the cadence is known and two patches land. */\n    public jitter(): number {\n        return this._jitter;\n    }\n\n    /** Server-encode time (raw `sNow`) of the most recent patch. Pair with\n     *  {@link serverNow} for the snapshot age (`serverNow() − lastServerTime()`).\n     *  `0` until the first sample. */\n    public lastServerTime(): number {\n        return this._lastServerTime;\n    }\n\n    /** Server snapshot cadence (`patchRate`, ms); `0` until the handshake\n     *  advertises it. @see RoomClockLike.patchInterval */\n    public patchInterval(): number {\n        return this._patchInterval;\n    }\n\n    /** Set the server snapshot cadence (ms), from the input handshake's\n     *  advertised `patchRate`. Non-positive values clear it back to `0`. */\n    public setPatchInterval(milliseconds: number): void {\n        this._patchInterval = milliseconds > 0 ? milliseconds : 0;\n    }\n\n    /**\n     * Feed a decoded TIMED sample. The input round-trip lives on the\n     * {@link InputHandle} now — the Room hands us a pre-computed RTT sample.\n     *\n     * @param sNow       Server clock (ms since room start, `clock.elapsedTime`)\n     *                   → clock offset.\n     * @param rttSample  Round-trip time (ms) for the input ack this packet\n     *                   carried, or `< 0` if none (no matching send / no input\n     *                   yet). Filtered + EMA-smoothed here.\n     */\n    public sample(sNow: number, rttSample: number): void {\n        const tNow = now();\n        const a = RoomClockImpl.EMA_ALPHA;\n\n        // Connection jitter (RFC 3550 interarrival): how far this patch's arrival\n        // interval strays from the advertised cadence — measured against the cadence,\n        // NOT `sNow` (only refreshed at the sim-tick rate, so a sim/patch rate mismatch\n        // would beat in as phantom jitter). Idle/dropped patches round to a whole\n        // multiple; bursts (mult 0) and stalls (> X) are skipped.\n        const PI = this._patchInterval;\n        if (this._lastRecvTime >= 0 && PI > 0) {\n            const gap = tNow - this._lastRecvTime;\n            const mult = Math.round(gap / PI);\n            if (mult >= 1 && mult <= RoomClockImpl.JITTER_STALL_X) {\n                this._jitter += (Math.abs(gap - mult * PI) - this._jitter) * RoomClockImpl.JITTER_GAIN;\n            }\n        }\n        this._lastRecvTime = tNow;\n\n        // Stamp the snapshot's server-encode time (raw, un-reconstructed).\n        this._lastServerTime = sNow;\n\n        // Reject impossible / outlier RTT (tab-resume spikes once converged).\n        if (rttSample < 0) {\n            rttSample = -1;\n        } else if (this._smoothedRtt > 0 && rttSample > this._smoothedRtt * RoomClockImpl.RTT_OUTLIER_X) {\n            rttSample = -1;\n        }\n\n        // Clock offset: refreshed every patch (sNow advances each patch). Prefer\n        // the RTT-corrected estimate when a fresh sample exists, else OWL-biased.\n        const offsetSample = rttSample >= 0 ? sNow + rttSample / 2 - tNow : sNow - tNow;\n        if (!this._clockHasSample) {\n            this._clockOffset = offsetSample;\n            this._clockHasSample = true;\n            if (rttSample >= 0) { this.pushRttFloor(rttSample, tNow); this._offsetCount = 1; }\n        } else if (rttSample >= 0) {\n            // Track the windowed-min RTT and gate: only low-jitter samples update the\n            // offset (see RTT_GATE_FACTOR) — EXCEPT during the post-reset warmup, when\n            // the gate is bypassed so convergence isn't stretched (see RTT_GATE_WARMUP).\n            // rttSample<0 (no ack this packet) skips the offset entirely — an\n            // uncorrected `sNow-tNow` is the noisiest kind, so let the offset hold.\n            const floor = this.pushRttFloor(rttSample, tNow);\n            const warming = this._offsetCount < RoomClockImpl.RTT_GATE_WARMUP;\n            this._offsetCount++;\n            if (warming || rttSample <= floor * RoomClockImpl.RTT_GATE_FACTOR) {\n                this._clockOffset = this._clockOffset * (1 - a) + offsetSample * a;\n            }\n        }\n\n        // RTT: seeded on the first valid sample (separate flag — see class doc).\n        if (rttSample >= 0) {\n            this._rtt = rttSample;\n            if (!this._rttHasSample) {\n                this._smoothedRtt = rttSample;\n                this._rttHasSample = true;\n            } else {\n                this._smoothedRtt = this._smoothedRtt * (1 - a) + rttSample * a;\n            }\n        }\n    }\n\n    /**\n     * Push an RTT sample into the sliding-window-minimum deque and return the\n     * current windowed-min RTT (the jitter-free floor the offset gate references).\n     * Standard monotonic-deque algorithm — O(1) amortized, the deque holds only\n     * descending \"record-low\" candidates (typically 1–few entries).\n     */\n    private pushRttFloor(rttSample: number, tNow: number): number {\n        const T = this._rttFloorT, V = this._rttFloorV;\n        // Drop back entries no lower than this sample — they can never be the min\n        // again while this newer, ≤ sample is in the window.\n        while (V.length > 0 && V[V.length - 1] >= rttSample) { V.pop(); T.pop(); }\n        V.push(rttSample); T.push(tNow);\n        // Expire entries older than the window from the front.\n        const cutoff = tNow - RoomClockImpl.RTT_GATE_WINDOW;\n        while (T.length > 0 && T[0] < cutoff) { T.shift(); V.shift(); }\n        return V[0]; // front = windowed minimum\n    }\n\n    /** Reset all state. Useful on reconnect when the room rebuilds context. */\n    public reset(): void {\n        this._clockOffset = 0;\n        this._clockHasSample = false;\n        this._offsetCount = 0;\n        this._rtt = 0;\n        this._smoothedRtt = 0;\n        this._rttHasSample = false;\n        this._jitter = 0;\n        this._lastRecvTime = -1;\n        this._lastServerTime = 0;\n        this._rttFloorT.length = 0;\n        this._rttFloorV.length = 0;\n        this._renderSn = 0;        // τ is config, not state — it survives reset\n        this._renderSnAt = 0;\n    }\n}\n"],"names":["now"],"mappings":"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"}