rollback-netcode 0.0.4

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 (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +140 -0
  3. package/dist/debug.d.ts +29 -0
  4. package/dist/debug.d.ts.map +1 -0
  5. package/dist/debug.js +56 -0
  6. package/dist/debug.js.map +1 -0
  7. package/dist/index.d.ts +62 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +57 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/protocol/encoding.d.ts +80 -0
  12. package/dist/protocol/encoding.d.ts.map +1 -0
  13. package/dist/protocol/encoding.js +992 -0
  14. package/dist/protocol/encoding.js.map +1 -0
  15. package/dist/protocol/messages.d.ts +271 -0
  16. package/dist/protocol/messages.d.ts.map +1 -0
  17. package/dist/protocol/messages.js +114 -0
  18. package/dist/protocol/messages.js.map +1 -0
  19. package/dist/rollback/engine.d.ts +261 -0
  20. package/dist/rollback/engine.d.ts.map +1 -0
  21. package/dist/rollback/engine.js +543 -0
  22. package/dist/rollback/engine.js.map +1 -0
  23. package/dist/rollback/input-buffer.d.ts +225 -0
  24. package/dist/rollback/input-buffer.d.ts.map +1 -0
  25. package/dist/rollback/input-buffer.js +483 -0
  26. package/dist/rollback/input-buffer.js.map +1 -0
  27. package/dist/rollback/snapshot-buffer.d.ts +119 -0
  28. package/dist/rollback/snapshot-buffer.d.ts.map +1 -0
  29. package/dist/rollback/snapshot-buffer.js +256 -0
  30. package/dist/rollback/snapshot-buffer.js.map +1 -0
  31. package/dist/session/desync-manager.d.ts +106 -0
  32. package/dist/session/desync-manager.d.ts.map +1 -0
  33. package/dist/session/desync-manager.js +136 -0
  34. package/dist/session/desync-manager.js.map +1 -0
  35. package/dist/session/lag-monitor.d.ts +69 -0
  36. package/dist/session/lag-monitor.d.ts.map +1 -0
  37. package/dist/session/lag-monitor.js +74 -0
  38. package/dist/session/lag-monitor.js.map +1 -0
  39. package/dist/session/message-builders.d.ts +86 -0
  40. package/dist/session/message-builders.d.ts.map +1 -0
  41. package/dist/session/message-builders.js +199 -0
  42. package/dist/session/message-builders.js.map +1 -0
  43. package/dist/session/message-router.d.ts +61 -0
  44. package/dist/session/message-router.d.ts.map +1 -0
  45. package/dist/session/message-router.js +105 -0
  46. package/dist/session/message-router.js.map +1 -0
  47. package/dist/session/player-manager.d.ts +100 -0
  48. package/dist/session/player-manager.d.ts.map +1 -0
  49. package/dist/session/player-manager.js +160 -0
  50. package/dist/session/player-manager.js.map +1 -0
  51. package/dist/session/session.d.ts +379 -0
  52. package/dist/session/session.d.ts.map +1 -0
  53. package/dist/session/session.js +1294 -0
  54. package/dist/session/session.js.map +1 -0
  55. package/dist/session/topology.d.ts +66 -0
  56. package/dist/session/topology.d.ts.map +1 -0
  57. package/dist/session/topology.js +72 -0
  58. package/dist/session/topology.js.map +1 -0
  59. package/dist/transport/adapter.d.ts +99 -0
  60. package/dist/transport/adapter.d.ts.map +1 -0
  61. package/dist/transport/adapter.js +8 -0
  62. package/dist/transport/adapter.js.map +1 -0
  63. package/dist/transport/local.d.ts +192 -0
  64. package/dist/transport/local.d.ts.map +1 -0
  65. package/dist/transport/local.js +435 -0
  66. package/dist/transport/local.js.map +1 -0
  67. package/dist/transport/transforming.d.ts +177 -0
  68. package/dist/transport/transforming.d.ts.map +1 -0
  69. package/dist/transport/transforming.js +407 -0
  70. package/dist/transport/transforming.js.map +1 -0
  71. package/dist/transport/webrtc.d.ts +285 -0
  72. package/dist/transport/webrtc.d.ts.map +1 -0
  73. package/dist/transport/webrtc.js +734 -0
  74. package/dist/transport/webrtc.js.map +1 -0
  75. package/dist/types.d.ts +394 -0
  76. package/dist/types.d.ts.map +1 -0
  77. package/dist/types.js +256 -0
  78. package/dist/types.js.map +1 -0
  79. package/dist/utils/rate-limiter.d.ts +59 -0
  80. package/dist/utils/rate-limiter.d.ts.map +1 -0
  81. package/dist/utils/rate-limiter.js +93 -0
  82. package/dist/utils/rate-limiter.js.map +1 -0
  83. package/package.json +61 -0
@@ -0,0 +1,543 @@
1
+ /**
2
+ * Core rollback netcode engine.
3
+ *
4
+ * Handles the rollback algorithm: detecting mispredictions,
5
+ * restoring state, and resimulating forward.
6
+ */
7
+ import { DEFAULT_INPUT_PREDICTOR, GameError, RollbackError, asTick, } from "../types.js";
8
+ import { InputBuffer } from "./input-buffer.js";
9
+ import { SnapshotBuffer } from "./snapshot-buffer.js";
10
+ /**
11
+ * Core rollback engine that handles prediction, rollback, and resimulation.
12
+ */
13
+ export class RollbackEngine {
14
+ game;
15
+ localPlayerId;
16
+ snapshotBuffer;
17
+ inputBuffer;
18
+ inputPredictor;
19
+ maxSpeculationTicks;
20
+ pruneBufferTicks;
21
+ onPlayerAddDuringResimulation;
22
+ onPlayerRemoveDuringResimulation;
23
+ onRollback;
24
+ _currentTick;
25
+ _confirmedTick;
26
+ localInputs = new Map();
27
+ /**
28
+ * Create a new rollback engine.
29
+ */
30
+ constructor(config) {
31
+ this.game = config.game;
32
+ this.localPlayerId = config.localPlayerId;
33
+ this.maxSpeculationTicks = config.maxSpeculationTicks ?? 60;
34
+ this.pruneBufferTicks = config.pruneBufferTicks ?? 10;
35
+ this.inputPredictor = config.inputPredictor ?? DEFAULT_INPUT_PREDICTOR;
36
+ this.onPlayerAddDuringResimulation = config.onPlayerAddDuringResimulation;
37
+ this.onPlayerRemoveDuringResimulation =
38
+ config.onPlayerRemoveDuringResimulation;
39
+ this.onRollback = config.onRollback;
40
+ this.snapshotBuffer = new SnapshotBuffer(config.snapshotHistorySize ?? 120);
41
+ this.inputBuffer = new InputBuffer();
42
+ this._currentTick = asTick(0);
43
+ this._confirmedTick = asTick(-1);
44
+ // Add local player
45
+ this.inputBuffer.addPlayer(this.localPlayerId, asTick(0));
46
+ }
47
+ /**
48
+ * The current simulation tick.
49
+ */
50
+ get currentTick() {
51
+ return this._currentTick;
52
+ }
53
+ /**
54
+ * The lowest confirmed tick across all active players.
55
+ * All inputs up to and including this tick are confirmed.
56
+ */
57
+ get confirmedTick() {
58
+ return this._confirmedTick;
59
+ }
60
+ /**
61
+ * Add a player to the simulation.
62
+ *
63
+ * @param playerId - The player's ID
64
+ * @param joinTick - The tick at which they join
65
+ */
66
+ addPlayer(playerId, joinTick) {
67
+ this.inputBuffer.addPlayer(playerId, joinTick);
68
+ }
69
+ /**
70
+ * Remove a player from the simulation.
71
+ *
72
+ * @param playerId - The player's ID
73
+ * @param leaveTick - The tick at which they leave
74
+ */
75
+ removePlayer(playerId, leaveTick) {
76
+ this.inputBuffer.removePlayer(playerId, leaveTick);
77
+ }
78
+ /**
79
+ * Get the confirmed tick for a specific player.
80
+ * Returns the highest tick for which we have received confirmed input from this player.
81
+ *
82
+ * @param playerId - The player's ID
83
+ * @returns The confirmed tick, or undefined if the player is not tracked
84
+ */
85
+ getConfirmedTickForPlayer(playerId) {
86
+ return this.inputBuffer.getConfirmedTick(playerId);
87
+ }
88
+ /**
89
+ * Set the local player's input for the current tick.
90
+ * Call this before tick() to set what input the local player uses.
91
+ *
92
+ * @param tick - The tick the input is for
93
+ * @param input - The input data
94
+ */
95
+ setLocalInput(tick, input) {
96
+ // Copy input
97
+ const inputCopy = new Uint8Array(input.length);
98
+ inputCopy.set(input);
99
+ this.localInputs.set(tick, inputCopy);
100
+ // Also register with input buffer so it's available for misprediction detection
101
+ this.inputBuffer.receiveInput(this.localPlayerId, tick, inputCopy);
102
+ }
103
+ /**
104
+ * Receive a remote player's input.
105
+ *
106
+ * @param playerId - The player's ID
107
+ * @param tick - The tick the input is for
108
+ * @param input - The input data
109
+ */
110
+ receiveRemoteInput(playerId, tick, input) {
111
+ this.inputBuffer.receiveInput(playerId, tick, input);
112
+ }
113
+ /**
114
+ * Get the local player's input for a tick.
115
+ *
116
+ * @param tick - The tick to get input for
117
+ * @returns The input, or undefined if not set
118
+ */
119
+ getLocalInput(tick) {
120
+ return this.localInputs.get(tick);
121
+ }
122
+ /**
123
+ * Save the initial snapshot at tick -1.
124
+ * This allows rollback of tick 0 if there's a misprediction.
125
+ * Call this before the first tick() if the engine wasn't initialized via setState().
126
+ */
127
+ saveInitialSnapshot() {
128
+ if (!this.snapshotBuffer.has(asTick(-1))) {
129
+ const tick = asTick(-1);
130
+ const state = this.gameSerialize(tick);
131
+ const hash = this.gameHash(tick);
132
+ this.snapshotBuffer.save(tick, state, hash);
133
+ }
134
+ }
135
+ /**
136
+ * Advance the simulation by one tick.
137
+ *
138
+ * This is the core rollback algorithm:
139
+ * 1. Check for mispredictions among remote players
140
+ * 2. If misprediction found, rollback and resimulate
141
+ * 3. Gather inputs (real or predicted) for all players
142
+ * 4. Step the simulation
143
+ * 5. Save snapshot
144
+ *
145
+ * @returns Result containing tick number and rollback info
146
+ */
147
+ tick() {
148
+ // Ensure we have an initial snapshot for rollback on first tick
149
+ if (this._currentTick === 0) {
150
+ this.saveInitialSnapshot();
151
+ }
152
+ // Check for max speculation limit
153
+ const minConfirmed = this.inputBuffer.getMinConfirmedTick(this._currentTick);
154
+ if (minConfirmed !== undefined) {
155
+ const speculation = this._currentTick - minConfirmed;
156
+ if (speculation >= this.maxSpeculationTicks) {
157
+ // Can't advance further - would exceed max speculation
158
+ // Return early without advancing
159
+ return {
160
+ tick: this._currentTick,
161
+ rolledBack: false,
162
+ };
163
+ }
164
+ }
165
+ // Check for mispredictions and rollback if needed
166
+ const rollbackResult = this.checkAndRollback();
167
+ // Gather inputs for current tick
168
+ const inputs = this.gatherInputs(this._currentTick);
169
+ // Step the simulation
170
+ this.gameStep(this._currentTick, inputs);
171
+ // Save snapshot
172
+ const state = this.gameSerialize(this._currentTick);
173
+ const hash = this.gameHash(this._currentTick);
174
+ this.snapshotBuffer.save(this._currentTick, state, hash);
175
+ // Update confirmed tick
176
+ this.updateConfirmedTick();
177
+ // Advance tick counter
178
+ const tickResult = this._currentTick;
179
+ this._currentTick = asTick(this._currentTick + 1);
180
+ const result = {
181
+ tick: tickResult,
182
+ rolledBack: rollbackResult.rolledBack,
183
+ };
184
+ if (rollbackResult.rollbackTicks !== undefined) {
185
+ result.rollbackTicks = rollbackResult.rollbackTicks;
186
+ }
187
+ if (rollbackResult.error !== undefined) {
188
+ result.error = rollbackResult.error;
189
+ }
190
+ return result;
191
+ }
192
+ /**
193
+ * Check for mispredictions and rollback if found.
194
+ */
195
+ checkAndRollback() {
196
+ // Find the earliest misprediction across all remote players
197
+ let earliestMisprediction;
198
+ const activePlayers = this.inputBuffer.getActivePlayers(this._currentTick);
199
+ for (const playerId of activePlayers) {
200
+ if (playerId === this.localPlayerId)
201
+ continue;
202
+ const mispredictTick = this.inputBuffer.findMisprediction(playerId, this._confirmedTick >= 0 ? asTick(this._confirmedTick + 1) : asTick(0));
203
+ if (mispredictTick !== undefined) {
204
+ if (earliestMisprediction === undefined ||
205
+ mispredictTick < earliestMisprediction) {
206
+ earliestMisprediction = mispredictTick;
207
+ }
208
+ }
209
+ }
210
+ if (earliestMisprediction === undefined) {
211
+ return { rolledBack: false };
212
+ }
213
+ // We need to rollback to the tick BEFORE the misprediction
214
+ const restoreTick = asTick(earliestMisprediction - 1);
215
+ // Find snapshot to restore - first try exact match
216
+ let snapshot = this.snapshotBuffer.get(restoreTick);
217
+ let actualRestoreTick = restoreTick;
218
+ if (!snapshot) {
219
+ // Try to find the closest available snapshot at or before the target
220
+ snapshot = this.snapshotBuffer.getAtOrBefore(restoreTick);
221
+ if (!snapshot) {
222
+ // No snapshot available at all - this can happen at startup
223
+ // before any snapshots have been saved
224
+ return {
225
+ rolledBack: false,
226
+ error: new RollbackError(`Cannot rollback to tick ${restoreTick}: no snapshots available in buffer`, restoreTick),
227
+ };
228
+ }
229
+ // We found an earlier snapshot, adjust resimulation range
230
+ actualRestoreTick = snapshot.tick;
231
+ }
232
+ // Calculate resimulation range - from the tick AFTER the restored snapshot
233
+ const resimulateFromTick = asTick(actualRestoreTick + 1);
234
+ const ticksToResimulate = this._currentTick - resimulateFromTick;
235
+ // Restore game state
236
+ this.gameDeserialize(actualRestoreTick, snapshot.state);
237
+ // Notify about rollback before resimulation
238
+ this.onRollback?.(actualRestoreTick);
239
+ // Clear used inputs from the resimulation start tick onwards
240
+ this.inputBuffer.clearAllUsedInputsFrom(resimulateFromTick);
241
+ // Resimulate from the tick after restored snapshot to current tick
242
+ for (let tick = resimulateFromTick; tick < this._currentTick; tick++) {
243
+ const tickAsTick = asTick(tick);
244
+ // Handle player lifecycle events at this tick
245
+ this.handlePlayerLifecycleAtTick(tickAsTick);
246
+ const inputs = this.gatherInputs(tickAsTick);
247
+ this.gameStep(tickAsTick, inputs);
248
+ // Update snapshot
249
+ const state = this.gameSerialize(tickAsTick);
250
+ const hash = this.gameHash(tickAsTick);
251
+ this.snapshotBuffer.save(tickAsTick, state, hash);
252
+ }
253
+ return {
254
+ rolledBack: true,
255
+ rollbackTicks: ticksToResimulate,
256
+ };
257
+ }
258
+ /**
259
+ * Handle player add/remove lifecycle events at a specific tick during resimulation.
260
+ * This ensures the game layer knows about player joins/leaves when replaying history.
261
+ * Uses O(1) tick-indexed lookups instead of iterating all players.
262
+ */
263
+ handlePlayerLifecycleAtTick(tick) {
264
+ // Handle player joins at this tick
265
+ if (this.onPlayerAddDuringResimulation) {
266
+ const joiningPlayers = this.inputBuffer.getPlayersJoiningAtTick(tick);
267
+ for (const playerId of joiningPlayers) {
268
+ this.onPlayerAddDuringResimulation(playerId, tick);
269
+ }
270
+ }
271
+ // Handle player leaves at this tick
272
+ if (this.onPlayerRemoveDuringResimulation) {
273
+ const leavingPlayers = this.inputBuffer.getPlayersLeavingAtTick(tick);
274
+ for (const playerId of leavingPlayers) {
275
+ this.onPlayerRemoveDuringResimulation(playerId, tick);
276
+ }
277
+ }
278
+ }
279
+ /**
280
+ * Gather inputs for all active players at a given tick.
281
+ * Uses real inputs when available, predicts otherwise.
282
+ */
283
+ gatherInputs(tick) {
284
+ const inputs = new Map();
285
+ const activePlayers = this.inputBuffer.getActivePlayers(tick);
286
+ for (const playerId of activePlayers) {
287
+ let input;
288
+ if (playerId === this.localPlayerId) {
289
+ // Local player - use our stored input
290
+ input = this.localInputs.get(tick) ?? new Uint8Array(0);
291
+ }
292
+ else {
293
+ // Remote player - use received input or predict
294
+ const received = this.inputBuffer.getInput(playerId, tick);
295
+ if (received) {
296
+ input = received;
297
+ }
298
+ else {
299
+ // Predict based on last confirmed input
300
+ const lastInput = this.inputBuffer.getLastConfirmedInput(playerId);
301
+ input = this.inputPredictor.predict(playerId, tick, lastInput);
302
+ }
303
+ }
304
+ inputs.set(playerId, input);
305
+ // Record what we used for misprediction detection
306
+ this.inputBuffer.recordUsedInput(playerId, tick, input);
307
+ }
308
+ return inputs;
309
+ }
310
+ /**
311
+ * Update the confirmed tick based on all players' confirmed ticks.
312
+ */
313
+ updateConfirmedTick() {
314
+ const minConfirmed = this.inputBuffer.getMinConfirmedTick(this._currentTick);
315
+ if (minConfirmed !== undefined && minConfirmed > this._confirmedTick) {
316
+ this._confirmedTick = minConfirmed;
317
+ // Prune old data only when we have enough confirmed ticks to keep a buffer
318
+ if (this._confirmedTick > this.pruneBufferTicks) {
319
+ const pruneBelow = asTick(this._confirmedTick - this.pruneBufferTicks);
320
+ this.inputBuffer.pruneBeforeTick(pruneBelow);
321
+ this.snapshotBuffer.pruneBeforeTick(pruneBelow);
322
+ // Also prune local inputs
323
+ for (const tick of this.localInputs.keys()) {
324
+ if (tick < pruneBelow) {
325
+ this.localInputs.delete(tick);
326
+ }
327
+ }
328
+ }
329
+ }
330
+ }
331
+ /**
332
+ * Get the hash at a specific tick.
333
+ *
334
+ * @param tick - The tick to get hash for
335
+ * @returns The hash, or undefined if not available
336
+ */
337
+ getHash(tick) {
338
+ return this.snapshotBuffer.get(tick)?.hash;
339
+ }
340
+ /**
341
+ * Get the current game hash.
342
+ */
343
+ getCurrentHash() {
344
+ return this.gameHash(this._currentTick);
345
+ }
346
+ /**
347
+ * Get the current game state and player timeline for sync.
348
+ */
349
+ getState() {
350
+ const players = this.inputBuffer.getAllPlayers();
351
+ const playerTimeline = [];
352
+ for (const playerId of players) {
353
+ const joinTick = this.inputBuffer.getJoinTick(playerId);
354
+ const leaveTick = this.inputBuffer.getLeaveTick(playerId);
355
+ if (joinTick !== undefined) {
356
+ playerTimeline.push({
357
+ playerId,
358
+ joinTick,
359
+ leaveTick: leaveTick ?? null,
360
+ });
361
+ }
362
+ }
363
+ return {
364
+ tick: this._currentTick,
365
+ state: this.gameSerialize(this._currentTick),
366
+ playerTimeline,
367
+ };
368
+ }
369
+ /**
370
+ * Set the game state from a sync message.
371
+ * Used for late join or desync recovery.
372
+ *
373
+ * @param tick - The tick the state is from
374
+ * @param state - The serialized game state
375
+ * @param playerTimeline - Timeline of player join/leave events
376
+ */
377
+ setState(tick, state, playerTimeline) {
378
+ // Restore game state
379
+ this.gameDeserialize(tick, state);
380
+ // Clear buffers
381
+ this.snapshotBuffer.clear();
382
+ this.inputBuffer.clear();
383
+ this.localInputs.clear();
384
+ // Restore player timeline
385
+ for (const entry of playerTimeline) {
386
+ this.inputBuffer.addPlayer(entry.playerId, entry.joinTick);
387
+ if (entry.leaveTick !== null) {
388
+ this.inputBuffer.removePlayer(entry.playerId, entry.leaveTick);
389
+ }
390
+ }
391
+ // Set confirmed tick for all active players to tick-1
392
+ // This is critical for mid-game joins: the synced state represents
393
+ // a confirmed state, so all players who contributed to it have
394
+ // implicitly confirmed inputs up to that point
395
+ this.inputBuffer.setConfirmedTickForSync(tick);
396
+ // Save initial snapshot at tick - 1 (state before any simulation)
397
+ // This is needed so we can rollback tick 0 if there's a misprediction
398
+ const snapshotTick = asTick(tick - 1);
399
+ const hash = this.gameHash(snapshotTick);
400
+ this.snapshotBuffer.save(snapshotTick, state, hash);
401
+ // Set tick counters - currentTick is the next tick to simulate
402
+ this._currentTick = tick;
403
+ this._confirmedTick = asTick(tick - 1);
404
+ }
405
+ /**
406
+ * Reset buffers and tick counters for sync without changing game state.
407
+ *
408
+ * Used by the host when broadcasting sync to all players. The host's game
409
+ * state is already correct, but it needs to reset buffers and tick counters
410
+ * to match the synced state being sent to clients.
411
+ *
412
+ * This is more efficient than setState() when the game state doesn't need
413
+ * to be restored (avoids unnecessary serialize/deserialize round-trip).
414
+ *
415
+ * @param tick - The tick to reset to
416
+ * @param playerTimeline - Timeline of player join/leave events
417
+ */
418
+ resetForSync(tick, playerTimeline) {
419
+ // Clear buffers
420
+ this.snapshotBuffer.clear();
421
+ this.inputBuffer.clear();
422
+ this.localInputs.clear();
423
+ // Restore player timeline
424
+ for (const entry of playerTimeline) {
425
+ this.inputBuffer.addPlayer(entry.playerId, entry.joinTick);
426
+ if (entry.leaveTick !== null) {
427
+ this.inputBuffer.removePlayer(entry.playerId, entry.leaveTick);
428
+ }
429
+ }
430
+ // Set confirmed tick for all active players to tick-1
431
+ this.inputBuffer.setConfirmedTickForSync(tick);
432
+ // Save snapshot of current state at tick - 1
433
+ // (game state is already correct, just need to capture it)
434
+ const snapshotTick = asTick(tick - 1);
435
+ const state = this.gameSerialize(snapshotTick);
436
+ const hash = this.gameHash(snapshotTick);
437
+ this.snapshotBuffer.save(snapshotTick, state, hash);
438
+ // Set tick counters
439
+ this._currentTick = tick;
440
+ this._confirmedTick = asTick(tick - 1);
441
+ }
442
+ /**
443
+ * Check if we have all inputs for a given tick.
444
+ *
445
+ * @param tick - The tick to check
446
+ * @returns true if all inputs are available
447
+ */
448
+ hasAllInputsForTick(tick) {
449
+ return this.inputBuffer.hasAllInputsForTick(tick);
450
+ }
451
+ /**
452
+ * Check if a tick is "settled" - meaning we've simulated past it
453
+ * and have all confirmed inputs for it.
454
+ *
455
+ * A settled tick's state is stable and won't change from future rollbacks,
456
+ * making it safe to compare hashes for desync detection.
457
+ *
458
+ * @param tick - The tick to check
459
+ * @param currentTick - The current simulation tick
460
+ * @returns true if the tick is settled
461
+ */
462
+ isTickSettled(tick, currentTick) {
463
+ // Must have simulated past this tick
464
+ if (tick >= currentTick) {
465
+ return false;
466
+ }
467
+ // Must have all inputs confirmed
468
+ return this.inputBuffer.hasAllInputsForTick(tick);
469
+ }
470
+ /**
471
+ * Get the number of ticks we're speculating ahead.
472
+ */
473
+ getSpeculationDistance() {
474
+ if (this._confirmedTick < 0) {
475
+ return this._currentTick;
476
+ }
477
+ return this._currentTick - this._confirmedTick - 1;
478
+ }
479
+ /**
480
+ * Get all active player IDs at the current tick.
481
+ */
482
+ getActivePlayers() {
483
+ return this.inputBuffer.getActivePlayers(this._currentTick);
484
+ }
485
+ /**
486
+ * Get all player IDs.
487
+ */
488
+ getAllPlayers() {
489
+ return this.inputBuffer.getAllPlayers();
490
+ }
491
+ /**
492
+ * Reset the engine to initial state.
493
+ */
494
+ reset() {
495
+ this.snapshotBuffer.clear();
496
+ this.inputBuffer.clear();
497
+ this.localInputs.clear();
498
+ this._currentTick = asTick(0);
499
+ this._confirmedTick = asTick(-1);
500
+ // Re-add local player
501
+ this.inputBuffer.addPlayer(this.localPlayerId, asTick(0));
502
+ }
503
+ // =========================================================================
504
+ // Game operation wrappers with error handling
505
+ // =========================================================================
506
+ /**
507
+ * Wrap a game operation with error handling.
508
+ * Catches any error and re-throws it wrapped in a GameError with context.
509
+ */
510
+ wrapGameOperation(operation, tick, fn) {
511
+ try {
512
+ return fn();
513
+ }
514
+ catch (error) {
515
+ throw new GameError(operation, tick, error instanceof Error ? error : new Error(String(error)));
516
+ }
517
+ }
518
+ /**
519
+ * Call game.step() with error wrapping.
520
+ */
521
+ gameStep(tick, inputs) {
522
+ this.wrapGameOperation("step", tick, () => this.game.step(inputs));
523
+ }
524
+ /**
525
+ * Call game.serialize() with error wrapping.
526
+ */
527
+ gameSerialize(tick) {
528
+ return this.wrapGameOperation("serialize", tick, () => this.game.serialize());
529
+ }
530
+ /**
531
+ * Call game.deserialize() with error wrapping.
532
+ */
533
+ gameDeserialize(tick, state) {
534
+ this.wrapGameOperation("deserialize", tick, () => this.game.deserialize(state));
535
+ }
536
+ /**
537
+ * Call game.hash() with error wrapping.
538
+ */
539
+ gameHash(tick) {
540
+ return this.wrapGameOperation("hash", tick, () => this.game.hash());
541
+ }
542
+ }
543
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/rollback/engine.ts"],"names":[],"mappings":"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"}