@colyseus/core 0.18.0 → 0.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/build/MatchMaker.cjs +3 -7
  2. package/build/MatchMaker.cjs.map +2 -2
  3. package/build/MatchMaker.mjs +4 -8
  4. package/build/MatchMaker.mjs.map +2 -2
  5. package/build/Protocol.cjs +3 -3
  6. package/build/Protocol.cjs.map +1 -1
  7. package/build/Protocol.d.ts +3 -3
  8. package/build/Protocol.mjs +3 -3
  9. package/build/Protocol.mjs.map +1 -1
  10. package/build/Rewind.cjs +385 -0
  11. package/build/Rewind.cjs.map +7 -0
  12. package/build/Rewind.d.ts +291 -0
  13. package/build/Rewind.mjs +359 -0
  14. package/build/Rewind.mjs.map +7 -0
  15. package/build/Room.cjs +280 -281
  16. package/build/Room.cjs.map +3 -3
  17. package/build/Room.d.ts +185 -81
  18. package/build/Room.mjs +286 -286
  19. package/build/Room.mjs.map +2 -2
  20. package/build/RoomMessages.cjs +265 -0
  21. package/build/RoomMessages.cjs.map +7 -0
  22. package/build/RoomMessages.d.ts +49 -0
  23. package/build/RoomMessages.mjs +240 -0
  24. package/build/RoomMessages.mjs.map +7 -0
  25. package/build/Server.cjs +88 -31
  26. package/build/Server.cjs.map +2 -2
  27. package/build/Server.d.ts +36 -0
  28. package/build/Server.mjs +88 -31
  29. package/build/Server.mjs.map +2 -2
  30. package/build/Transport.cjs +26 -0
  31. package/build/Transport.cjs.map +2 -2
  32. package/build/Transport.d.ts +70 -2
  33. package/build/Transport.mjs +25 -0
  34. package/build/Transport.mjs.map +2 -2
  35. package/build/errors/RoomExceptions.cjs +7 -4
  36. package/build/errors/RoomExceptions.cjs.map +2 -2
  37. package/build/errors/RoomExceptions.d.ts +29 -17
  38. package/build/errors/RoomExceptions.mjs +5 -3
  39. package/build/errors/RoomExceptions.mjs.map +2 -2
  40. package/build/index.cjs +19 -2
  41. package/build/index.cjs.map +2 -2
  42. package/build/index.d.ts +7 -4
  43. package/build/index.mjs +17 -4
  44. package/build/index.mjs.map +2 -2
  45. package/build/input/InputBuffer.cjs +465 -16
  46. package/build/input/InputBuffer.cjs.map +2 -2
  47. package/build/input/InputBuffer.d.ts +195 -95
  48. package/build/input/InputBuffer.mjs +461 -15
  49. package/build/input/InputBuffer.mjs.map +2 -2
  50. package/build/input/RoomInput.cjs +307 -0
  51. package/build/input/RoomInput.cjs.map +7 -0
  52. package/build/input/RoomInput.d.ts +91 -0
  53. package/build/input/RoomInput.mjs +289 -0
  54. package/build/input/RoomInput.mjs.map +7 -0
  55. package/build/input/types.cjs +18 -0
  56. package/build/input/types.cjs.map +7 -0
  57. package/build/input/types.d.ts +476 -0
  58. package/build/input/types.mjs +0 -0
  59. package/build/input/types.mjs.map +7 -0
  60. package/build/presence/LocalPresence.cjs.map +2 -2
  61. package/build/presence/LocalPresence.d.ts +1 -1
  62. package/build/presence/LocalPresence.mjs.map +2 -2
  63. package/build/rooms/QueueRoom.cjs +1 -1
  64. package/build/rooms/QueueRoom.cjs.map +2 -2
  65. package/build/rooms/QueueRoom.mjs +1 -1
  66. package/build/rooms/QueueRoom.mjs.map +2 -2
  67. package/build/router/default_routes.cjs +4 -1
  68. package/build/router/default_routes.cjs.map +2 -2
  69. package/build/router/default_routes.mjs +4 -1
  70. package/build/router/default_routes.mjs.map +2 -2
  71. package/build/router/index.cjs +19 -7
  72. package/build/router/index.cjs.map +2 -2
  73. package/build/router/index.mjs +19 -7
  74. package/build/router/index.mjs.map +2 -2
  75. package/build/router/node.cjs +37 -2
  76. package/build/router/node.cjs.map +2 -2
  77. package/build/router/node.d.ts +10 -0
  78. package/build/router/node.mjs +35 -1
  79. package/build/router/node.mjs.map +2 -2
  80. package/build/serializer/NoneSerializer.cjs +2 -2
  81. package/build/serializer/NoneSerializer.cjs.map +2 -2
  82. package/build/serializer/NoneSerializer.d.ts +3 -3
  83. package/build/serializer/NoneSerializer.mjs +2 -2
  84. package/build/serializer/NoneSerializer.mjs.map +2 -2
  85. package/build/serializer/SchemaSerializer.cjs +44 -14
  86. package/build/serializer/SchemaSerializer.cjs.map +2 -2
  87. package/build/serializer/SchemaSerializer.d.ts +3 -3
  88. package/build/serializer/SchemaSerializer.mjs +46 -16
  89. package/build/serializer/SchemaSerializer.mjs.map +2 -2
  90. package/build/serializer/Serializer.cjs.map +1 -1
  91. package/build/serializer/Serializer.d.ts +12 -2
  92. package/build/utils/DevMode.cjs +14 -14
  93. package/build/utils/DevMode.cjs.map +2 -2
  94. package/build/utils/DevMode.d.ts +0 -2
  95. package/build/utils/DevMode.mjs +14 -12
  96. package/build/utils/DevMode.mjs.map +2 -2
  97. package/build/utils/Env.cjs +8 -4
  98. package/build/utils/Env.cjs.map +3 -3
  99. package/build/utils/Env.mjs +8 -4
  100. package/build/utils/Env.mjs.map +2 -2
  101. package/build/utils/Utils.cjs +3 -0
  102. package/build/utils/Utils.cjs.map +2 -2
  103. package/build/utils/Utils.d.ts +8 -0
  104. package/build/utils/Utils.mjs +2 -0
  105. package/build/utils/Utils.mjs.map +2 -2
  106. package/package.json +15 -12
  107. package/src/MatchMaker.ts +7 -9
  108. package/src/Protocol.ts +3 -3
  109. package/src/Rewind.ts +572 -0
  110. package/src/Room.ts +409 -448
  111. package/src/RoomMessages.ts +342 -0
  112. package/src/Server.ts +112 -38
  113. package/src/Transport.ts +98 -2
  114. package/src/errors/RoomExceptions.ts +36 -22
  115. package/src/index.ts +13 -2
  116. package/src/input/InputBuffer.ts +494 -105
  117. package/src/input/RoomInput.ts +342 -0
  118. package/src/input/types.ts +503 -0
  119. package/src/presence/LocalPresence.ts +1 -1
  120. package/src/rooms/QueueRoom.ts +1 -1
  121. package/src/router/default_routes.ts +6 -1
  122. package/src/router/index.ts +32 -14
  123. package/src/router/node.ts +44 -0
  124. package/src/serializer/NoneSerializer.ts +3 -3
  125. package/src/serializer/SchemaSerializer.ts +110 -19
  126. package/src/serializer/Serializer.ts +13 -2
  127. package/src/utils/DevMode.ts +18 -13
  128. package/src/utils/Env.ts +12 -4
  129. package/src/utils/Utils.ts +9 -0
