{"version":3,"file":"RoomInput.cjs","sources":["../../src/input/RoomInput.ts"],"sourcesContent":["import { decode, Iterator, Reflection } from '@colyseus/schema';\nimport { InputEncoder } from '@colyseus/schema/input';\nimport { InputFlags } from '@colyseus/shared-types';\n\nimport { InputHandleImpl, type InputHandle, type InputOptions } from './InputHandle.ts';\nimport { NULL_CLOCK, RoomClockImpl } from '../RoomClock.ts';\n\n// Type-only: avoids a runtime import cycle (Room imports RoomInput as a value).\nimport type { Room } from '../Room.ts';\n\n/**\n * Owns all per-room input state, kept off the {@link Room} class itself: the\n * schema constructor recovered from the JOIN handshake, the server-advertised\n * stamp/rate flags, and the lazily-created {@link InputHandle}.\n *\n * Created lazily by {@link Room} only when the room declares input (an\n * `INPUT_*` handshake section arrives) or the app calls `room.input(...)`.\n * Rooms that never use input (chat / lobby / turn-based) never allocate one.\n * @internal\n */\nexport class RoomInput {\n    #room: Room;\n\n    // Impl type (not the public interface) so the TIMED decode can feed it the\n    // server ack via the internal `ackInput()`.\n    #handle?: InputHandleImpl<any>;\n\n    // First-call context, kept only to diagnose later room.input(options) calls\n    // whose options are ignored (the handle is created once — first call wins).\n    #options?: InputOptions<any>;\n    #encoder?: InputEncoder<any>;\n    #warnedIgnoredOptions = false;\n\n    /**\n     * Schema constructor recovered via Reflection from the server's handshake\n     * (the `INPUT_REFLECTION` tagged section). Falls back to `undefined` when\n     * the server room didn't call `defineInput()`.\n     *\n     * Typed as `new () => any` (not `Schema`) on purpose — pinning to this\n     * SDK's Schema type would clash with user instances coming from a\n     * different copy of `@colyseus/schema` under multi-version installs.\n     */\n    #ctorFromReflection?: new () => any;\n\n    /** `true` when the handshake advertised the SNAPSHOT-timeline stamp\n     *  (`INPUT_OPTIONS`, `InputFlags.RENDER_TIME`). */\n    #stampRender = false;\n\n    /** `true` when the handshake advertised the RECKON-timeline stamp\n     *  (`INPUT_OPTIONS`, `InputFlags.RECKON_TIME`). Set together with\n     *  {@link #stampRender} ⇒ the 6-byte `[reckonTime][renderDelta]` prefix. */\n    #stampReckon = false;\n\n    /** Server-advertised fixed simulation/input step rate (Hz) from\n     *  `defineInput({ tickRate })`. */\n    #tickRate?: number;\n\n    /** Server-advertised state-patch interval (ms) = the reconcile cadence. */\n    #patchRate?: number;\n\n    /** Server-advertised physics sub-steps per input tick\n     *  (`setFixedTimestep(..., { subSteps })`). */\n    #subSteps?: number;\n\n    constructor(room: Room) {\n        this.#room = room;\n    }\n\n    /** Snapshot cadence (ms), so {@link Room} can feed `clock.setPatchInterval`. */\n    get patchRate(): number | undefined {\n        return this.#patchRate;\n    }\n\n    /**\n     * Decode the `INPUT_REFLECTION` handshake section: install schema-builder\n     * field descriptors on the reconstructed class so {@link InputEncoder} can\n     * read its `$values` and emit non-empty packets, then cache the ctor.\n     *\n     * INPUT_REFLECTION is also the signal that the server called `defineInput()`\n     * and will emit TIMED-prefixed state messages — so swap the default stub\n     * clock for a real {@link RoomClockImpl} unless the user already replaced\n     * `room.clock` with their own. Advances `it`.\n     */\n    applyReflection(buffer: Uint8Array, it: Iterator, sectionEnd: number): void {\n        const inputDecoder = Reflection.decode(buffer.subarray(0, sectionEnd) as any, it);\n        Reflection.makeEncodable(inputDecoder.state.constructor as any);\n        this.#ctorFromReflection = inputDecoder.state.constructor as new () => any;\n\n        if (this.#room.clock === NULL_CLOCK) this.#room.clock = new RoomClockImpl();\n    }\n\n    /**\n     * Decode the `INPUT_OPTIONS` handshake section.\n     * `[flags uint8][tickRate varint?][patchRate varint?][subSteps varint?]`,\n     * varints in bit order. Advances `it`.\n     */\n    applyOptions(buffer: Uint8Array, it: Iterator): void {\n        const flags = buffer[it.offset++];\n        this.#stampRender = (flags & InputFlags.RENDER_TIME) !== 0;\n        this.#stampReckon = (flags & InputFlags.RECKON_TIME) !== 0;\n        if (flags & InputFlags.FIXED_TIMESTEP) this.#tickRate = decode.number(buffer as Buffer, it);\n        if (flags & InputFlags.PATCH_RATE) this.#patchRate = decode.number(buffer as Buffer, it);\n        if (flags & InputFlags.SUB_STEPS) this.#subSteps = decode.number(buffer as Buffer, it);\n    }\n\n    /** Feed the server's last-processed input seq to the handle; returns the RTT\n     *  sample (or `-1` before the handle exists / when the seq aged out). */\n    ackInput(inputSeq: number): number {\n        return this.#handle ? this.#handle.ackInput(inputSeq) : -1;\n    }\n\n    /** Reset the input round-trip on reconnect (see {@link Room} reconnection). */\n    reset(): void {\n        this.#handle?.reset();\n    }\n\n    /**\n     * Lazily create and cache the per-room {@link InputHandle}; subsequent calls\n     * return the same handle (options on later calls are ignored — a warning\n     * fires once if they differ from the constructed handle's). Backs\n     * `room.input(...)` — see that method for the full discovery/usage docs.\n     */\n    handle<I>(options?: InputOptions<I>): InputHandle<I> {\n        if (this.#handle) {\n            if (options !== undefined) this.#warnIfIgnored(options);\n            return this.#handle as InputHandle<I>;\n        }\n\n        const Ctor = (options?.type ?? this.#ctorFromReflection) as (new () => I) | undefined;\n        if (!Ctor) {\n            throw new Error(\n                \"room.input(): no input schema available. The server room must call \" +\n                \"`defineInput(YourInput)`, or you can pass `{ type: YourInput }` explicitly.\"\n            );\n        }\n\n        const instance = new Ctor();\n        // The InputEncoder always delta-encodes (no full-snapshot mode), so\n        // there's nothing to configure here beyond mode/historySize.\n        const encoder = new InputEncoder(instance as any, options);\n        // The handle owns the input round-trip (send counter, RTT send-times, server-acked count);\n        // the TIMED decode feeds it the ack and it produces RTT samples for the clock (see Room.onMessage).\n        // `stampRender`/`stampReckon` are server-driven (INPUT_OPTIONS flags); `renderDelay` lets the app subtract its interp buffer.\n        this.#handle = new InputHandleImpl(this.#room, instance, encoder, {\n            stampRender: this.#stampRender,\n            stampReckon: this.#stampReckon,\n            renderDelay: options?.renderDelay,\n            allowRewind: options?.allowRewind,   // app gate: skip the stamp on inputs the server won't rewind\n            tickRate: this.#tickRate,\n            patchRate: this.#patchRate,\n            subSteps: this.#subSteps,\n        });\n        this.#options = options;\n        this.#encoder = encoder;\n        return this.#handle as InputHandle<I>;\n    }\n\n    /** Warn (once) when a later `room.input(options)` call would have produced a\n     *  different handle — those options are silently ignored (first call wins),\n     *  which is invisible without this. Value fields compare against the RESOLVED\n     *  config (ctor/mode/historySize), not the first call's raw options, so a\n     *  textually identical second call stays silent. */\n    #warnIfIgnored(later: InputOptions<any>): void {\n        if (this.#warnedIgnoredOptions) return;\n        const handle = this.#handle!;\n        const diffs: string[] = [];\n        if (later.type !== undefined && later.type !== (handle.data as any)?.constructor) diffs.push(\"type\");\n        if (later.mode !== undefined && later.mode !== handle.mode) diffs.push(\"mode\");\n        // historySize is inert in reliable mode (for BOTH calls) — only compare when unreliable.\n        if (later.historySize !== undefined && handle.mode === \"unreliable\"\n            && later.historySize !== this.#encoder!.historySize) diffs.push(\"historySize\");\n        if (later.renderDelay !== undefined && later.renderDelay !== this.#options?.renderDelay) diffs.push(\"renderDelay\");\n        // Function identity is meaningless across call sites — compare presence only.\n        if ((later.allowRewind !== undefined) !== (this.#options?.allowRewind !== undefined)) diffs.push(\"allowRewind\");\n        if (diffs.length === 0) return;\n        this.#warnedIgnoredOptions = true;\n        console.warn(\n            \"@colyseus/sdk: room.input() options ignored — the input handle was already \" +\n            `created by an earlier call (first call wins). Differing: ${diffs.join(\", \")}.`\n        );\n    }\n}\n"],"names":["__classPrivateFieldSet","__classPrivateFieldGet","Reflection","NULL_CLOCK","RoomClockImpl","InputFlags","decode","InputEncoder","InputHandleImpl"],"mappings":"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"}