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.
- package/LICENSE +21 -0
- package/README.md +140 -0
- package/dist/debug.d.ts +29 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +56 -0
- package/dist/debug.js.map +1 -0
- package/dist/index.d.ts +62 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol/encoding.d.ts +80 -0
- package/dist/protocol/encoding.d.ts.map +1 -0
- package/dist/protocol/encoding.js +992 -0
- package/dist/protocol/encoding.js.map +1 -0
- package/dist/protocol/messages.d.ts +271 -0
- package/dist/protocol/messages.d.ts.map +1 -0
- package/dist/protocol/messages.js +114 -0
- package/dist/protocol/messages.js.map +1 -0
- package/dist/rollback/engine.d.ts +261 -0
- package/dist/rollback/engine.d.ts.map +1 -0
- package/dist/rollback/engine.js +543 -0
- package/dist/rollback/engine.js.map +1 -0
- package/dist/rollback/input-buffer.d.ts +225 -0
- package/dist/rollback/input-buffer.d.ts.map +1 -0
- package/dist/rollback/input-buffer.js +483 -0
- package/dist/rollback/input-buffer.js.map +1 -0
- package/dist/rollback/snapshot-buffer.d.ts +119 -0
- package/dist/rollback/snapshot-buffer.d.ts.map +1 -0
- package/dist/rollback/snapshot-buffer.js +256 -0
- package/dist/rollback/snapshot-buffer.js.map +1 -0
- package/dist/session/desync-manager.d.ts +106 -0
- package/dist/session/desync-manager.d.ts.map +1 -0
- package/dist/session/desync-manager.js +136 -0
- package/dist/session/desync-manager.js.map +1 -0
- package/dist/session/lag-monitor.d.ts +69 -0
- package/dist/session/lag-monitor.d.ts.map +1 -0
- package/dist/session/lag-monitor.js +74 -0
- package/dist/session/lag-monitor.js.map +1 -0
- package/dist/session/message-builders.d.ts +86 -0
- package/dist/session/message-builders.d.ts.map +1 -0
- package/dist/session/message-builders.js +199 -0
- package/dist/session/message-builders.js.map +1 -0
- package/dist/session/message-router.d.ts +61 -0
- package/dist/session/message-router.d.ts.map +1 -0
- package/dist/session/message-router.js +105 -0
- package/dist/session/message-router.js.map +1 -0
- package/dist/session/player-manager.d.ts +100 -0
- package/dist/session/player-manager.d.ts.map +1 -0
- package/dist/session/player-manager.js +160 -0
- package/dist/session/player-manager.js.map +1 -0
- package/dist/session/session.d.ts +379 -0
- package/dist/session/session.d.ts.map +1 -0
- package/dist/session/session.js +1294 -0
- package/dist/session/session.js.map +1 -0
- package/dist/session/topology.d.ts +66 -0
- package/dist/session/topology.d.ts.map +1 -0
- package/dist/session/topology.js +72 -0
- package/dist/session/topology.js.map +1 -0
- package/dist/transport/adapter.d.ts +99 -0
- package/dist/transport/adapter.d.ts.map +1 -0
- package/dist/transport/adapter.js +8 -0
- package/dist/transport/adapter.js.map +1 -0
- package/dist/transport/local.d.ts +192 -0
- package/dist/transport/local.d.ts.map +1 -0
- package/dist/transport/local.js +435 -0
- package/dist/transport/local.js.map +1 -0
- package/dist/transport/transforming.d.ts +177 -0
- package/dist/transport/transforming.d.ts.map +1 -0
- package/dist/transport/transforming.js +407 -0
- package/dist/transport/transforming.js.map +1 -0
- package/dist/transport/webrtc.d.ts +285 -0
- package/dist/transport/webrtc.d.ts.map +1 -0
- package/dist/transport/webrtc.js +734 -0
- package/dist/transport/webrtc.js.map +1 -0
- package/dist/types.d.ts +394 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +256 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +59 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +93 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Player state management for sessions.
|
|
3
|
+
*/
|
|
4
|
+
import { PlayerConnectionState, PlayerRole, } from "../types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Manages player state within a session.
|
|
7
|
+
*
|
|
8
|
+
* Centralizes player tracking, connection state, and lifecycle operations.
|
|
9
|
+
*/
|
|
10
|
+
export class PlayerManager {
|
|
11
|
+
players = new Map();
|
|
12
|
+
/**
|
|
13
|
+
* Add a new player to the session.
|
|
14
|
+
*
|
|
15
|
+
* @param info - The player info to add
|
|
16
|
+
*/
|
|
17
|
+
addPlayer(info) {
|
|
18
|
+
this.players.set(info.id, info);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Remove a player from the session.
|
|
22
|
+
*
|
|
23
|
+
* @param playerId - The player ID to remove
|
|
24
|
+
* @returns The removed player info, or undefined if not found
|
|
25
|
+
*/
|
|
26
|
+
removePlayer(playerId) {
|
|
27
|
+
const player = this.players.get(playerId);
|
|
28
|
+
if (player) {
|
|
29
|
+
this.players.delete(playerId);
|
|
30
|
+
}
|
|
31
|
+
return player;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get a player by ID.
|
|
35
|
+
*
|
|
36
|
+
* @param playerId - The player ID to look up
|
|
37
|
+
* @returns The player info, or undefined if not found
|
|
38
|
+
*/
|
|
39
|
+
getPlayer(playerId) {
|
|
40
|
+
return this.players.get(playerId);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Check if a player exists.
|
|
44
|
+
*
|
|
45
|
+
* @param playerId - The player ID to check
|
|
46
|
+
*/
|
|
47
|
+
hasPlayer(playerId) {
|
|
48
|
+
return this.players.has(playerId);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Mark a player as disconnected.
|
|
52
|
+
*
|
|
53
|
+
* @param playerId - The player ID to mark
|
|
54
|
+
* @param leaveTick - The tick when they disconnected (optional)
|
|
55
|
+
* @returns The updated player info, or undefined if not found
|
|
56
|
+
*/
|
|
57
|
+
markDisconnected(playerId, leaveTick) {
|
|
58
|
+
const player = this.players.get(playerId);
|
|
59
|
+
if (player) {
|
|
60
|
+
player.connectionState = PlayerConnectionState.Disconnected;
|
|
61
|
+
if (leaveTick !== undefined) {
|
|
62
|
+
player.leaveTick = leaveTick;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return player;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Mark a player as connected.
|
|
69
|
+
*
|
|
70
|
+
* @param playerId - The player ID to mark
|
|
71
|
+
* @returns The updated player info, or undefined if not found
|
|
72
|
+
*/
|
|
73
|
+
markConnected(playerId) {
|
|
74
|
+
const player = this.players.get(playerId);
|
|
75
|
+
if (player) {
|
|
76
|
+
player.connectionState = PlayerConnectionState.Connected;
|
|
77
|
+
}
|
|
78
|
+
return player;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Get all players that are currently active (connected and role is Player).
|
|
82
|
+
*
|
|
83
|
+
* @returns Array of active player infos
|
|
84
|
+
*/
|
|
85
|
+
getActivePlayers() {
|
|
86
|
+
return Array.from(this.players.values()).filter((p) => p.role === PlayerRole.Player &&
|
|
87
|
+
p.connectionState === PlayerConnectionState.Connected);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Get all connected players (any role).
|
|
91
|
+
*
|
|
92
|
+
* @returns Array of connected player infos
|
|
93
|
+
*/
|
|
94
|
+
getConnectedPlayers() {
|
|
95
|
+
return Array.from(this.players.values()).filter((p) => p.connectionState === PlayerConnectionState.Connected);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get the count of active players.
|
|
99
|
+
*/
|
|
100
|
+
getActivePlayerCount() {
|
|
101
|
+
let count = 0;
|
|
102
|
+
for (const player of this.players.values()) {
|
|
103
|
+
if (player.role === PlayerRole.Player &&
|
|
104
|
+
player.connectionState === PlayerConnectionState.Connected) {
|
|
105
|
+
count++;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return count;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Find the host player.
|
|
112
|
+
*
|
|
113
|
+
* @returns The host player info, or undefined if no host
|
|
114
|
+
*/
|
|
115
|
+
findHost() {
|
|
116
|
+
for (const player of this.players.values()) {
|
|
117
|
+
if (player.isHost) {
|
|
118
|
+
return player;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Get all player IDs.
|
|
125
|
+
*/
|
|
126
|
+
getPlayerIds() {
|
|
127
|
+
return Array.from(this.players.keys());
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Get all player infos as an array.
|
|
131
|
+
*/
|
|
132
|
+
getAllPlayers() {
|
|
133
|
+
return Array.from(this.players.values());
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Clear all players.
|
|
137
|
+
*/
|
|
138
|
+
clear() {
|
|
139
|
+
this.players.clear();
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Number of players in the session.
|
|
143
|
+
*/
|
|
144
|
+
get size() {
|
|
145
|
+
return this.players.size;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Iterate over all players.
|
|
149
|
+
*/
|
|
150
|
+
[Symbol.iterator]() {
|
|
151
|
+
return this.players.values();
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Get players as a readonly map (for compatibility with existing code).
|
|
155
|
+
*/
|
|
156
|
+
asReadonlyMap() {
|
|
157
|
+
return this.players;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=player-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"player-manager.js","sourceRoot":"","sources":["../../src/session/player-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-level session manager that orchestrates the rollback engine and transport.
|
|
3
|
+
*
|
|
4
|
+
* Handles room management, player join/leave, message routing, and desync detection.
|
|
5
|
+
*/
|
|
6
|
+
import type { ConnectionMetrics, TransportAdapter } from "../transport/adapter.js";
|
|
7
|
+
import { type Game, type InputPredictor, PauseReason, type PlayerId, type PlayerInfo, PlayerRole, type SessionConfig, type SessionEvents, SessionState, type Tick, type TickResult } from "../types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Options for creating a session.
|
|
10
|
+
*/
|
|
11
|
+
export interface CreateSessionOptions {
|
|
12
|
+
/** The game instance to control */
|
|
13
|
+
game: Game;
|
|
14
|
+
/** Transport adapter for network communication */
|
|
15
|
+
transport: TransportAdapter;
|
|
16
|
+
/** Local player's ID (defaults to transport's localPeerId) */
|
|
17
|
+
localPlayerId?: PlayerId;
|
|
18
|
+
/** Session configuration (uses defaults if not specified) */
|
|
19
|
+
config?: Partial<SessionConfig>;
|
|
20
|
+
/** Custom input predictor */
|
|
21
|
+
inputPredictor?: InputPredictor<Uint8Array>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Session manager that coordinates the rollback engine with network transport.
|
|
25
|
+
*/
|
|
26
|
+
export declare class Session {
|
|
27
|
+
private readonly game;
|
|
28
|
+
private readonly transport;
|
|
29
|
+
private readonly config;
|
|
30
|
+
private readonly engine;
|
|
31
|
+
private readonly eventHandlers;
|
|
32
|
+
private readonly _localPlayerId;
|
|
33
|
+
private readonly topologyStrategy;
|
|
34
|
+
private readonly debug;
|
|
35
|
+
private readonly playerManager;
|
|
36
|
+
private readonly desyncManager;
|
|
37
|
+
private readonly lagMonitor;
|
|
38
|
+
private readonly joinRateLimiter;
|
|
39
|
+
private readonly messageRouter;
|
|
40
|
+
private _state;
|
|
41
|
+
private _isHost;
|
|
42
|
+
private _roomId;
|
|
43
|
+
private _localRole;
|
|
44
|
+
private lastHashBroadcastTick;
|
|
45
|
+
private readonly inputRedundancy;
|
|
46
|
+
/** Timer for periodic rate limit cleanup */
|
|
47
|
+
private rateLimitCleanupTimer;
|
|
48
|
+
/** Buffer for deferred hash comparison (processed after rollback in tick()) */
|
|
49
|
+
private pendingHashMessages;
|
|
50
|
+
/** Tracks players whose playerJoined event has been emitted to prevent duplicates during resimulation */
|
|
51
|
+
private readonly emittedJoinEvents;
|
|
52
|
+
/** Number of RTT samples to keep for averaging */
|
|
53
|
+
private static readonly RTT_SAMPLE_COUNT;
|
|
54
|
+
/** RTT tracking: peerId -> { pendingPings: Map<timestamp, sendTime>, rtt: number } */
|
|
55
|
+
private readonly peerRttData;
|
|
56
|
+
/**
|
|
57
|
+
* Create a new session.
|
|
58
|
+
* @throws ValidationError if config values are invalid
|
|
59
|
+
*/
|
|
60
|
+
constructor(options: CreateSessionOptions);
|
|
61
|
+
/**
|
|
62
|
+
* Create message handlers bound to this session.
|
|
63
|
+
*/
|
|
64
|
+
private createMessageHandlers;
|
|
65
|
+
/**
|
|
66
|
+
* Current session state.
|
|
67
|
+
*/
|
|
68
|
+
get state(): SessionState;
|
|
69
|
+
/**
|
|
70
|
+
* Map of all players in the session.
|
|
71
|
+
*/
|
|
72
|
+
get players(): ReadonlyMap<PlayerId, PlayerInfo>;
|
|
73
|
+
/**
|
|
74
|
+
* Local player's ID.
|
|
75
|
+
*/
|
|
76
|
+
get localPlayerId(): PlayerId;
|
|
77
|
+
/**
|
|
78
|
+
* Whether this session is the host.
|
|
79
|
+
*/
|
|
80
|
+
get isHost(): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Current room ID (null if not in a room).
|
|
83
|
+
*/
|
|
84
|
+
get roomId(): string | null;
|
|
85
|
+
/**
|
|
86
|
+
* Local player's role in the session.
|
|
87
|
+
*/
|
|
88
|
+
get localRole(): PlayerRole;
|
|
89
|
+
/**
|
|
90
|
+
* Set the local player's role.
|
|
91
|
+
* Must be called before joining a room or starting the game.
|
|
92
|
+
*
|
|
93
|
+
* @param role - The role to set ('pilot' or 'spectator')
|
|
94
|
+
* @throws Error if called while in a room
|
|
95
|
+
*/
|
|
96
|
+
setLocalRole(role: PlayerRole): void;
|
|
97
|
+
/**
|
|
98
|
+
* Current tick from the engine.
|
|
99
|
+
*/
|
|
100
|
+
get currentTick(): Tick;
|
|
101
|
+
/**
|
|
102
|
+
* Confirmed tick from the engine.
|
|
103
|
+
*/
|
|
104
|
+
get confirmedTick(): Tick;
|
|
105
|
+
/**
|
|
106
|
+
* Get connection quality metrics for a player.
|
|
107
|
+
*
|
|
108
|
+
* @param playerId - The player's ID
|
|
109
|
+
* @returns Connection metrics or null if not available
|
|
110
|
+
*/
|
|
111
|
+
getPlayerMetrics(playerId: PlayerId): ConnectionMetrics | null;
|
|
112
|
+
/**
|
|
113
|
+
* Destroy the session and clean up resources.
|
|
114
|
+
* Call this when the session is no longer needed.
|
|
115
|
+
*/
|
|
116
|
+
destroy(): void;
|
|
117
|
+
/**
|
|
118
|
+
* Create a new room and become the host.
|
|
119
|
+
*
|
|
120
|
+
* @returns The room ID
|
|
121
|
+
*/
|
|
122
|
+
createRoom(): Promise<string>;
|
|
123
|
+
/**
|
|
124
|
+
* Join an existing room.
|
|
125
|
+
*
|
|
126
|
+
* @param roomId - The room ID to join
|
|
127
|
+
* @param hostPeerId - The host's peer ID
|
|
128
|
+
*/
|
|
129
|
+
joinRoom(roomId: string, hostPeerId: string): Promise<void>;
|
|
130
|
+
/**
|
|
131
|
+
* Leave the current room.
|
|
132
|
+
*/
|
|
133
|
+
leaveRoom(): void;
|
|
134
|
+
/**
|
|
135
|
+
* Start the game (host only).
|
|
136
|
+
* Transitions from lobby to playing state.
|
|
137
|
+
*/
|
|
138
|
+
start(): void;
|
|
139
|
+
/**
|
|
140
|
+
* Pause the game (host only).
|
|
141
|
+
*/
|
|
142
|
+
pause(reason?: PauseReason): void;
|
|
143
|
+
/**
|
|
144
|
+
* Resume the game (host only).
|
|
145
|
+
*/
|
|
146
|
+
resume(): void;
|
|
147
|
+
/**
|
|
148
|
+
* Send a resume countdown to all players (host only).
|
|
149
|
+
* Use this before calling resume() to give players time to prepare.
|
|
150
|
+
*
|
|
151
|
+
* @param secondsRemaining - Number of seconds until resume
|
|
152
|
+
*/
|
|
153
|
+
sendResumeCountdown(secondsRemaining: number): void;
|
|
154
|
+
/**
|
|
155
|
+
* Drop a player from the game (host only).
|
|
156
|
+
* Use this to remove a disconnected or lagging player and allow the game to continue.
|
|
157
|
+
*
|
|
158
|
+
* @param playerId - The player to drop
|
|
159
|
+
* @param metadata - Optional metadata (e.g., AI replacement info)
|
|
160
|
+
*/
|
|
161
|
+
dropPlayer(playerId: PlayerId, metadata?: Uint8Array): void;
|
|
162
|
+
/**
|
|
163
|
+
* Advance the simulation by one tick.
|
|
164
|
+
* Call this at your game's tick rate (e.g., 60 times per second).
|
|
165
|
+
*
|
|
166
|
+
* @param localInput - The local player's input for this tick (required for pilots, ignored for spectators)
|
|
167
|
+
* @returns Tick result with rollback info
|
|
168
|
+
*/
|
|
169
|
+
tick(localInput?: Uint8Array): TickResult;
|
|
170
|
+
/**
|
|
171
|
+
* Request state sync from host (for desync recovery).
|
|
172
|
+
*/
|
|
173
|
+
requestSync(): void;
|
|
174
|
+
/**
|
|
175
|
+
* Register an event handler.
|
|
176
|
+
*/
|
|
177
|
+
on<E extends keyof SessionEvents>(event: E, handler: SessionEvents[E]): void;
|
|
178
|
+
/**
|
|
179
|
+
* Remove an event handler.
|
|
180
|
+
*/
|
|
181
|
+
off<E extends keyof SessionEvents>(event: E, handler: SessionEvents[E]): void;
|
|
182
|
+
/**
|
|
183
|
+
* Remove all event handlers.
|
|
184
|
+
*
|
|
185
|
+
* Optionally specify an event type to only remove handlers for that event.
|
|
186
|
+
* Call this during cleanup to prevent memory leaks.
|
|
187
|
+
*
|
|
188
|
+
* @param event - Optional event type to clear handlers for
|
|
189
|
+
*/
|
|
190
|
+
removeAllListeners<E extends keyof SessionEvents>(event?: E): void;
|
|
191
|
+
/**
|
|
192
|
+
* Emit an event to all registered handlers.
|
|
193
|
+
*/
|
|
194
|
+
private emit;
|
|
195
|
+
/**
|
|
196
|
+
* Emit an error event with context.
|
|
197
|
+
*/
|
|
198
|
+
private emitError;
|
|
199
|
+
/**
|
|
200
|
+
* Valid state transitions for the session state machine.
|
|
201
|
+
*
|
|
202
|
+
* State machine:
|
|
203
|
+
* ```
|
|
204
|
+
* Disconnected ──→ Connecting ──→ Lobby ──→ Playing ⇄ Paused
|
|
205
|
+
* ↑ │ │ │ │
|
|
206
|
+
* └───────────────┴────────────┴─────────┴─────────┘
|
|
207
|
+
* (any state can go to Disconnected)
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
private static readonly VALID_TRANSITIONS;
|
|
211
|
+
/**
|
|
212
|
+
* Update session state and emit event.
|
|
213
|
+
* Validates that the transition is allowed by the state machine.
|
|
214
|
+
* @throws Error if the transition is not valid
|
|
215
|
+
*/
|
|
216
|
+
private setState;
|
|
217
|
+
/**
|
|
218
|
+
* Handle decode error from message router.
|
|
219
|
+
*/
|
|
220
|
+
private handleDecodeError;
|
|
221
|
+
/**
|
|
222
|
+
* Handle incoming message from transport.
|
|
223
|
+
*/
|
|
224
|
+
private handleMessage;
|
|
225
|
+
/**
|
|
226
|
+
* Handle peer connection.
|
|
227
|
+
*/
|
|
228
|
+
private handlePeerConnect;
|
|
229
|
+
/**
|
|
230
|
+
* Handle peer disconnection.
|
|
231
|
+
*/
|
|
232
|
+
private handlePeerDisconnect;
|
|
233
|
+
/**
|
|
234
|
+
* Mark a player as disconnected and handle cleanup.
|
|
235
|
+
*/
|
|
236
|
+
private markPlayerDisconnected;
|
|
237
|
+
/**
|
|
238
|
+
* Handle disconnect report from a guest (host only, mesh+host-authority mode).
|
|
239
|
+
*/
|
|
240
|
+
private handleDisconnectReport;
|
|
241
|
+
/**
|
|
242
|
+
* Handle lag report from a guest (host only).
|
|
243
|
+
*/
|
|
244
|
+
private handleLagReport;
|
|
245
|
+
/**
|
|
246
|
+
* Check for lagging players and report to host (guests only, when lag threshold is set).
|
|
247
|
+
*/
|
|
248
|
+
private checkAndReportLag;
|
|
249
|
+
/**
|
|
250
|
+
* Handle resume countdown message.
|
|
251
|
+
*/
|
|
252
|
+
private handleResumeCountdown;
|
|
253
|
+
/**
|
|
254
|
+
* Handle drop player message.
|
|
255
|
+
*/
|
|
256
|
+
private handleDropPlayer;
|
|
257
|
+
/**
|
|
258
|
+
* Handle input message from remote player.
|
|
259
|
+
*/
|
|
260
|
+
private handleInputMessage;
|
|
261
|
+
/**
|
|
262
|
+
* Handle hash message for desync detection.
|
|
263
|
+
*/
|
|
264
|
+
private handleHashMessage;
|
|
265
|
+
/**
|
|
266
|
+
* Process pending hash comparisons after rollback has corrected state.
|
|
267
|
+
* Called from tick() after engine.tick() completes.
|
|
268
|
+
*/
|
|
269
|
+
private processPendingHashComparisons;
|
|
270
|
+
/**
|
|
271
|
+
* Handle sync message (state synchronization).
|
|
272
|
+
*/
|
|
273
|
+
private handleSyncMessage;
|
|
274
|
+
/**
|
|
275
|
+
* Handle sync request (host only).
|
|
276
|
+
*
|
|
277
|
+
* IMPORTANT: When a sync is requested, we broadcast the authoritative state
|
|
278
|
+
* to ALL players, not just the requester. This ensures all players are
|
|
279
|
+
* synchronized to the same tick, preventing tick divergence issues that
|
|
280
|
+
* can occur with latency:
|
|
281
|
+
*
|
|
282
|
+
* Without broadcast-to-all:
|
|
283
|
+
* 1. Player-2 desyncs, requests sync from host at tick X
|
|
284
|
+
* 2. With latency, host responds with state at tick X+3
|
|
285
|
+
* 3. Player-2 resets to tick X+3, but player-1/3 are at tick X+6
|
|
286
|
+
* 4. Player-1/3's input redundancy doesn't cover tick X+3
|
|
287
|
+
* 5. Player-2 can't advance confirmedTick -> max speculation -> deadlock
|
|
288
|
+
*
|
|
289
|
+
* With broadcast-to-all:
|
|
290
|
+
* - All players reset to the same tick simultaneously
|
|
291
|
+
* - No tick divergence, no deadlock
|
|
292
|
+
*/
|
|
293
|
+
private handleSyncRequest;
|
|
294
|
+
/**
|
|
295
|
+
* Handle join request (host only).
|
|
296
|
+
*/
|
|
297
|
+
private handleJoinRequest;
|
|
298
|
+
/**
|
|
299
|
+
* Handle join accept.
|
|
300
|
+
*/
|
|
301
|
+
private handleJoinAccept;
|
|
302
|
+
/**
|
|
303
|
+
* Handle join reject.
|
|
304
|
+
*/
|
|
305
|
+
private handleJoinReject;
|
|
306
|
+
/**
|
|
307
|
+
* Handle player joined notification.
|
|
308
|
+
*/
|
|
309
|
+
private handlePlayerJoined;
|
|
310
|
+
/**
|
|
311
|
+
* Handle player left notification.
|
|
312
|
+
*/
|
|
313
|
+
private handlePlayerLeft;
|
|
314
|
+
/**
|
|
315
|
+
* Handle pause message.
|
|
316
|
+
*/
|
|
317
|
+
private handlePause;
|
|
318
|
+
/**
|
|
319
|
+
* Handle resume message.
|
|
320
|
+
*/
|
|
321
|
+
private handleResume;
|
|
322
|
+
/**
|
|
323
|
+
* Handle ping message - respond with pong.
|
|
324
|
+
*/
|
|
325
|
+
private handlePing;
|
|
326
|
+
/**
|
|
327
|
+
* Handle pong message - calculate RTT.
|
|
328
|
+
*/
|
|
329
|
+
private handlePong;
|
|
330
|
+
/**
|
|
331
|
+
* Send a ping to a peer for RTT measurement.
|
|
332
|
+
*
|
|
333
|
+
* @param peerId - The peer to ping
|
|
334
|
+
*/
|
|
335
|
+
sendPing(peerId: string): void;
|
|
336
|
+
/**
|
|
337
|
+
* Get the measured RTT to a peer in milliseconds.
|
|
338
|
+
* Returns 0 if no RTT data is available yet.
|
|
339
|
+
*
|
|
340
|
+
* @param peerId - The peer to get RTT for
|
|
341
|
+
*/
|
|
342
|
+
getRtt(peerId: string): number;
|
|
343
|
+
/**
|
|
344
|
+
* Broadcast input to all peers with redundancy.
|
|
345
|
+
*/
|
|
346
|
+
private broadcastInput;
|
|
347
|
+
/**
|
|
348
|
+
* Maybe broadcast hash for desync detection.
|
|
349
|
+
*
|
|
350
|
+
* IMPORTANT: We only broadcast hashes for CONFIRMED ticks, not just completed ticks.
|
|
351
|
+
* A completed tick may have used predicted inputs that turn out to be wrong.
|
|
352
|
+
* Broadcasting a hash based on predictions would cause false desync detections
|
|
353
|
+
* when compared against a peer who has the actual inputs.
|
|
354
|
+
*
|
|
355
|
+
* We find the most recent hash-interval tick that is confirmed and broadcast that.
|
|
356
|
+
*/
|
|
357
|
+
private maybeBroadcastHash;
|
|
358
|
+
/**
|
|
359
|
+
* Record a hash from a player and check for desync (host-authority mode).
|
|
360
|
+
*/
|
|
361
|
+
private recordHashAndCheckDesync;
|
|
362
|
+
/**
|
|
363
|
+
* Send a message to all connected peers.
|
|
364
|
+
*/
|
|
365
|
+
private broadcast;
|
|
366
|
+
/**
|
|
367
|
+
* Send a message to a specific peer.
|
|
368
|
+
*/
|
|
369
|
+
private sendToPeer;
|
|
370
|
+
/**
|
|
371
|
+
* Send a message to the host.
|
|
372
|
+
*/
|
|
373
|
+
private sendToHost;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Convenience function to create a session.
|
|
377
|
+
*/
|
|
378
|
+
export declare function createSession(options: CreateSessionOptions): Session;
|
|
379
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/session/session.ts"],"names":[],"mappings":"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"}
|