@@ -1,134 +1,234 @@
1
1
  import type { ClientPrivate } from '../Transport.ts';
2
+ import type { ConsumeOptions, IdleInput, InputAccessor, SanitizeInput } from './types.ts';
2
3
  /**
3
- * Names of fields on `I` whose values are `number` — used by
4
- * `Room.defineInput()` to constrain `seqField` to actually-numeric fields
5
- * on the input schema. Filters out booleans, strings, methods, etc.
4
+ * @internal Validate a `subSteps` count. Throws on a fractional/non-positive
5
+ * value: both sides loop `subSteps` times at `dt/subSteps`, so anything but a
6
+ * whole number is a determinism bug, not a tunable. Shared by `defineInput`
7
+ * and `setFixedTimestep`.
6
8
  */
7
- export type NumericFieldsOf<I> = {
8
- [K in keyof I]: I[K] extends number ? (K extends string ? K : never) : never;
9
- }[keyof I];
9
+ export declare function validateSubSteps(subSteps: number | undefined, source: string): number | undefined;
10
10
  /**
11
- * Internal: input configuration captured by `Room.defineInput()`. The schema
12
- * constructor is stored here so the runtime doesn't need to know it through
13
- * the public `room.input` (which is now a callable accessor).
14
- *
15
- * @internal
16
- */
17
- export interface InputOptions {
18
- /**
19
- * Schema constructor used to allocate per-client input instances on join.
20
- * Captured by `defineInput()` from its `type` argument.
21
- *
22
- * Typed loosely (`new () => any`) to sidestep type-identity issues across
23
- * duplicate `@colyseus/schema` installs; the runtime calls
24
- * `instance.clone()` and friends, which match by shape.
25
- */
26
- ctor: new () => any;
27
- /**
28
- * Name of a monotonically-increasing numeric field on the input schema used
29
- * to order and dedupe incoming frames. When set, the framework:
30
- * - Drops redundant frames (`input[seqField]` ≤ the last-seen value are
31
- * discarded before they enter the buffer). Matches the unreliable-mode
32
- * ring-redundancy pattern out of the box.
33
- * - Powers `room.input(sessionId).at(value)` lookups.
34
- *
35
- * Despite the name, "seq" here is broader than an integer counter — any
36
- * monotonic numeric field works:
37
- * - **Sequence counter** (`"seq"`, `"tick"`, `"frame"`) — typical for
38
- * lockstep / rollback netcode (Photon Quantum, GGPO).
39
- * - **Timestamp** (`"timestamp"`, milliseconds or seconds) — useful for
40
- * variable-rate clients, lag compensation, hit registration (Unreal CMC
41
- * uses float-seconds timestamps via `FSavedMove_Character.TimeStamp`).
42
- *
43
- * Whichever you use, the field must increase monotonically across frames
44
- * for dedupe to work.
45
- */
46
- seqField?: string;
47
- /**
48
- * > 0 enables per-client buffering of cloned snapshots — required for
49
- * `room.input(sessionId).drain() / .peek() / .at()` to return populated
50
- * data. Oldest drops on overflow. Set to `0` to disable (`.latest` still
51
- * works).
52
- */
53
- bufferMaxSize: number;
54
- }
55
- /**
56
- * Per-client input accessor returned by `room.input(sessionId)`. Combines the
57
- * latest decoded instance with the (optional) snapshot ring buffer.
58
- *
59
- * - {@link latest} — the bound Schema instance, mutated in place by the
60
- * decoder. Cheapest read; use when only the most recent state matters.
61
- * - {@link drain} / {@link peek} / {@link at} — populated when
62
- * `defineInput()` was called with `bufferMaxSize > 0` (default 32).
63
- * Use for rollback netcode / lockstep where every frame matters.
64
- *
65
- * Returned for unknown sessionIds and rooms without `defineInput()` is a
66
- * frozen no-op accessor (latest=undefined, drain/peek=[], at=undefined,
67
- * size=0, clear=no-op).
11
+ * @internal Compile a {@link SanitizeInput} spec into the per-frame function the
12
+ * decode path applies. The map form precompiles to dense min/max arrays walked
13
+ * with the NaN-safe branch clamp; the callback form passes through.
68
14
  */
