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,261 @@
1
+ /**
2
+ * Core rollback netcode engine.
3
+ *
4
+ * Handles the rollback algorithm: detecting mispredictions,
5
+ * restoring state, and resimulating forward.
6
+ */
7
+ import type { Game, InputPredictor, PlayerId, PlayerTimeline, Tick, TickResult } from "../types.js";
8
+ /**
9
+ * Callback for player lifecycle events during resimulation.
10
+ */
11
+ export type PlayerLifecycleCallback = (playerId: PlayerId, tick: Tick) => void;
12
+ /**
13
+ * Configuration for the rollback engine.
14
+ */
15
+ export interface RollbackEngineConfig {
16
+ /** The game instance to control */
17
+ game: Game;
18
+ /** The local player's ID */
19
+ localPlayerId: PlayerId;
20
+ /** Number of snapshots to keep in history */
21
+ snapshotHistorySize?: number;
22
+ /** Maximum ticks to speculate ahead without confirmed inputs */
23
+ maxSpeculationTicks?: number;
24
+ /** Input predictor for remote players */
25
+ inputPredictor?: InputPredictor<Uint8Array>;
26
+ /**
27
+ * Number of ticks to keep before the confirmed tick when pruning.
28
+ * Higher values use more memory but allow rollback further into the past.
29
+ * @default 10
30
+ */
31
+ pruneBufferTicks?: number;
32
+ /**
33
+ * Callback invoked when a player should be added during resimulation.
34
+ * Called when resimulating past a player's joinTick.
35
+ */
36
+ onPlayerAddDuringResimulation?: PlayerLifecycleCallback;
37
+ /**
38
+ * Callback invoked when a player should be removed during resimulation.
39
+ * Called when resimulating past a player's leaveTick.
40
+ */
41
+ onPlayerRemoveDuringResimulation?: PlayerLifecycleCallback;
42
+ /**
43
+ * Callback invoked when a rollback occurs, before resimulation.
44
+ * Receives the tick that we're rolling back to (the restore tick).
45
+ * Use this to clear state that needs to be re-applied during resimulation.
46
+ */
47
+ onRollback?: (restoreTick: Tick) => void;
48
+ }
49
+ /**
50
+ * Core rollback engine that handles prediction, rollback, and resimulation.
51
+ */
52
+ export declare class RollbackEngine {
53
+ private readonly game;
54
+ private readonly localPlayerId;
55
+ private readonly snapshotBuffer;
56
+ private readonly inputBuffer;
57
+ private readonly inputPredictor;
58
+ private readonly maxSpeculationTicks;
59
+ private readonly pruneBufferTicks;
60
+ private readonly onPlayerAddDuringResimulation;
61
+ private readonly onPlayerRemoveDuringResimulation;
62
+ private readonly onRollback;
63
+ private _currentTick;
64
+ private _confirmedTick;
65
+ private localInputs;
66
+ /**
67
+ * Create a new rollback engine.
68
+ */
69
+ constructor(config: RollbackEngineConfig);
70
+ /**
71
+ * The current simulation tick.
72
+ */
73
+ get currentTick(): Tick;
74
+ /**
75
+ * The lowest confirmed tick across all active players.
76
+ * All inputs up to and including this tick are confirmed.
77
+ */
78
+ get confirmedTick(): Tick;
79
+ /**
80
+ * Add a player to the simulation.
81
+ *
82
+ * @param playerId - The player's ID
83
+ * @param joinTick - The tick at which they join
84
+ */
85
+ addPlayer(playerId: PlayerId, joinTick: Tick): void;
86
+ /**
87
+ * Remove a player from the simulation.
88
+ *
89
+ * @param playerId - The player's ID
90
+ * @param leaveTick - The tick at which they leave
91
+ */
92
+ removePlayer(playerId: PlayerId, leaveTick: Tick): void;
93
+ /**
94
+ * Get the confirmed tick for a specific player.
95
+ * Returns the highest tick for which we have received confirmed input from this player.
96
+ *
97
+ * @param playerId - The player's ID
98
+ * @returns The confirmed tick, or undefined if the player is not tracked
99
+ */
100
+ getConfirmedTickForPlayer(playerId: PlayerId): Tick | undefined;
101
+ /**
102
+ * Set the local player's input for the current tick.
103
+ * Call this before tick() to set what input the local player uses.
104
+ *
105
+ * @param tick - The tick the input is for
106
+ * @param input - The input data
107
+ */
108
+ setLocalInput(tick: Tick, input: Uint8Array): void;
109
+ /**
110
+ * Receive a remote player's input.
111
+ *
112
+ * @param playerId - The player's ID
113
+ * @param tick - The tick the input is for
114
+ * @param input - The input data
115
+ */
116
+ receiveRemoteInput(playerId: PlayerId, tick: Tick, input: Uint8Array): void;
117
+ /**
118
+ * Get the local player's input for a tick.
119
+ *
120
+ * @param tick - The tick to get input for
121
+ * @returns The input, or undefined if not set
122
+ */
123
+ getLocalInput(tick: Tick): Uint8Array | undefined;
124
+ /**
125
+ * Save the initial snapshot at tick -1.
126
+ * This allows rollback of tick 0 if there's a misprediction.
127
+ * Call this before the first tick() if the engine wasn't initialized via setState().
128
+ */
129
+ saveInitialSnapshot(): void;
130
+ /**
131
+ * Advance the simulation by one tick.
132
+ *
133
+ * This is the core rollback algorithm:
134
+ * 1. Check for mispredictions among remote players
135
+ * 2. If misprediction found, rollback and resimulate
136
+ * 3. Gather inputs (real or predicted) for all players
137
+ * 4. Step the simulation
138
+ * 5. Save snapshot
139
+ *
140
+ * @returns Result containing tick number and rollback info
141
+ */
142
+ tick(): TickResult;
143
+ /**
144
+ * Check for mispredictions and rollback if found.
145
+ */
146
+ private checkAndRollback;
147
+ /**
148
+ * Handle player add/remove lifecycle events at a specific tick during resimulation.
149
+ * This ensures the game layer knows about player joins/leaves when replaying history.
150
+ * Uses O(1) tick-indexed lookups instead of iterating all players.
151
+ */
152
+ private handlePlayerLifecycleAtTick;
153
+ /**
154
+ * Gather inputs for all active players at a given tick.
155
+ * Uses real inputs when available, predicts otherwise.
156
+ */
157
+ private gatherInputs;
158
+ /**
159
+ * Update the confirmed tick based on all players' confirmed ticks.
160
+ */
161
+ private updateConfirmedTick;
162
+ /**
163
+ * Get the hash at a specific tick.
164
+ *
165
+ * @param tick - The tick to get hash for
166
+ * @returns The hash, or undefined if not available
167
+ */
168
+ getHash(tick: Tick): number | undefined;
169
+ /**
170
+ * Get the current game hash.
171
+ */
172
+ getCurrentHash(): number;
173
+ /**
174
+ * Get the current game state and player timeline for sync.
175
+ */
176
+ getState(): {
177
+ tick: Tick;
178
+ state: Uint8Array;
179
+ playerTimeline: PlayerTimeline;
180
+ };
181
+ /**
182
+ * Set the game state from a sync message.
183
+ * Used for late join or desync recovery.
184
+ *
185
+ * @param tick - The tick the state is from
186
+ * @param state - The serialized game state
187
+ * @param playerTimeline - Timeline of player join/leave events
188
+ */
189
+ setState(tick: Tick, state: Uint8Array, playerTimeline: PlayerTimeline): void;
190
+ /**
191
+ * Reset buffers and tick counters for sync without changing game state.
192
+ *
193
+ * Used by the host when broadcasting sync to all players. The host's game
194
+ * state is already correct, but it needs to reset buffers and tick counters
195
+ * to match the synced state being sent to clients.
196
+ *
197
+ * This is more efficient than setState() when the game state doesn't need
198
+ * to be restored (avoids unnecessary serialize/deserialize round-trip).
199
+ *
200
+ * @param tick - The tick to reset to
201
+ * @param playerTimeline - Timeline of player join/leave events
202
+ */
203
+ resetForSync(tick: Tick, playerTimeline: PlayerTimeline): void;
204
+ /**
205
+ * Check if we have all inputs for a given tick.
206
+ *
207
+ * @param tick - The tick to check
208
+ * @returns true if all inputs are available
209
+ */
210
+ hasAllInputsForTick(tick: Tick): boolean;
211
+ /**
212
+ * Check if a tick is "settled" - meaning we've simulated past it
213
+ * and have all confirmed inputs for it.
214
+ *
215
+ * A settled tick's state is stable and won't change from future rollbacks,
216
+ * making it safe to compare hashes for desync detection.
217
+ *
218
+ * @param tick - The tick to check
219
+ * @param currentTick - The current simulation tick
220
+ * @returns true if the tick is settled
221
+ */
222
+ isTickSettled(tick: Tick, currentTick: Tick): boolean;
223
+ /**
224
+ * Get the number of ticks we're speculating ahead.
225
+ */
226
+ getSpeculationDistance(): number;
227
+ /**
228
+ * Get all active player IDs at the current tick.
229
+ */
230
+ getActivePlayers(): PlayerId[];
231
+ /**
232
+ * Get all player IDs.
233
+ */
234
+ getAllPlayers(): PlayerId[];
235
+ /**
236
+ * Reset the engine to initial state.
237
+ */
238
+ reset(): void;
239
+ /**
240
+ * Wrap a game operation with error handling.
241
+ * Catches any error and re-throws it wrapped in a GameError with context.
242
+ */
243
+ private wrapGameOperation;
244
+ /**
245
+ * Call game.step() with error wrapping.
246
+ */
247
+ private gameStep;
248
+ /**
249
+ * Call game.serialize() with error wrapping.
250
+ */
251
+ private gameSerialize;
252
+ /**
253
+ * Call game.deserialize() with error wrapping.
254
+ */
255
+ private gameDeserialize;
256
+ /**
257
+ * Call game.hash() with error wrapping.
258
+ */
259
+ private gameHash;
260
+ }
261
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/rollback/engine.ts"],"names":[],"mappings":"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"}