{"version":3,"file":"predictedSpawns.cjs","sources":["../../src/predict/predictedSpawns.ts"],"sourcesContent":["/**\n * Predicted-spawn store — optimistic, server-reconciled *entities* (a fired\n * bullet, a thrown grenade, a dropped item), the entity-level counterpart to\n * {@link PredictedEvents}' discrete keys.\n *\n * The pattern the shooter hand-rolls today:\n *\n *   - On fire, render a client-only bullet immediately (no ~RTT wait).\n *   - Skip rendering the server's copy of *my own* bullets (`if (ownerId ===\n *     me) continue`) to avoid a duplicate.\n *   - Never reconcile predicted → authoritative, because the server assigns\n *     the id and the client can't correlate them.\n *   - Hand-write mispredict cleanup (\"server rejected the shot → ghost\").\n *\n * `PredictedSpawns` collapses all of that. Predicted locals live **outside**\n * the schema collection (in this store); the authoritative entities stay in\n * the decoder-owned collection. Correlation happens *post-decode* — when the\n * server entity's `onAdd` fires, its fields are populated, so a pending local\n * is matched to it ({@link PredictedSpawnsOptions.correlate}) and the two\n * collapse onto one logical {@link SpawnEntry} with a **stable `id`**.\n *\n * The handoff is seamless not by sharing a JS object (that would need a\n * `@colyseus/schema` change) but by keeping `id` constant across the\n * predicted → authoritative transition: the renderer keys its sprite on\n * `entry.id` and reads `entry.server ?? entry.local`, so the predicted bullet\n * becomes the authoritative one with no remove/re-add churn. This is the one\n * contract the render loop must follow.\n *\n * Lifecycle:\n *   1. {@link spawn} — push an optimistic local; renders instantly.\n *   2. `onAdd` (mine + matched) — server confirms; same `id`, `server` set.\n *   3. {@link prune} — a local with no match within TTL was a mispredict\n *      (server rejected the action); drop it, the sprite reverts.\n *   4. `onRemove` — the authoritative entity despawned; drop the entry.\n *\n * Driven automatically when created via `predict.spawns(...)` — the owning\n * {@link Predict} ticks ({@link tick}, dead-reckons pending locals) and prunes\n * ({@link prune}) it each frame. For standalone use, call {@link attach} with a\n * subscribe function and drive `tick`/`prune` yourself.\n */\nimport { DEFAULT_TTL_POLICY } from \"./predictedEvents.ts\";\n\n/**\n * Minimal clock shape consumed by the store — a strict subset of\n * `RoomClockLike`, declared locally so this module stays portable without an\n * intra-package dependency on `../RoomClock.ts`.\n */\nexport interface PredictedSpawnsClock {\n    /** Lag-invariant timestamp source for spawn `at` and TTL comparison. */\n    serverNow(): number;\n    /** Current smoothed round-trip time, fed to the dynamic TTL policy. */\n    smoothedRtt(): number;\n}\n\n/**\n * How a candidate server entity is paired to a pending local prediction:\n *   - `\"fifo\"` (default): consume the oldest unmatched prediction. Zero server\n *     cooperation; relies only on spawn order. Fragile only if the server\n *     rejects this client's actions *out of order*.\n *   - predicate: match the first pending local for which it returns true —\n *     e.g. `(local, server) => Math.abs(server.spawnTime - local.spawnTime) <\n *     TOL`. Robust to out-of-order without any extra wire field.\n */\nexport type SpawnCorrelation<S, L> = \"fifo\" | ((local: L, server: S) => boolean);\n\n/** Options for {@link PredictedSpawns}. `S` is the server element type; `L` the\n *  predicted-local shape (defaults to `Partial<S>` — annotate a callback param\n *  or pass `L` explicitly to model client-only fields). */\nexport interface PredictedSpawnsOptions<S = unknown, L = Partial<S>, D = undefined> {\n    /**\n     * Which incoming server entities are this client's to correlate. Entities\n     * for which this returns false are surfaced as *foreign* (server-only)\n     * entries and never consume a prediction — e.g. `s => s.ownerId ===\n     * room.sessionId`. Omit to treat every server entity as correlatable\n     * (single-owner rooms).\n     */\n    owned?: (server: S) => boolean;\n\n    /** Pairing strategy. Defaults to `\"fifo\"`. */\n    correlate?: SpawnCorrelation<S, L>;\n\n    /**\n     * Server-clock spawn instant of an authoritative entity (e.g. `r =>\n     * r.bornMs`). When set, confirmation measures the entry's **input lead**\n     * — `spawnTime(server) − entry.at` — the exact uplink + input-buffering\n     * delay between the client predicting the spawn and the server executing\n     * it. Measured per spawn; no RTT/2 estimating.\n     *\n     * Why: a lag-compensated projectile is hit-tested through the *shooter's*\n     * rewound view, so the trajectory the shooter predicted at fire time is\n     * the one the server judges. Rendering the confirmed entity at reckoned\n     * server-present would snap it back by `lead × velocity` and re-fly that\n     * stretch. `predict.spawns(..., { fields })` reckons owned entities with\n     * this lead so the confirmed entity continues the prediction's flight\n     * seamlessly; foreign entities (never predicted, `lead = 0`) render at\n     * server-present as usual.\n     */\n    spawnTime?: (server: S) => number;\n\n    /**\n     * Advance a *pending* (not-yet-confirmed) local each frame. `dt` is seconds\n     * since the previous {@link tick}. Confirmed entries read from the server\n     * entity and are never stepped.\n     */\n    step?: (local: L, dt: number) => void;\n\n    /**\n     * Eviction window for unmatched predictions, in ms, given the current RTT.\n     * A pending local older than this with no server match is a mispredict\n     * (server rejected the action) and is dropped on {@link prune}. Defaults to\n     * {@link DEFAULT_TTL_POLICY} — `max(2 × rtt, 600ms)`.\n     */\n    ttl?: (rtt: number) => number;\n\n    /** Invoked when a prediction is dropped as a mispredict (TTL expiry). */\n    onReject?: (local: L, id: number) => void;\n\n    /**\n     * Per-entry render-scratch factory. Called once when each logical entry is\n     * created — both predicted spawns and foreign/server-native adds. The\n     * returned object is exposed as `entry.data` and dropped automatically when\n     * the entry dies (handoff preserves it; remove/prune/cancel discard it).\n     *\n     * Lets the render layer keep id-keyed scratch — a catch-up accumulator, a\n     * hit/hidden latch — on a *server-owned* entry without a side map (you can\n     * hang fields on your own `entry.local`, but not on the decoder's\n     * `entry.server`, which can be recycled on remove/re-add). `D` is inferred\n     * from the return type; omit it and `entry.data` is `undefined`.\n     */\n    data?: () => D;\n}\n\n/**\n * A merged logical entity. Exactly one per logical spawn, regardless of\n * predicted/authoritative status. Render via `server ?? local`, keyed on `id`.\n */\nexport interface SpawnEntry<S = unknown, L = Partial<S>, D = undefined> {\n    /** Stable across the predicted → authoritative handoff. Key sprites on it. */\n    readonly id: number;\n    /** Authoritative instance; set once correlated (and for foreign entities). */\n    server?: S;\n    /** Predicted local; present until pruned or (for foreign entries) absent. */\n    local?: L;\n    /** `\"pending\"` = local only; `\"confirmed\"` = authoritative entity present. */\n    readonly state: \"pending\" | \"confirmed\";\n    /** Measured input lead (ms) — `spawnTime(server) − at`, set at confirmation\n     *  when {@link PredictedSpawnsOptions.spawnTime} is configured. 0 for\n     *  foreign entries and while pending. */\n    readonly leadMs: number;\n    /** Per-entry render scratch from {@link PredictedSpawnsOptions.data}; the\n     *  reference is stable for the entry's life (mutate its fields freely) and\n     *  dropped with the entry. `undefined` when no `data` factory was given. */\n    readonly data: D;\n}\n\n/** Handle returned by {@link PredictedSpawns.spawn}. */\nexport interface SpawnHandle<L = unknown, D = undefined> {\n    /** The logical id assigned to this prediction (survives handoff). */\n    readonly id: number;\n    /** The predicted local instance. */\n    readonly local: L;\n    /** This entry's render scratch (same object as `entry.data`). */\n    readonly data: D;\n    /** Drop this prediction (e.g. a local cancel or rollback). No-op once the entry\n     *  has been confirmed by its authoritative `onAdd`, so a late/duplicate rollback\n     *  can't nuke a legitimate entity. */\n    cancel(): void;\n    /** Mark the prediction accepted: exempt the still-pending entry from TTL\n     *  eviction (its authoritative patch may land a tick after the confirmation). */\n    accept(): void;\n}\n\n/** Internal entry — the live object reused across handoff. Carries `at` for\n *  TTL bookkeeping in addition to the public {@link SpawnEntry} fields. */\ninterface InternalEntry<S, L, D> {\n    id: number;\n    server: S | undefined;\n    local: L | undefined;\n    state: \"pending\" | \"confirmed\";\n    /** Spawn time (`serverNow`) — undefined for entries with no prediction. */\n    at: number | undefined;\n    /** Measured input lead (ms) — see {@link PredictedSpawnsOptions.spawnTime}. */\n    leadMs: number;\n    /** Set by `accept()` — a confirmed-but-slow spawn exempt from TTL eviction\n     *  while its authoritative `onAdd` is still in flight. */\n    accepted: boolean;\n    data: D;\n}\n\nexport class PredictedSpawns<S = unknown, L = Partial<S>, D = undefined> {\n    private opts: PredictedSpawnsOptions<S, L, D>;\n    private clock: PredictedSpawnsClock | null;\n    private correlate: SpawnCorrelation<S, L>;\n    private ttl: (rtt: number) => number;\n\n    /** Master index: every live entry (pending + confirmed + foreign), in\n     *  insertion order — FIFO correlation walks this picking the oldest\n     *  still-`pending` entry. */\n    private byId = new Map<number, InternalEntry<S, L, D>>();\n    /** Secondary index: authoritative instance → entry, for `onRemove`. */\n    private byServer = new Map<S, InternalEntry<S, L, D>>();\n\n    private nextId = 1;\n    private lastTickAt: number | undefined;\n    private detach: (() => void) | undefined;\n\n    /** Set by {@link dispose}; the owning Predict drops a `dead` child on its\n     *  next tick. */\n    dead = false;\n\n    constructor(opts: PredictedSpawnsOptions<S, L, D> = {}, clock: PredictedSpawnsClock | null = null) {\n        this.opts = opts;\n        this.clock = clock;\n        this.correlate = opts.correlate ?? \"fifo\";\n        this.ttl = opts.ttl ?? DEFAULT_TTL_POLICY;\n    }\n\n    /**\n     * Wire the store to a collection's add/remove stream. `subscribe` receives\n     * the store's handlers and returns a detacher. Called once by\n     * `predict.spawns(...)`; call it yourself for standalone use, e.g.\n     *\n     * ```ts\n     * const cb = Callbacks.get(room);\n     * spawns.attach((onAdd, onRemove) => {\n     *   const a = cb.onAdd(\"bullets\", onAdd);\n     *   const r = cb.onRemove(\"bullets\", onRemove);\n     *   return () => { a?.(); r?.(); };\n     * });\n     * ```\n     */\n    attach(\n        subscribe: (\n            onAdd: (server: S, key: string | number) => void,\n            onRemove: (server: S, key: string | number) => void,\n        ) => () => void,\n    ): void {\n        this.detach?.();\n        this.detach = subscribe(this.handleAdd, this.handleRemove);\n    }\n\n    /** Record an optimistic local spawn. Returns a handle for cancellation. */\n    spawn(local: L): SpawnHandle<L, D> {\n        const id = this.nextId++;\n        const data = this.makeData();\n        const entry: InternalEntry<S, L, D> = { id, server: undefined, local, state: \"pending\", at: this.now(), leadMs: 0, accepted: false, data };\n        this.byId.set(id, entry);\n        return {\n            id,\n            local,\n            data,\n            // Pending-safe: a confirmed entry is owned by the authoritative entity,\n            // so a late rollback must not delete it.\n            cancel: () => {\n                const e = this.byId.get(id);\n                if (e && e.state === \"pending\") { this.byId.delete(id); }\n            },\n            accept: () => {\n                const e = this.byId.get(id);\n                if (e) { e.accepted = true; }\n            },\n        };\n    }\n\n    private handleAdd = (server: S, _key: string | number): void => {\n        // Decoder may re-fire for an instance already tracked (immediate replay\n        // + a later op); ignore the second sighting.\n        if (this.byServer.has(server)) { return; }\n\n        // fifo / predicate match, or a foreign (server-only) entity.\n        const matched = this.isOwned(server) ? this.takeMatch(server) : undefined;\n        if (matched) {\n            this.confirmEntry(matched, server);\n        } else {\n            // Foreign entity, or mine-without-a-prediction (joined late / the\n            // server spawned it on my behalf) — surfaced as server-only.\n            const entry: InternalEntry<S, L, D> = { id: this.nextId++, server, local: undefined, state: \"confirmed\", at: undefined, leadMs: 0, accepted: false, data: this.makeData() };\n            this.byId.set(entry.id, entry);\n            this.byServer.set(server, entry);\n        }\n    };\n\n    /** Transition a matched pending entry to confirmed in place (the live object\n     *  is reused across handoff — same `id`). */\n    private confirmEntry(entry: InternalEntry<S, L, D>, server: S): void {\n        entry.server = server;\n        entry.state = \"confirmed\";\n        const spawnTime = this.opts.spawnTime;\n        if (spawnTime !== undefined && entry.at !== undefined) {\n            entry.leadMs = spawnTime(server) - entry.at;\n        }\n        this.byServer.set(server, entry);\n    }\n\n    private handleRemove = (server: S, _key: string | number): void => {\n        const entry = this.byServer.get(server);\n        if (entry) {\n            this.byServer.delete(server);\n            this.byId.delete(entry.id);\n        }\n    };\n\n    /** Find a pending local to pair with `server`, per the correlation\n     *  strategy. The matched entry transitions in place (not removed). */\n    private takeMatch(server: S): InternalEntry<S, L, D> | undefined {\n        const corr = this.correlate;\n        // \"fifo\": claim the oldest pending.\n        if (typeof corr !== \"function\") {\n            for (const entry of this.byId.values()) {\n                if (entry.state === \"pending\") { return entry; } // oldest pending\n            }\n            return undefined;\n        }\n        for (const entry of this.byId.values()) {\n            if (entry.state === \"pending\" && corr(entry.local as L, server)) { return entry; }\n        }\n        return undefined;\n    }\n\n    private isOwned(server: S): boolean {\n        return this.opts.owned ? this.opts.owned(server) : true;\n    }\n\n    private makeData(): D {\n        return this.opts.data ? this.opts.data() : (undefined as D);\n    }\n\n    /**\n     * Advance pending locals via {@link PredictedSpawnsOptions.step}.\n     * Confirmed/foreign entries are left to the authoritative state.\n     *\n     * With a clock, `dt` is derived on the clock's `serverNow()` axis — the\n     * SAME axis `at` (and thus the measured input lead) live on — so a pending\n     * local's flight and the confirmed entity's lead-reckon are the same\n     * expression by construction: the handoff cannot jump, no matter how\n     * biased or drifty the client's server-clock estimate is. Without a\n     * clock, `now` (typically `performance.now()`) paces the step.\n     */\n    tick(now: number = performance.now()): void {\n        const step = this.opts.step;\n        const t = this.clock !== null ? this.clock.serverNow() : now;\n        if (step !== undefined && this.lastTickAt !== undefined) {\n            const dt = Math.max(0, (t - this.lastTickAt) / 1000);\n            if (dt > 0) {\n                for (const entry of this.byId.values()) {\n                    if (entry.state === \"pending\") { step(entry.local as L, dt); }\n                }\n            }\n        }\n        this.lastTickAt = t;\n    }\n\n    /** Drop pending locals older than the TTL policy — mispredicts the server\n     *  never confirmed. Uses `serverNow()` and the RTT-aware TTL. */\n    prune(): void {\n        if (this.byId.size === 0) { return; }\n        const now = this.now();\n        const ttl = this.ttl(this.clock?.smoothedRtt() ?? 0);\n        for (const entry of this.byId.values()) {\n            // `accepted` entries are server-confirmed and awaiting their (slightly\n            // late) authoritative patch — never a mispredict, so skip eviction.\n            if (entry.state === \"pending\" && !entry.accepted && entry.at !== undefined && now - entry.at > ttl) {\n                this.byId.delete(entry.id);\n                this.opts.onReject?.(entry.local as L, entry.id);\n            }\n        }\n    }\n\n    /** Iterate the merged view — exactly one entry per logical entity. */\n    entries(): IterableIterator<SpawnEntry<S, L, D>> {\n        return this.byId.values() as IterableIterator<SpawnEntry<S, L, D>>;\n    }\n\n    /** The entry an authoritative instance collapsed onto (or was surfaced as,\n     *  for foreign entities) — e.g. to reach `leadMs`/`data` from a collection\n     *  callback that only has the server instance. */\n    entryFor(server: S): SpawnEntry<S, L, D> | undefined {\n        return this.byServer.get(server) as SpawnEntry<S, L, D> | undefined;\n    }\n\n    /**\n     * Unified field read across the predicted → authoritative handoff:\n     * pending entries read the stepped local; confirmed entries read the\n     * authoritative instance through the bound reader — `predict.value()`\n     * (reckoned, lead-aware) when created via `predict.spawns(...)` with\n     * `fields`, a raw field read otherwise. Render from this and the handoff\n     * is invisible: same `id`, same timeline, one code path.\n     */\n    value(entry: SpawnEntry<S, L, D>, field: keyof S & string): number {\n        if (entry.server !== undefined) { return this.readServer(entry.server, field); }\n        return (entry.local as Record<string, number>)[field];\n    }\n\n    /** Route confirmed-entry `value()` reads (wired by `predict.spawns` to its\n     *  reckon slots; standalone stores keep the raw default). */\n    bindReader(read: (server: S, field: keyof S & string) => number): void {\n        this.readServer = read;\n    }\n\n    private readServer: (server: S, field: keyof S & string) => number =\n        (server, field) => (server as Record<string, number>)[field as string];\n\n    /** Is `id` still live this frame? Useful for despawning stale sprites. */\n    alive(id: number): boolean {\n        return this.byId.has(id);\n    }\n\n    /** Total live entries (pending + confirmed + foreign). */\n    get size(): number {\n        return this.byId.size;\n    }\n\n    /** Drop all predictions and tracked entries (keeps the subscription). */\n    clear(): void {\n        this.byId.clear();\n        this.byServer.clear();\n    }\n\n    /** Detach from the collection, drop everything, and mark dead so the owning\n     *  Predict stops driving it. */\n    dispose(): void {\n        this.dead = true;\n        this.detach?.();\n        this.detach = undefined;\n        this.clear();\n    }\n\n    private now(): number {\n        return this.clock?.serverNow() ?? performance.now();\n    }\n}\n"],"names":["DEFAULT_TTL_POLICY"],"mappings":"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"}