69
- export interface InputAccessor<I = any> {
70
- /** Latest decoded input. `undefined` when unknown sessionId or no input declared. */
71
- readonly latest: I | undefined;
72
- /**
73
- * Find the buffered snapshot whose `[seqField]` equals `value`. The field
74
- * name is the Room's `defineInput()` `seqField`. Linear scan — cheap for
75
- * typical buffer sizes; not intended for very large rings. Returns
76
- * `undefined` when no match is buffered (or `seqField` isn't configured).
77
- *
78
- * Useful for tick-aligned retrieval (lockstep, rollback).
79
- */
80
- at(value: number): I | undefined;
81
- /** Take everything buffered (oldest → newest) and clear. Snapshots are safe to retain. */
82
- drain(): I[];
83
- /** Read everything buffered without consuming. */
84
- peek(): I[];
85
- /** Number of snapshots currently buffered. */
86
- readonly size: number;
87
- /** Drop all buffered snapshots (also resets the dedupe tracker). */
88
- clear(): void;
89
- }
15
+ export declare function compileSanitizer<I>(spec: SanitizeInput<I>): (input: I) => void;
90
16
  /**
91
- * Callable returned by `Room.defineInput()`. Assign it to `this.input` and
92
- * call `room.input(sessionId)` per tick to read each client's latest input
93
- * and/or buffered snapshots.
17
+ * @internal Seed every declared field that has no construction default with
18
+ * its wire-neutral zero value (0 / false / ""; quantized: 0 clamped into the
19
+ * descriptor's range). The input contract is "the server holds the last
20
+ * received value" — before anything is received, that value is the ZERO of
21
+ * the field's type, never `undefined`: a sim would NaN-propagate it and a
22
+ * range sanitizer would clamp it into a phantom input. Clients only transmit
23
+ * fields they assign, so an untouched field stays absent on the wire forever.
94
24
  */
