{"version":3,"file":"rollback.cjs","sources":["../../src/predict/rollback.ts"],"sourcesContent":["/**\n * RollbackController — the shared server-reconciled rollback engine behind both\n * {@link Reconciler} (flat `fields` mirrored off one schema instance) and\n * `SimReconciler` (composite `world` + `adopt`/`pose` callbacks).\n *\n * Both controllers run the SAME loop: step each input the app sends immediately\n * (zero-latency local feel), buffer the unacknowledged ones on the input handle,\n * and when the server's authoritative state arrives rewind to that truth and\n * replay the still-unacked inputs on top — the rewind-and-replay rollback loop,\n * with the *server* as the authority that provides the restore point. They differ\n * only in WHERE the predicted state lives and how truth is adopted / read back for\n * rendering; everything else — the ack poll, the reconcile scaffold, smooth error\n * correction, `ctx.memo` memoization, drift telemetry — is identical and lives here.\n *\n * The acknowledgement lives on the INPUT HANDLE, not a clock: inputs go through\n * `room.input(...)`, so that handle knows the server ack (`input.lastProcessed`)\n * and the seq you've sent (`input.sentCount`). Reconcile is driven by polling\n * `lastProcessed` in {@link tick} — no schema field, no per-field subscription.\n *\n * Smooth error correction: a misprediction is absorbed into a per-field visual\n * offset (error = renderedBefore − correctedLocal) that decays to 0 over a few\n * frames, so corrections never pop. Correct predictions ⇒ ~zero offset.\n *\n * OBSERVER MODEL — the controller never stages or sends. You mutate + send through\n * the handle directly (`input.data.x = …; input.send()`); the controller subscribes\n * to the handle's {@link InputHandle.onSend} and steps its predicted simulation for\n * each sent input right then, so the render reads stay pure. Fixed-timestep pacing\n * lives on the owning `Predict`: `predict.tick(now)` returns HOW MANY fixed steps\n * are due this frame and pushes the interpolation `alpha` in via {@link tick}. The\n * user loop stays callback-free (`for (n) { input.data = …; input.send() }`) so it\n * ports to C# / C / Lua by transcription — only the loop and transport live in the shell.\n *\n * The subclass supplies the small set of hooks that genuinely differ:\n *   - {@link smoothedFields} / {@link readCurrent} — the numeric field set that\n *     gets smoothed, and how to read one's current predicted value.\n *   - {@link adoptTruth} — seed the server's authoritative state before replay.\n *   - {@link applyStep} — run the user step for one buffered input (live or replay).\n *   - {@link snapshotPrev} — capture the pre-step smoothed value for interpolation.\n *   - {@link reseedState} — re-seed local state on a hard {@link reset}.\n *   - {@link refreshRender} / {@link markDirty} — optional post-hooks (a pose\n *     reconciler re-samples its pose + marks its render cache dirty; the flat one no-ops).\n */\n\n// Drives + reads acks through `room.input(...)`'s handle (type-only, erased).\nimport type { InputHandle } from \"../input/InputHandle.ts\";\nimport { newDrift, updateDrift, resetDrift, classifyDrift, type Drift } from \"./drift.ts\";\nimport { warnDivergence, warnReadBeforePump, warnMemoCollision, diagnosticsActive } from \"./divergence.ts\";\n\n/**\n * Per-seq memo backing {@link StepContext.memo}: run a closure ONCE on the\n * live step, freeze its result keyed by `(seq, key)`, and on every rollback\n * REPLAY of that seq return the frozen value WITHOUT re-running it. Pruned when\n * the seq is acked, cleared on reset. Shared by {@link Reconciler} and\n * `SimReconciler` (both replay the same per-seq input buffer the same way).\n *\n * Storage is sparse — only seqs that memoized ≥1 value get an entry — so it\n * stays as small as the hand-rolled per-seq Maps it replaces. With dev\n * diagnostics on, warns once per key when two calls in one step share a slot.\n */\nclass MemoStore {\n    /** seq → (key → memoized value). */\n    private byTick = new Map<number, Map<string, any>>();\n\n    // Collision diagnostic (live path, diagnostics-gated): keys seen this tick.\n    // Tracked separately from byTick — undefined computes are never stored there.\n    private diagTick = -1;\n    private diagKeys = new Set<string>();\n    private warnedKeys = new Set<string>();\n\n    /**\n     * LIVE (`isReplay=false`): run `compute`, memoize a non-`undefined` result\n     * under `(tick, key)`, return it. REPLAY (`isReplay=true`): return the memo\n     * (or `undefined` if the live step memoized none) WITHOUT running `compute`.\n     */\n    run<T>(tick: number, isReplay: boolean, key: string, compute: () => T): T | undefined {\n        if (isReplay) return this.byTick.get(tick)?.get(key) as T | undefined;\n        if (diagnosticsActive()) {\n            if (tick !== this.diagTick) { this.diagTick = tick; this.diagKeys.clear(); }\n            else if (this.diagKeys.has(key) && !this.warnedKeys.has(key)) {\n                this.warnedKeys.add(key);\n                warnMemoCollision(tick, key);\n            }\n            this.diagKeys.add(key);\n        }\n        const v = compute();\n        if (v !== undefined) {\n            let m = this.byTick.get(tick);\n            if (m === undefined) { m = new Map(); this.byTick.set(tick, m); }\n            m.set(key, v);\n        }\n        return v;\n    }\n\n    /** Drop memos for seqs the server has acked (they'll never replay again). */\n    prune(acked: number): void {\n        for (const tick of this.byTick.keys()) if (tick <= acked) this.byTick.delete(tick);\n    }\n\n    clear(): void {\n        this.byTick.clear();\n        // Epoch reset reuses tick numbers — stale diag state would false-positive.\n        // warnedKeys survives: warn-once per store lifetime, no re-spam on respawn.\n        this.diagTick = -1;\n        this.diagKeys.clear();\n    }\n}\n\n/**\n * Per-step context handed to a reconciler's `step`. Mirrors the server's\n * `StepContext` (@colyseus/core) so ONE fixed `dt` drives both sides of the\n * rollback. Carries only the fixed step — never wall-clock time.\n */\nexport interface StepContext {\n  /** Fixed step in SECONDS (`1/tickRate`) — the dt to integrate this step with. */\n  readonly dt: number;\n  /** Fixed step in MILLISECONDS (`1000/tickRate`). */\n  readonly dtMs: number;\n  /** The input's sequence (= `input.sentCount`), which IS the index of the step\n   *  being simulated — during replay it's the historical seq, not a fresh count. */\n  readonly tick: number;\n  /**\n   * Physics sub-steps per fixed step (≥ 1) — mirrors the server's\n   * `setFixedTimestep(..., { subSteps })`, cascaded through the join handshake.\n   * One input still drives ONE `step` call (live and replayed alike — the\n   * replay invariant is untouched); inside it, integrate your engine\n   * `subSteps` times at {@link subDt}:\n   * `for (let i = 0; i < ctx.subSteps; i++) world.step(ctx.subDt)` —\n   * the same loop the server runs, so physics can run at `tickRate * subSteps`\n   * Hz while only `tickRate` inputs/sec cross the wire. `1` when the server\n   * doesn't sub-step, in which case `subDt === dt` and the loop above\n   * degenerates to a single full step — one shared `step` fn covers both.\n   */\n  readonly subSteps: number;\n  /** Physics sub-step in SECONDS (`dt / subSteps`) — bit-identical to the\n   *  server's `ctx.subDt`. Equals {@link dt} when `subSteps` is 1. */\n  readonly subDt: number;\n  /** Physics sub-step in MILLISECONDS (`dtMs / subSteps`). */\n  readonly subDtMs: number;\n  /**\n   * `false` on the live, first-time step of a fresh input; `true` while the\n   * reconciler RE-simulates an already-applied input during rollback (it rewinds\n   * to the server's authoritative state, then replays every still-unacked input\n   * on top to catch back up).\n   *\n   * Why it matters: one input is replayed 0..N times — once per reconcile until\n   * the server acks it (often several frames). Deterministic simulation (your\n   * `applyInput`) MUST re-run every time, or replay won't reproduce the server.\n   * But anything one-shot must not: this is the standard re-simulation flag\n   * rollback netcode exposes.\n   *\n   * The one-shot family has three legs, split by shape:\n   * - {@link memo} — one-shot VALUES the sim consumes (frozen, replayed back);\n   * - {@link predict} — one-shot EVENTS with settlement (confirm / auto-reject);\n   * - `if (!ctx.isReplay) { … }` — fire-and-forget PRESENTATION (a sound,\n   *   particles, camera shake, a timestamp): a plain branch on this flag IS the\n   *   idiom, deliberately not a wrapper API — a branch transcribes to any\n   *   language a port targets; a closure-taking helper doesn't.\n   */\n  readonly isReplay: boolean;\n  /**\n   * The input's reckon instant (server-clock ms) — the client's `serverNow()`\n   * estimate when this input was sent, the SAME value the server reads as\n   * `channel.reckonTime` / `rewind.lastSeenBy(sid)`. Buffered per-seq on the\n   * input handle, so it's identical on the live step and on every replay of\n   * that seq.\n   *\n   * Hit-test remote entities at this instant — sample moving solids at\n   * `reckonTime`, reckon other entities with `predict.valueAt(e, field,\n   * reckonTime)` — and your client verdict matches the server's lag-comp rewind\n   * BY CONSTRUCTION (\"what you see is what you hit\"), including for discrete\n   * motion. Because it's the same value per seq across rollbacks, collision in\n   * the step replays deterministically.\n   *\n   * Always a usable instant when the controller has a clock (automatic when\n   * spawned via `predict.reconciler()` / `predict.sim()`): a seq that wasn't\n   * stamped for lag-comp (the room never rewinds, clock not yet synced, seq\n   * aged out) resolves to the clock's live `serverNow()` — the fallback\n   * consumers previously wrote by hand. Check {@link lagCompActive} to\n   * distinguish. An unstamped seq re-reads the live `serverNow()` on each\n   * replay — that was never deterministic (consumers substituted live\n   * `serverNow()` there anyway); stamped seqs stay per-seq-buffered and\n   * replay-deterministic. `0` only on a bare controller constructed without a\n   * clock.\n   */\n  readonly reckonTime: number;\n  /**\n   * Whether THIS seq carried a reckon lag-comp stamp — the server rewinds to\n   * {@link reckonTime} for it, and the value is the buffered per-seq stamp\n   * (replay-deterministic). `false` ⇒ `reckonTime` resolved to the live\n   * `serverNow()`. The gate for the rare \"skip the lag-comp read entirely\"\n   * consumer.\n   */\n  readonly lagCompActive: boolean;\n  /**\n   * Memoize a VALUE on the rollback timeline that replay can't re-derive: a\n   * lag-comp'd collision outcome (its `reckonTime` interp samples age out), an\n   * RNG roll, a server-assigned id. `compute` runs exactly ONCE — on the LIVE\n   * step for this seq — and its result is frozen; every rollback REPLAY of\n   * this seq gets the frozen value back WITHOUT re-running `compute`, so\n   * re-simulation stays deterministic. Auto-pruned when the seq is acked,\n   * cleared on `reset()`.\n   *\n   *     const hit = ctx.memo(() => collide(state, ctx.reckonTime));\n   *     if (hit) state.vx = hit.vx;   // re-applied identically on every replay\n   *\n   * `compute` should return `undefined` for \"nothing this seq\" (stored\n   * sparsely — costs nothing). Call `memo` on EVERY step (let `compute` decide\n   * the value) rather than conditionally, so replay sees the same call shape.\n   * A step that keeps MORE THAN ONE memo disambiguates them with the `key`\n   * overload — `ctx.memo(\"collide\", …)`; the key-less form is ONE shared slot\n   * per step. Two calls landing on the same slot in one step (two key-less\n   * calls, or a repeated key) silently corrupt replay — both call sites get\n   * the one frozen value back; dev diagnostics warn on the collision.\n   *\n   * Prefer reconciled `fields` when the value IS derivable by re-running the\n   * step (sync it, both sides simulate it) — that replays AND self-corrects for\n   * free. Reach for `memo` only when it genuinely can't be re-derived, and\n   * NEVER reconstruct such a value via an `input.at(seq)` lookback (it ages out\n   * the moment the seq is acked — the snap-back this primitive exists to prevent).\n   * For one-shot EVENTS (a sound, a celebration, a spawn) use {@link predict} —\n   * events belong to a channel with settlement; a memo is a value the sim\n   * itself consumes.\n   */\n  memo<T>(compute: () => T): T | undefined;\n  memo<T>(key: string, compute: () => T): T | undefined;\n  /**\n   * Declare an optimistic discrete EVENT the timeline just produced (a goal, a\n   * kill, a pickup) into an event channel (`predict.defineEvent(...)`). Fires\n   * only on the LIVE step — silently skipped on every rollback replay, so a\n   * re-simulated crossing never re-fires feedback. The channel handles the\n   * rest of the event's lifecycle: pending-dedupe, cooldown, server\n   * confirm / ack-anchored auto-reject.\n   *\n   * The sibling of {@link memo}, split by shape: `memo` freezes a VALUE\n   * the replay consumes (use the return); `predict` declares an EVENT for the\n   * world outside the sim (no return — the channel's `onPredict` callback is\n   * the consumer).\n   */\n  predict<T>(sink: PredictSink<T>, payload: T): void;\n}\n\n/**\n * Minimal shape {@link StepContext.predict} emits into — implemented by\n * `PredictedEventChannel` (see `predict.defineEvent(...)`). Declared here,\n * structurally, so this module never imports the channel (no cycle); anything\n * with a `_predictFromSim` can receive sim-born predictions.\n */\nexport interface PredictSink<T> {\n  /**\n   * Receive one sim-born prediction from the LIVE step at `seq`. `acked`\n   * reports the emitting controller's server-ack watermark\n   * (`input.lastProcessed`) — the receiver anchors the entry's settlement to\n   * it: once the server has processed past `seq` without confirming, the\n   * predicted event didn't happen (the event channel's auto-reject).\n   */\n  _predictFromSim(seq: number, payload: T, acked?: () => number): void;\n}\n\n/**\n * Depth of rollback replay currently executing (module-wide). Replay loops are\n * synchronous and never interleave across controllers, so a simple counter is\n * exact. Backstop for event channels: `channel.predict(...)` called from inside\n * a replayed step (instead of the blessed `ctx.predict`) can detect the replay\n * and no-op rather than re-fire feedback.\n */\nlet replayDepth = 0;\n\n/** Is a rollback replay executing right now? @see replayDepth */\nexport function isReplaying(): boolean { return replayDepth > 0; }\n\n/**\n * Options shared by every rollback controller ({@link Reconciler},\n * `SimReconciler`) — the observed input channel, the fixed-step trio, and the\n * reconcile telemetry hooks. Each controller extends this with its own\n * state-shape options (`fields` / `world` + `adopt`/`pose`) and its own `step`\n * signature.\n */\nexport interface RollbackOptions<I> {\n    /**\n     * The input channel to OBSERVE (`room.input(...)`). You mutate + send through\n     * the handle directly (`input.data.x = …; input.send()`); the controller\n     * watches its `sentCount` and steps each new input (predict), and polls\n     * `input.lastProcessed` to reconcile. It never stages or sends — the handle is\n     * the single way to mutate and send input.\n     *\n     * Every `send()` transmits one input (body-less when unchanged, never\n     * suppressed), so the predicted set always equals the server-applied set (no\n     * backdrift). Nothing to configure — the default `room.input()` behavior.\n     */\n    input: InputHandle<I>;\n    /**\n     * Server-synced clock resolving {@link StepContext.reckonTime}'s fallback\n     * (`serverNow()` for unstamped seqs). Injected automatically by\n     * `predict.reconciler()` / `predict.sim()` (the owning Predict's clock —\n     * `room.clock`); pass explicitly only for bare construction. Absent ⇒\n     * unstamped seqs read `ctx.reckonTime === 0` / `lagCompActive === false`.\n     */\n    clock?: { serverNow(): number };\n    /**\n     * Error-decay time constant in ms — the reconcile delta eases out ~63%\n     * per `smoothMs` (see {@link SmoothingOptions.smoothMs}). 0 = hard snap.\n     * Defaults to the server's correction cadence (`input.patchRate`, one\n     * patch interval) so a correction fades before the next one lands —\n     * else 50.\n     */\n    smoothMs?: number;\n    /**\n     * Teleport threshold (world/pose units). When a reconcile's max per-field\n     * |correction| exceeds it, the visual offsets POP to the corrected pose\n     * (error zeroed, interpolation re-seeded) instead of decaying out — the\n     * active-controller mirror of the passive `attachAll` `snap:`: past the\n     * threshold the jump is a discontinuity (teleport / respawn), not an error\n     * to glide across the map. All-or-nothing over the smoothed fields — a\n     * teleport is one event, one cut; popping per field would tear the pose.\n     * Offsets-only: pending inputs still replay from the new truth (correct\n     * rollback). A respawn that lands on the SAME position induces zero\n     * correction and never trips it — it doesn't need to. Size it above\n     * `maxSpeed × patch interval` and below the smallest legitimate teleport.\n     * `0`/unset = off (every correction smooths). For discontinuities with no\n     * positional jump, call `reset()` instead.\n     */\n    snap?: number;\n    /**\n     * Fixed simulation timestep (ms). One input is produced + predicted per step,\n     * so the input rate is tied to this, NOT the frame rate — a 120fps and a 60fps\n     * client emit the same number of inputs. The owning `Predict` reads this to\n     * pace `predict.tick(now)` (which returns how many fixed steps are due).\n     * Defaults to the input handle's server-advertised `stepMs` (`1000/tickRate`).\n     * REQUIRED (via this or the handle's advertised rate): the controller throws\n     * if the fixed step can't be determined, since a wrong `dt` silently diverges\n     * rollback-replay. Pass explicitly only when the prediction step differs from\n     * the input rate.\n     */\n    stepMs?: number;\n    /**\n     * The fixed step in SECONDS used for {@link StepContext.dt} — the dt your\n     * `step` integrates with. MUST equal the server's per-step dt (`1/tickRate`)\n     * for rollback-replay to reproduce the server. Defaults to the input handle's\n     * `input.stepSeconds` (the server's exact `1/tickRate`); else `stepMs / 1000`\n     * (which can be 1 ULP off at some rates). Pass explicitly only to override.\n     */\n    stepSeconds?: number;\n    /**\n     * Physics sub-steps per fixed step for {@link StepContext.subSteps} /\n     * {@link StepContext.subDt} (integer ≥ 1). MUST equal the server's count for\n     * replay to reproduce its trajectory. Defaults to the input handle's\n     * server-advertised `input.subSteps` (from `setFixedTimestep(..., { subSteps\n     * })`) — pass explicitly only to override.\n     */\n    subSteps?: number;\n    /**\n     * Called at the end of each reconcile with the just-acked seq, after the\n     * authoritative state is adopted and unacked inputs replayed. For state the\n     * controller doesn't own — adopting server hit/invuln, pruning per-seq\n     * side-effect records, etc.\n     */\n    onReconcile?: (acked: number) => void;\n    /**\n     * Dev diagnostic: when set, `console.warn` (throttled to ~1/s) whenever a\n     * reconcile's max |correction| exceeds this tolerance (world/pose units),\n     * naming the input seq, the worst field + its delta, and the usual cause. The\n     * reconcile correction already IS the client-vs-server divergence, so this\n     * costs no extra wire traffic. Leave unset (the default) in production.\n     */\n    warnOnDivergence?: number;\n}\n\n/** Reused per-step context — mutated in place each step, no per-step alloc.\n *  `dt`/`dtMs`/sub-step trio are constant; `tick`/`isReplay`/`reckonTime`/\n *  `lagCompActive` change. `memo` is bound once and reads the live\n *  `tick`/`isReplay` at call time. */\ninterface MutableStepContext {\n    dt: number; dtMs: number; tick: number; isReplay: boolean; reckonTime: number;\n    lagCompActive: boolean;\n    subSteps: number; subDt: number; subDtMs: number;\n    memo: <T>(keyOrCompute: string | (() => T), compute?: () => T) => T | undefined;\n    predict: <T>(sink: PredictSink<T>, payload: T) => void;\n}\n\n/**\n * Shared rollback engine — a pure OBSERVER of an input handle. Owns the ack poll,\n * the reconcile scaffold, smooth error correction, `ctx.memo` memoization, and\n * drift telemetry; subclasses fill the state-shape hooks (see the class header).\n *\n * It never stages or sends: you mutate + send through the handle directly\n * (`input.data.x = …; input.send()`), and the controller — subscribed to the\n * handle's `onSend` — runs your `step` for that input right then (so render reads\n * stay pure). The server ack is the one thing it polls (`input.lastProcessed`, in\n * {@link tick}), since that arrives asynchronously over the network. The parent\n * `Predict` paces the room (`predict.tick(now)` returns how many fixed steps are\n * due); this controller derives its own render interpolation from that same\n * `tick(now)` (see {@link renderAlpha}). Not exported from the package — consumers\n * use {@link Reconciler} / `SimReconciler`.\n */\nexport abstract class RollbackController<I = any> {\n    // --- Debug telemetry (no effect on prediction) ---------------------------\n    /** Per-numeric-field correction injected by the most recent reconcile — the\n     *  raw pop (rendered-before − corrected), nonzero even in snap mode. Reused\n     *  object, overwritten each reconcile; read it right after, don't retain. */\n    readonly lastCorrection: Record<string, number> = {};\n    /** Max |{@link lastCorrection}| across fields (world/pose units). ~0 ⇒ the\n     *  prediction matched the server at the acked input. */\n    lastCorrectionMag = 0;\n    /** Increments once per reconcile — lets a consumer detect a fresh one\n     *  (compare against a stored value) without a callback. */\n    reconcileSeq = 0;\n    /** Rolling reconcile drift (world/pose units). `ema` = persistent component\n     *  (steady nonzero ⇒ divergence / rubber-banding); `peak` = recent decaying\n     *  max (a spike over a low `ema` ⇒ network jitter, not divergence). Both ~0 ⇒\n     *  the prediction matched the server. Updated once per reconcile. @see Drift */\n    readonly drift: Drift = newDrift();\n\n    /** Per-field visual offset decaying toward 0 (numeric/pose fields only). */\n    protected readonly error: Record<string, number> = {};\n    /** Previous step's SMOOTHED value (`current + error`) — render interpolates\n     *  from this by {@link alpha} so motion is smooth above the step rate. */\n    protected readonly prev: Record<string, number> = {};\n    /** Reused scratch for reconcile's pre-snap rendered values — no per-reconcile alloc. */\n    protected readonly renderedBefore: Record<string, number> = {};\n\n    protected lastTick = -1;\n    protected lastAcked = 0;\n    /** Cached `input.epoch` — {@link tick} self-resets when the handle's epoch\n     *  moves (reconnect / `input.reset()`), so the app never wires it manually. */\n    private lastEpoch: number;\n    /** Seq floor for replay: inputs sent at/before this aren't replayed (they\n     *  applied to a prior life — set to the sent count on {@link reset}). The\n     *  unacked INPUTS themselves live on the input handle, not here. */\n    protected replayFrom = 0;\n\n    /** Highest input seq the LIVE prediction has stepped. Advanced by {@link catchUp}\n     *  as the app sends (via the `onSend` hook); reconcile brings it back to\n     *  `input.sentCount` after replay. */\n    protected predictedSeq = 0;\n    /** Re-entrancy guard: a user `step` that reads back a predicted value must not\n     *  recurse into {@link catchUp}. */\n    private catching = false;\n    /** Unsubscribe from the input handle's `onSend` (set in the constructor). */\n    private unsubscribeSend: () => void = () => {};\n    /** Render interpolation accumulator: real time (ms) past the latest APPLIED\n     *  step. `renderAlpha() = clamp(renderAcc / stepMs, 0, 1)`. Advanced by frame\n     *  time in {@link tick}, consumed one `stepMs` per applied step in\n     *  {@link catchUp}. While stepping keeps up it equals the exact fixed-timestep\n     *  leftover (smooth) and stays in `[0, stepMs)`. The consume rule (see\n     *  {@link catchUp}) is what makes it robust across all four render regimes —\n     *  steady play, LOAD offset, PAUSE, and a tab-in HITCH — with no cap or special\n     *  case: it grows freely (alpha just clamps at 1, so a pause HOLDS at the latest\n     *  step), and every applied step snaps it back into `[0, stepMs)` so play,\n     *  resume, and hitch all render smooth. */\n    private renderAcc = 0;\n\n    /** Frame counter (one bump per {@link tick}) — pairs with\n     *  {@link clampedReadTick} to catch render reads that precede the frame's\n     *  sends (see {@link noteRenderRead}). */\n    private tickSeq = 0;\n    /** `tickSeq` of the last render read taken while a full step was due but\n     *  unapplied (alpha clamped at 1) — armed by {@link noteRenderRead},\n     *  checked against the current frame by {@link catchUp}. */\n    private clampedReadTick = -1;\n    /** One-shot: the read-before-pump warning already fired for this controller. */\n    private warnedStaleRead = false;\n\n    protected readonly stepCtx: MutableStepContext;\n    /** Ack watermark handed to event sinks with each `ctx.predict` (one shared\n     *  closure — no per-emit alloc). @see PredictSink._predictFromSim */\n    private readonly ackWatermark = () => this.input_.lastProcessed;\n    /** Per-seq memo backing `ctx.memo` — computed live, replayed verbatim, pruned on ack. */\n    protected readonly memos = new MemoStore();\n    protected readonly smoothMs: number;\n    /** Teleport pop threshold — see {@link RollbackOptions.snap}. 0 = off. */\n    private readonly snapThreshold: number;\n    /** The fixed simulation step (ms) this controller predicts at — read by the\n     *  owning `Predict` to pace `predict.tick(now)`. */\n    readonly stepMs: number;\n    protected readonly input_: InputHandle<I>;\n    private readonly onReconcile?: (acked: number) => void;\n    /** Divergence-warning tolerance; `undefined` ⇒ off. @see warnOnDivergence */\n    private readonly warnTolerance?: number;\n    /** Resolves ctx.reckonTime's unstamped fallback. @see RollbackOptions.clock */\n    private readonly clock?: { serverNow(): number };\n\n    constructor(opts: RollbackOptions<I>) {\n        this.input_ = opts.input;\n        this.clock = opts.clock;\n        // Default the decay window to the server's correction cadence (τ = one\n        // patch interval) so corrections ease out before the next one — no stacking.\n        this.smoothMs = opts.smoothMs\n            ?? (this.input_.patchRate ? this.input_.patchRate : 50);\n        this.snapThreshold = opts.snap ?? 0;\n        // Fixed step: prefer an explicit ms, else the handle's server-advertised\n        // rate, else derive from an explicit stepSeconds. A wrong dt silently\n        // diverges rollback-replay, so we refuse to guess (no 60Hz fallback):\n        // the server must advertise a rate (setFixedTimestep/setTimestep) or the\n        // caller must pass stepMs/stepSeconds.\n        const stepMs = opts.stepMs ?? this.input_.stepMs\n            ?? (opts.stepSeconds !== undefined ? opts.stepSeconds * 1000 : undefined);\n        if (stepMs === undefined) {\n            throw new Error(\n                \"@colyseus/sdk reconciler: fixed simulation step is unknown. The \" +\n                \"server room must call setFixedTimestep() (or setTimestep()) so the \" +\n                \"input handle advertises a tick rate, or pass stepMs/stepSeconds \" +\n                \"explicitly — a wrong dt silently diverges rollback-replay.\",\n            );\n        }\n        this.stepMs = stepMs;\n        // ctx.dt: authoritative seconds. Prefer the handle's stepSeconds (server's\n        // exact 1/tickRate); fall back to stepMs/1000 (1-ULP off at some rates).\n        const dt = opts.stepSeconds ?? this.input_.stepSeconds ?? (stepMs / 1000);\n        // subDt = dt/subSteps: same expression as the server's ctx → bit-identical.\n        const subSteps = opts.subSteps ?? this.input_.subSteps ?? 1;\n        this.stepCtx = {\n            dt, dtMs: stepMs, tick: 0, isReplay: false, reckonTime: 0,\n            lagCompActive: false,\n            subSteps, subDt: dt / subSteps, subDtMs: stepMs / subSteps,\n            // key-less form shares one slot per seq (\"\" — see StepContext.memo)\n            memo: (keyOrCompute, compute) => (typeof keyOrCompute === \"string\"\n                ? this.memos.run(this.stepCtx.tick, this.stepCtx.isReplay, keyOrCompute, compute!)\n                : this.memos.run(this.stepCtx.tick, this.stepCtx.isReplay, \"\", keyOrCompute)),\n            // live-only by construction: replayed steps re-run the physics, never the event\n            predict: (sink, payload) => { if (!this.stepCtx.isReplay) sink._predictFromSim(this.stepCtx.tick, payload, this.ackWatermark); },\n        };\n        this.onReconcile = opts.onReconcile;\n        this.warnTolerance = opts.warnOnDivergence;\n        this.lastAcked = this.input_.lastProcessed;\n        this.lastEpoch = this.input_.epoch;\n        // Only inputs sent AFTER this controller exists are predicted (catch-up\n        // starts here); pre-existing sends belong to whatever ran before.\n        this.predictedSeq = this.input_.sentCount;\n        // OBSERVE the input stream: step our predicted simulation for each input\n        // the app sends through the handle. The listener fires synchronously at the\n        // end of `input.send()`, so prediction is current right after — reads\n        // (`value`/`state`/`pose`) never have to trigger a catch-up. Fires after\n        // subclass construction (only on a later send), so the hooks it calls are ready.\n        this.unsubscribeSend = this.input_.onSend(() => this.catchUp());\n    }\n\n    // --- Shared observe/reconcile loop -----------------------------------------\n\n    /**\n     * Advance one render frame (called by the owning `Predict.tick`): stamp the\n     * render clock, reconcile if the server acked new input, then decay the\n     * smooth-correction error. Live inputs are already stepped (eagerly, via the\n     * `onSend` hook), so tick does NOT step them. The interpolation fraction is\n     * derived from elapsed render time vs the fixed step (see {@link renderAlpha}),\n     * so it holds steady at the latest step when stepping pauses.\n     */\n    tick(now: number): void {\n        this.tickSeq++;   // new frame — see noteRenderRead/catchUp\n        const dt = this.lastTick < 0 ? 0 : now - this.lastTick;\n        this.lastTick = now;\n        // Advance the render interpolation clock by real frame time. Consumed per\n        // applied step in catchUp; equals the fixed-step leftover while stepping\n        // keeps up, so interpolation is as smooth as a classic accumulator. It just\n        // grows when nothing consumes it (a PAUSE) — alpha clamps at 1 so the render\n        // HOLDS at the latest step, and catchUp snaps the backlog back on resume.\n        if (dt > 0 && this.stepMs > 0) this.renderAcc += dt;\n\n        // Follow the handle's reset (reconnect / `input.reset()`): the epoch moved,\n        // so our seq cursors describe a dead seq space — without this, predictedSeq\n        // sits above the re-zeroed sentCount and catch-up no-ops (a frozen entity).\n        // Must run BEFORE the ack poll: reset() re-syncs lastAcked, so the poll\n        // below sees no phantom delta. Compare (not +1) absorbs multiple resets.\n        const epoch = this.input_.epoch;\n        if (epoch !== this.lastEpoch) {\n            this.lastEpoch = epoch;\n            this.reset();\n        }\n\n        const acked = this.input_.lastProcessed;\n        if (acked > this.lastAcked) {\n            this.lastAcked = acked;\n            this.reconcile(acked);\n        }\n        this.markDirty();   // render clock advanced → any cached render pose is stale\n\n        if (dt <= 0) return;\n        const k = this.smoothMs <= 0 ? 1 : 1 - Math.exp(-dt / this.smoothMs);\n        for (const f of this.smoothedFields()) this.error[f] -= this.error[f] * k;\n    }\n\n    /**\n     * Render interpolation fraction ∈ [0, 1]: how far into the current step interval\n     * we are — the {@link renderAcc} leftover over `stepMs`. Eases 0→1 across one\n     * step, then CLAMPS at 1 — so when stepping pauses (input gated off on death, a\n     * menu, a freeze) the render HOLDS at the latest step instead of sawtoothing\n     * back to the previous one. Read by the subclasses' `value`/`pose`.\n     */\n    protected renderAlpha(): number {\n        if (this.stepMs <= 0) return 1;\n        const a = this.renderAcc / this.stepMs;\n        return a < 0 ? 0 : a > 1 ? 1 : a;\n    }\n\n    /**\n     * Record a render read (`value`/`pose` — the subclasses call this at the top\n     * of theirs). A read taken while a full fixed step is DUE but not yet applied\n     * (`renderAcc ≥ stepMs`, alpha clamped at 1) returns a one-step-stale pose; if\n     * this frame's `input.send()` calls then arrive AFTER it, the app rendered\n     * stale motion — the read-before-pump wiring bug ({@link catchUp} warns once).\n     * The correct frame order is: `predict.tick(now)` → send the due inputs →\n     * read `value()`/`pose()`. Raw `state`/`world` reads (game logic, hit-reg)\n     * don't come through here and are order-independent. Reads made from inside\n     * controller-driven user code (a `step` or effect during catch-up/replay) are\n     * skipped — they aren't the app's render pass.\n     */\n    protected noteRenderRead(): void {\n        if (this.catching || this.stepMs <= 0 || this.renderAcc < this.stepMs) return;\n        this.clampedReadTick = this.tickSeq;\n    }\n\n    /**\n     * Step every input sent since the last catch-up (predict each, zero-latency).\n     * Driven by the input handle's `onSend` hook (subscribed in the constructor),\n     * so it runs synchronously at the end of each `input.send()` — normally\n     * stepping exactly the one just-sent input. The loop (rather than a single\n     * step) makes it robust to a missed notification. Idempotent once caught up.\n     */\n    protected catchUp(): void {\n        const sent = this.input_.sentCount;\n        if (this.predictedSeq >= sent || this.catching) return;\n        // A render value was read earlier THIS frame at clamped alpha, and the\n        // frame's sends are only arriving now — the app rendered a one-step-stale\n        // pose (frame jitter becomes visible stutter on fast objects). Warn once.\n        if (this.clampedReadTick === this.tickSeq && !this.warnedStaleRead) {\n            this.warnedStaleRead = true;\n            warnReadBeforePump();\n        }\n        this.catching = true;\n        this.stepCtx.isReplay = false;           // live forward steps\n        for (let seq = this.predictedSeq + 1; seq <= sent; seq++) {\n            const inp = this.input_.at(seq);\n            if (inp !== undefined) {\n                // Snapshot the pre-step smoothed value so the render lerps prev →\n                // current across this step by `renderAlpha()`.\n                this.snapshotPrev();\n                this.runStep(seq, inp);          // predict from the round-tripped wire input\n                this.refreshRender();\n                // Consume one step of the render clock, resyncing it into [0, stepMs)\n                // so the interpolation is smooth across every regime:\n                //   • steady play: the clock is already < stepMs after each step, so\n                //     this leaves the exact fixed-step leftover (both branches skip).\n                //   • LOAD offset (reconciler born mid-frame, first tick dt=0 → clock\n                //     lags the pacing accumulator): the subtract goes negative → snap\n                //     to 0, resyncing instead of drifting out of phase.\n                //   • PAUSE / tab-in HITCH (input gated off, so the clock grew for\n                //     many frames with no consume): a WHOLE step of lead remains after\n                //     the subtract → drop the stale whole-steps (%=), so the resuming\n                //     step renders from the real leftover, not a pinned alpha=1.\n                this.renderAcc -= this.stepMs;\n                if (this.renderAcc < 0) this.renderAcc = 0;\n                else if (this.renderAcc >= this.stepMs) this.renderAcc %= this.stepMs;\n            }\n            this.predictedSeq = seq;\n        }\n        this.catching = false;\n    }\n\n    /**\n     * Set the shared step context for `seq` (tick + reckon instant), then let the\n     * subclass run the user step. Used by both the live input path and the\n     * reconcile replay loop, so the exact same step invocation drives forward and\n     * rollback. `isReplay` is set by the caller before this.\n     */\n    protected runStep(seq: number, input: I): void {\n        this.stepCtx.tick = seq;\n        // Per-seq stamp when lag-comp stamped this seq (same value live + on\n        // every replay); else resolve to the live serverNow() — the fallback\n        // every consumer previously hand-wrote. 0 only with no clock (bare tests).\n        const raw = this.input_.reckonTimeAt(seq);\n        this.stepCtx.lagCompActive = raw > 0;\n        this.stepCtx.reckonTime = raw > 0 ? raw\n            : this.clock !== undefined ? this.clock.serverNow() : 0;\n        this.applyStep(input);\n    }\n\n    /**\n     * Adopt the authoritative state and replay unacked inputs. Captures the\n     * rendered pose first, adopts truth, replays the still-unacked inputs, then\n     * re-bases the error so the rendered pose is UNCHANGED at this instant — the\n     * correction then decays out via {@link tick}, hiding the pop.\n     *\n     * WIRE-PRECISION SHORT-CIRCUIT: when {@link truthMatchesAt} reports the\n     * prediction at `acked` is wire-indistinguishable from the decoded truth,\n     * adopt+replay are SKIPPED and the client keeps its own (full-precision)\n     * state. This is what makes lossy wire types (float32 / auto `number`)\n     * safe for reconciled fields: adopting a rounded truth over a correct\n     * prediction injects rounding noise into the restore point, and at a\n     * knife-edge sim branch (a grounded check, a step-up test) that epsilon\n     * flips the branch — a real mispredict born from the wire, not the sim.\n     * Skipping is also the fast path: a clean reconcile costs one per-field\n     * compare instead of adopt + replay × pending. Ack bookkeeping still runs\n     * (memo prune, `onReconcile`, zero-correction telemetry).\n     */\n    protected reconcile(acked: number): void {\n        // Drift telemetry runs only when watched — `warnOnDivergence` set or the\n        // debug bundle loaded — so production that uses neither pays nothing.\n        const diag = this.warnTolerance !== undefined || diagnosticsActive();\n\n        if (this.truthMatchesAt(acked)) {\n            if (diag) {\n                for (const f of this.smoothedFields()) this.lastCorrection[f] = 0;\n                this.lastCorrectionMag = 0;\n                updateDrift(this.drift, 0);   // a perfect reconcile — decay the rolling drift\n            }\n            this.reconcileSeq++;\n            this.memos.prune(acked);\n            this.onReconcile?.(acked);\n            return;\n        }\n\n        // Smoothed value before reconcile (NON-interpolated): keeping `prev`\n        // intact lets step-smoothing continue, and a prediction that MATCHED the\n        // server induces ZERO new correction (error stays 0).\n        const renderedBefore = this.renderedBefore;   // reused scratch (no per-reconcile alloc)\n        for (const f of this.smoothedFields()) renderedBefore[f] = this.readCurrent(f) + this.error[f];\n\n        this.adoptTruth();\n\n        // Replay still-unacked inputs from the handle's buffer (controller keeps\n        // no copies). Skip anything sent at/before the last reset — it applied to\n        // a prior life (respawn) and must not re-run.\n        const from = Math.max(acked, this.replayFrom);\n        this.stepCtx.isReplay = true;            // rollback re-sim of buffered inputs\n        this.catching = true;   // guard: replay-driven user code isn't a render pass, and must not recurse\n        replayDepth++;          // backstop for channel.predict() called without ctx (see isReplaying)\n        try {\n            for (let seq = from + 1; seq <= this.input_.sentCount; seq++) {\n                const inp = this.input_.at(seq);\n                if (inp !== undefined) this.runStep(seq, inp);\n            }\n        } finally {\n            replayDepth--;\n        }\n        this.catching = false;\n        this.refreshRender();\n        // Replay reconstructed the predicted state up to the latest send, so the\n        // live cursor is now current — subsequent catch-up has nothing to do.\n        this.predictedSeq = this.input_.sentCount;\n\n        // Re-base `error` so the smoothed value is unchanged at this instant, then\n        // decays out via tick(). `prev` untouched (interpolation keeps flowing).\n        // The raw correction (pre-smoothing pop) doubles as a debug gauge —\n        // recorded regardless of smoothing mode so telemetry sees it either way.\n        // The `error` rebase below is the REAL reconciliation and always runs.\n        const hard = this.smoothMs <= 0;\n        const wantMag = diag || this.snapThreshold > 0;\n        let mag = 0;\n        for (const f of this.smoothedFields()) {\n            const correction = renderedBefore[f] - this.readCurrent(f);\n            this.error[f] = hard ? 0 : correction;\n            if (wantMag) {\n                const a = correction < 0 ? -correction : correction;\n                if (a > mag) mag = a;\n            }\n            if (diag) this.lastCorrection[f] = correction;\n        }\n        // Past the snap threshold the correction is a TELEPORT, not an error: pop\n        // every smoothed field to the corrected pose (see RollbackOptions.snap).\n        // `prev` must re-seed too — zeroing `error` alone still lerps one render\n        // step from the pre-jump pose (a one-frame glide across the map).\n        const popped = this.snapThreshold > 0 && mag > this.snapThreshold;\n        if (popped) {\n            for (const f of this.smoothedFields()) {\n                this.error[f] = 0;\n                this.prev[f] = this.readCurrent(f);\n            }\n        }\n        this.reconcileSeq++;\n        if (diag) {\n            this.lastCorrectionMag = mag;\n            // A detected teleport is not divergence — feeding it to the drift EMA\n            // would false-fire warnOnDivergence on every respawn.\n            if (!popped) {\n                updateDrift(this.drift, mag);\n                if (this.warnTolerance !== undefined && classifyDrift(this.drift, this.warnTolerance) === \"diverging\") {\n                    warnDivergence(acked, this.lastCorrection, this.drift.ema, this.warnTolerance);\n                }\n            }\n        }\n\n        // Drop ctx.memo entries for acked seqs (they won't replay again) BEFORE\n        // user code — replay only touches seqs > acked, so this never removes a\n        // memo a still-pending replay needs.\n        this.memos.prune(acked);\n        this.onReconcile?.(acked);\n    }\n\n    /** Number of unacknowledged inputs currently buffered. */\n    get pendingCount(): number {\n        return this.input_.pendingCount;\n    }\n\n    /**\n     * Re-seed local state from the authoritative instance(s): clears the error\n     * offsets, memos, and the in-flight window (prior-life sends won't replay).\n     *\n     * Mostly the library's job: the controller self-resets when the input handle\n     * resets (reconnect / `input.reset()` — it polls `input.epoch`), and a\n     * {@link RollbackOptions.snap} threshold pops big positional jumps\n     * (teleport / respawn) with no reset at all. Call this yourself only for\n     * discontinuities the library can't see: a schema field changed meaning with\n     * no positional jump and no input flow (a round flip in a backgrounded tab),\n     * app-side context went stale (a map swap), or in-flight inputs the app\n     * knows are void (death).\n     */\n    reset(): void {\n        this.reseedState();\n        resetDrift(this.drift);   // fresh life — don't carry the prior life's drift\n        // Forget in-flight inputs from the prior life — don't replay or re-step them.\n        this.replayFrom = this.input_.sentCount;\n        this.predictedSeq = this.input_.sentCount;\n        this.lastAcked = this.input_.lastProcessed;\n        this.renderAcc = 0;   // fresh life renders at the reseeded state (alpha 0)\n        this.memos.clear();   // prior life's memoized values must not replay\n        this.markDirty();\n    }\n\n    /** Set when {@link dispose} is called — the owning Predict drops a `dead`\n     *  child from its drive list on the next tick. */\n    dead = false;\n\n    /** Teardown hooks run synchronously by {@link dispose} (after `dead` is\n     *  set) — the owning Predict restores its `value()` overlay here, so bound\n     *  reads fall back the instant the controller dies, not a tick later. */\n    private disposedHooks: Array<() => void> = [];\n\n    /** Register a teardown hook for {@link dispose}. Idempotent-safe: hooks run\n     *  once (the list is drained). */\n    onDisposed(hook: () => void): void { this.disposedHooks.push(hook); }\n\n    /** Stop being driven by the owning Predict and unsubscribe from the input\n     *  handle's sends. Runs {@link onDisposed} hooks synchronously. */\n    dispose(): void {\n        this.dead = true;\n        this.unsubscribeSend();\n        for (const hook of this.disposedHooks.splice(0)) hook();\n    }\n\n    // --- Subclass hooks --------------------------------------------------------\n\n    /** The numeric fields that get smooth error correction (Reconciler's numeric\n     *  `fields`, SimReconciler's pose fields). */\n    protected abstract smoothedFields(): readonly string[];\n    /** Current predicted value of one smoothed field (`local[f]` / `curPose[f]`). */\n    protected abstract readCurrent(field: string): number;\n    /** Seed the server's authoritative truth into the predicted state, BEFORE the\n     *  unacked inputs are replayed on top of it. */\n    protected abstract adoptTruth(): void;\n    /** Run the user `step` for one buffered input (live or replay). The shared\n     *  {@link runStep} has already set `stepCtx.tick`/`reckonTime`; `isReplay` is\n     *  set by the caller. */\n    protected abstract applyStep(input: I): void;\n    /** Snapshot the pre-step SMOOTHED value into `prev` so a subsequent live step\n     *  interpolates from it by {@link renderAlpha}. Called once before each live\n     *  catch-up step (Reconciler reads `local + error`; SimReconciler `curPose + error`). */\n    protected abstract snapshotPrev(): void;\n    /** Re-seed local state from the authoritative instance(s) on a hard reset. */\n    protected abstract reseedState(): void;\n    /**\n     * Is the prediction AT the acked seq wire-indistinguishable from the decoded\n     * authoritative truth? `true` short-circuits {@link reconcile} (no adopt, no\n     * replay — the client's own full-precision state stands). Requires per-seq\n     * predicted-state history plus knowledge of each field's wire precision, so\n     * only the flat `Reconciler` implements it (its truth is a declared `fields`\n     * list on one schema instance); `SimReconciler` can't see through its\n     * `adopt`/`pose` closures and inherits this default.\n     */\n    protected truthMatchesAt(_acked: number): boolean { return false; }\n\n    /** Refresh any derived render state after a step (SimReconciler re-samples its\n     *  pose). Called after each live catch-up step and once after reconcile replay.\n     *  Default no-op (the flat Reconciler mutates its state in place). */\n    protected refreshRender(): void {}\n    /** Invalidate any cached render pose after state/alpha changes. Default no-op\n     *  (the flat Reconciler recomputes `value()` on read). */\n    protected markDirty(): void {}\n}\n"],"names":["diagnosticsActive","warnMemoCollision","newDrift","warnReadBeforePump","updateDrift","classifyDrift","warnDivergence","resetDrift"],"mappings":"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"}