95
- export type InputAPI<I = any> = (sessionId: string) => InputAccessor<I>;
25
+ export declare function seedInputZeroValues(instance: any, ctor: new () => any): void;
96
26
  /** @internal */
97
27
  export declare class InputBufferImpl<I = any> {
28
+ /** Pending snapshots, indexed `[_head, _items.length)`. Consumed inputs are
29
+ * NOT spliced off per-read — `_head` advances and the prefix is reclaimed in
30
+ * bulk by {@link compact} (a `shift()` per read is O(n), so a burst would be
31
+ * O(n²)). `_renderTimes`/`_reckonTimes` stay parallel to `_items`. */
98
32
  private _items;
33
+ /** Read cursor: index of the oldest UNCONSUMED input (== `_items.length` when empty). */
34
+ private _head;
99
35
  private _lastSeq;
100
36
  private readonly _maxSize;
101
37
  private readonly _seqField;
102
- constructor(maxSize: number, seqField: string | undefined);
103
- push(snapshot: I): void;
38
+ /**
39
+ * Cumulative count of inputs CONSUMED from this buffer (via any consume
40
+ * primitive — {@link next}/{@link take}/{@link drain}/{@link consume} — plus
41
+ * {@link clear} and overflow). Consumed = "removed from the pending set",
42
+ * whether applied to state or discarded. The server echoes this in the TIMED
43
+ * prefix as the reconciliation ack: how many of the client's inputs are
44
+ * reflected in (or finished influencing) the authoritative state, which lags
45
+ * the receive counter by inputs still buffered. Distinct from
46
+ * `_receivedInputCount` (receive-time, for RTT), which leads the state.
47
+ */
48
+ consumedCount: number;
49
+ /** Render times parallel to `_items` (server-clock ms; `0` when unset). */
50
+ private _renderTimes;
51
+ /** Render time of the most recently drained input (see {@link renderTime}). */
52
+ private _lastRenderTime;
53
+ /** Reckon-display stamps parallel to `_items` — the client's serverNow
54
+ * estimate at input-sample time, i.e. the instant its forward-reckoned
55
+ * entities were displayed at (server-clock ms; `0` when unset). */
56
+ private _reckonTimes;
57
+ /** Reckon stamp of the most recently consumed input (see {@link reckonTime}). */
58
+ private _lastReckonTime;
59
+ /** Framework wire seq per buffered input (parallel to `_items`) — UNRELIABLE
60
+ * ONLY, lazily created on the first seq-carrying push. Reliable inputs are
61
+ * contiguous, so their consumed-seq-value is always exactly {@link consumedCount}
62
+ * and needs no parallel array; `undefined` here marks that (the common, default
63
+ * path pays nothing). A buffer is single-mode, so this is either never created
64
+ * (reliable) or created once and kept parallel (unreliable). */
65
+ private _seqs?;
66
+ /** Seq VALUE of the last consumed input — the reconciliation ack echoed to the
67
+ * client (see {@link ackSeq}). Only meaningful when {@link _seqs} is tracked
68
+ * (unreliable); reliable's ack falls back to {@link consumedCount}. */
69
+ private _lastConsumedSeq;
70
+ /** Whether the most recently produced frame was a synthesized idle (see {@link wasIdle}). */
71
+ private _lastWasIdle;
72
+ /** Reused {@link consume} iterator (lazily minted) + its per-call state, so a
73
+ * per-tick loop allocates no generator frame. `_iterRemaining` snapshots the
74
+ * COUNT to walk — a count, not an index: mid-pass mutations (`next()`/`take()`/
75
+ * `clear()`/compaction) shift indices but can only shorten a count-based pass,
76
+ * never point it past the tail. `_iterIdle` is an optional trailing synthesized
77
+ * frame; `_iterActive` guards against a nested consume() clobbering the shared
78
+ * `_iterRes`. */
79
+ private _iter?;
80
+ private _iterRemaining;
81
+ private _iterActive;
82
+ private _iterIdle?;
83
+ private readonly _iterRes;
84
+ /** Input schema ctor — mints the reused idle frame; idle is off without it. */
85
+ private readonly _ctor?;
86
+ /** Client slice this buffer belongs to (the live object is `Client & ClientPrivate`)
87
+ * — feeds the idle callback's ctx (latest + sessionId). */
88
+ private readonly _client?;
89
+ /** Room-level idle policy (`defineInput({ idle })`) — the bare-call default. */
90
+ private readonly _roomIdle?;
91
+ /** Reused synthesized idle frame + the schema's field names/defaults (lazy). */
92
+ private _idle?;
93
+ private _fieldNames?;
94
+ private _defaults?;
95
+ /** Reused ctx for the idle callback form (see {@link IdleContext}). */
96
+ private readonly _idleCtx;
97
+ constructor(maxSize: number, seqField: string | undefined, ctor?: new () => I, client?: Pick<ClientPrivate, '_input'> & {
98
+ sessionId: string;
99
+ }, idle?: IdleInput<I>);
100
+ /** The effective idle policy for one consume call: per-call `false` suppresses,
101
+ * per-call value overrides, else the room-level default (or none). */
102
+ private effectiveIdle;
103
+ /** Resolve an {@link IdleInput} to overrides — invokes the callback form
104
+ * LAZILY, here at synthesis time (the buffer is known to be empty). */
105
+ private resolveIdle;
106
+ /**
107
+ * The synthesized "no input this tick" frame: schema defaults overlaid with
108
+ * `overrides` (`true` = none). Copies BY FIELD NAME from the schema metadata —
109
+ * schema fields are prototype accessors (no own props), so `Object.assign`
110
+ * can't source from a schema instance; the name walk reads getters, letting
111
+ * `overrides` be a plain partial OR a schema instance (e.g. `latest`).
112
+ * ONE reused instance — refilled per call, never advances the ack.
113
+ */
114
+ private idleFrame;
115
+ /** The idle frame to synthesize on an empty tick (room policy or per-call
116
+ * `opts.idle`), or `undefined` when no policy is in effect. Reuses the single
117
+ * idle instance; never advances the ack. Callers set {@link wasIdle}. */
118
+ private idleFrameOnEmpty;
119
+ /** Consume the input at the cursor: advance cursor + ack, stamp THIS input's
120
+ * render/reckon times, clear {@link wasIdle}. The shared per-input step behind
121
+ * {@link next}, {@link consume}'s iterator, and the re-entrant fallback. */
122
+ private stepHead;
123
+ /** Drop ALL slots, reusing the backing arrays' capacity — the zero-GC reset for
124
+ * the consume/next path ({@link compact}/{@link clear}). `drain()` deliberately
125
+ * does NOT use this (it returns an array, so fresh `[]` is faster there). */
126
+ private truncate;
127
+ /**
128
+ * Append a decoded input snapshot. `seq` is the framework wire seq (unreliable);
129
+ * omit it for reliable inputs, which get an implicit monotonic receive count so
130
+ * {@link ackSeq} stays well-defined in both modes.
131
+ */
132
+ push(snapshot: I, renderTime?: number, reckonTime?: number, seq?: number): void;
133
+ /** Reclaim the consumed prefix `[0, _head)`. Free when fully drained (reuse the
134
+ * arrays); otherwise splice only once the cursor passes {@link COMPACT_THRESHOLD},
135
+ * so the amortized per-input cost stays O(1). */
136
+ private compact;
104
137
  /** Returns true if `value` hasn't been seen, and updates the last-seen marker. */
105
138
  accept(value: number): boolean;
106
- drain(): I[];
139
+ drain(opts?: ConsumeOptions<I>): I[];
140
+ /** Consume the single oldest input (ack advances by one); `undefined` if
141
+ * empty — or the synthesized idle frame when an idle policy is in effect. */
142
+ next(opts?: ConsumeOptions<I>): I | undefined;
143
+ /** Consume up to `n` oldest inputs (ack advances by the count actually taken). */
144
+ take(n: number): I[];
145
+ /**
146
+ * Iterate pending inputs one at a time (per-yield ack + stamp updates), or
147
+ * exactly one synthesized idle frame on an empty buffer with a policy in
148
+ * effect. See {@link InputAccessor.consume}.
149
+ *
150
+ * Returns a POOLED iterator (reused across calls — no generator frame, no
151
+ * per-call allocation) that consumes at most the pending count snapshotted at
152
+ * the call — never past the live tail — plus one optional trailing idle frame.
153
+ * The cursor advances per `next()`, so `break` (which calls `return()`)
154
+ * leaves the rest buffered and compacts. A nested
155
+ * `consume()` of the SAME buffer while one is live falls back to a fresh
156
+ * generator so the pooled `_iterRes` isn't clobbered (nesting is meaningless —
157
+ * both share the cursor — but it must not corrupt).
158
+ */
159
+ consume(opts?: ConsumeOptions<I>): IterableIterator<I>;
160
+ [Symbol.iterator](): IterableIterator<I>;
161
+ /** Lazily mint the reused iterator. Closures over `this` so it reads the
162
+ * private cursor directly; one `_iterRes` is reused — read each result before
163
+ * the next `next()`, as `for..of` / spread / `Array.from` all do. */
164
+ private ensureIter;
165
+ /** Re-entrant fallback: a fresh generator for a nested `consume()` of this same
166
+ * buffer (the pooled iterator is single-active). Same accounting + compaction. */
167
+ private consumeGen;
107
168
  peek(): I[];
108
169
  at(value: number): I | undefined;
109
170
  get size(): number;
171
+ /** Render time (server-clock ms) of the most recently drained input; `0`
172
+ * until the first render-time-stamped input is drained. */
173
+ get renderTime(): number;
174
+ /** Reckon-display stamp of the most recently consumed input — the client's
175
+ * serverNow estimate when it sampled that input, i.e. the EXACT instant its
176
+ * forward-reckoned entities were displayed at. Same consume semantics as
177
+ * {@link renderTime}. RAW: stays `0` until stamped — the resolved,
178
+ * always-usable value is the accessor's `reckonTime`
179
+ * (`room.inputs.get(sid)`); `rewind.lastSeenBy()`'s midpoint-reconstruction
180
+ * fallback depends on this raw `0`. */
181
+ get reckonTime(): number;
182
+ /** Seq VALUE of the last consumed input — the reconciliation ack sent to the
183
+ * client. Reliable (no wire seq tracked): falls back to {@link consumedCount}
184
+ * for free. Unreliable: the framework wire seq, so a fully-dropped input doesn't
185
+ * make the ack lag the client's sent seq by the lost count. `0` before the first
186
+ * consume. */
187
+ get ackSeq(): number;
188
+ /** Whether the most recently produced frame was a synthesized idle (see {@link wasIdle}). */
189
+ get wasIdle(): boolean;
110
190
  clear(): void;
111
191
  }
112
192
  /**
113
193
  * Default per-client accessor. Reads `_input` and `_inputBuffer` off the
114
194
  * client at access time — both are nullable until the room declares input
115
195
  * via `defineInput()`. Cached as `client._inputAccessor` at join, so
116
- * `room.input(sessionId)` is a Map lookup + property read.
196
+ * `room.inputs.get(sessionId)` is a Map lookup + property read.
117
197
  *
118
198
  * @internal
119
199
  */
120
200
  export declare class InputAccessorImpl<I = any> implements InputAccessor<I> {
121
201
  private _client;
122
- constructor(client: ClientPrivate);
202
+ /** Current room time (`clock.elapsedTime`) — resolves the {@link reckonTime}
203
+ * fallback. Threaded by `RoomInput.allocate()`; optional so bare
204
+ * constructions (tests) keep the raw 0. */
205
+ private _nowOf?;
206
+ constructor(client: ClientPrivate, nowOf?: () => number);
123
207
  get latest(): I | undefined;
124
208
  at(value: number): I | undefined;
125
- drain(): I[];
209
+ consume(opts?: ConsumeOptions<I>): IterableIterator<I>;
210
+ [Symbol.iterator](): IterableIterator<I>;
211
+ drain(opts?: ConsumeOptions<I>): I[];
212
+ next(): I | undefined;
213
+ next(opts: {
214
+ idle: IdleInput<I>;
215
+ }): I;
216
+ take(n: number): I[];
126
217
  peek(): I[];
127
218
  get size(): number;
219
+ get consumedCount(): number;
220
+ get wasIdle(): boolean;
128
221
  clear(): void;
222
+ get renderTime(): number;
223
+ /** @internal RAW reckon stamp (0 until stamped). The rewind binding reads
224
+ * THIS, not the resolved getter below: `Rewind._aim`'s midpoint fallback
225
+ * must still see 0 for unstamped clients (a resolved value would silently
226
+ * take the direct-stamp clamp path). */
227
+ get rawReckonTime(): number;
228
+ get reckonTime(): number;
129
229
  }
130
230
  /**
131
- * Returned by `room.input(sessionId)` for unknown sessions and for rooms
231
+ * Returned by `room.inputs.get(sessionId)` for unknown sessions and for rooms
132
232
  * that didn't call `defineInput()`.
133
233
  *
134
234
  * @internal