@antha/multiplayer-p2p-lock-step 0.0.3 → 0.0.5

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.
@@ -1,7 +1,7 @@
1
1
  import { type ApiAndRoomConnectionState, type ClientId, ControllerClientEvent, ControllerConnectionEvent, ControllerRoomListEvent, type ControllerRoomListListener, type MultiplayerInitParams, type MultiplayerRoomConnection, MultiplayerRoomController, type RoomInput, RoomRejectionError } from '@antha/multiplayer-core';
2
2
  import { type JsonCompatibleValue, type MaybePromise, type PartialWithUndefined } from '@augment-vir/common';
3
3
  import { type AnyDuration } from 'date-vir';
4
- import { ListenTarget, type TypedCustomEventInit } from 'typed-event-target';
4
+ import { ListenTarget, type RemoveListenerCallback, type TypedCustomEventInit } from 'typed-event-target';
5
5
  /**
6
6
  * Message type for {@link P2pLockStepMessage}.
7
7
  *
@@ -18,7 +18,7 @@ export declare enum P2pLockStepMessageType {
18
18
  */
19
19
  export type FrameEventDetail<MultiplayerPacket extends JsonCompatibleValue> = {
20
20
  packet: MultiplayerPacket;
21
- clientId: ClientId;
21
+ sourceClientId: ClientId;
22
22
  };
23
23
  /**
24
24
  * Message exchanged by p2p-lock-step clients.
@@ -31,7 +31,9 @@ export type P2pLockStepMessage<MultiplayerPacket extends JsonCompatibleValue> =
31
31
  type: P2pLockStepMessageType.Actions;
32
32
  sourceClientId: ClientId;
33
33
  actions: MultiplayerPacket[];
34
- } | {
34
+ }
35
+ /** Sent from the host to clients when a frame is ready. */
36
+ | {
35
37
  type: P2pLockStepMessageType.Frame;
36
38
  actions: FrameEventDetail<MultiplayerPacket>[];
37
39
  };
@@ -146,7 +148,9 @@ export declare class P2pLockStepMultiplayerController<MultiplayerPacket extends
146
148
  *
147
149
  * If a callback is provided, it is called each time the room list is updated.
148
150
  */
149
- startRoomUpdates(callback?: ControllerRoomListListener | undefined): import("typed-event-target").RemoveListenerCallback;
151
+ startRoomUpdates(callback: ControllerRoomListListener): RemoveListenerCallback;
152
+ startRoomUpdates(callback?: undefined): undefined;
153
+ startRoomUpdates(callback?: ControllerRoomListListener | undefined): RemoveListenerCallback | undefined;
150
154
  /** Turn off room list updates and remove callbacks added via `startRoomUpdates`. */
151
155
  stopRoomUpdates(): void;
152
156
  /** Currently joined room id. If a room has not been joined yet, this will be empty. */
@@ -202,12 +206,13 @@ export declare class P2pLockStepMultiplayerController<MultiplayerPacket extends
202
206
  isConnected(): boolean;
203
207
  /** Cleanup everything. */
204
208
  destroy(): void;
205
- /**
206
- * Join or create a room.
207
- *
208
- * @throws `Error` if this controller is already connected to a room.
209
- */
209
+ /** Join or create a room. */
210
210
  joinOrCreateRoom(room: Readonly<RoomInput>): Promise<void>;
211
+ /** Join through the core room controller while preserving the wrapper connection on failure. */
212
+ protected joinRoom({ previousRoomConnection, room, }: Readonly<{
213
+ previousRoomConnection: MultiplayerRoomConnection<P2pLockStepMessage<MultiplayerPacket>> | undefined;
214
+ room: Readonly<RoomInput>;
215
+ }>): Promise<MultiplayerRoomConnection<P2pLockStepMessage<MultiplayerPacket>>>;
211
216
  /** Leave the current room or single player connection. */
212
217
  leaveRoom(): void;
213
218
  /** Forward core room-controller events into this frame-sync controller. */
@@ -1,7 +1,7 @@
1
1
  import { ControllerClientEvent, ControllerConnectionEvent, ControllerMessageEvent, ControllerRoomListEvent, createMultiplayerId, emptyApiAndRoomConnectionState, MultiplayerConnectionState, MultiplayerRoomController, RoomRejectionError, } from '@antha/multiplayer-core';
2
2
  import { ensureArray, log, makeWritable, } from '@augment-vir/common';
3
3
  import { convertDuration } from 'date-vir';
4
- import { defineTypedCustomEvent, ListenTarget } from 'typed-event-target';
4
+ import { defineTypedCustomEvent, ListenTarget, } from 'typed-event-target';
5
5
  /**
6
6
  * Message type for {@link P2pLockStepMessage}.
7
7
  *
@@ -85,11 +85,6 @@ export class P2pLockStepMultiplayerController extends ListenTarget {
85
85
  get clientId() {
86
86
  return this.roomConnection?.clientId || this.localClientId;
87
87
  }
88
- /**
89
- * Listen for room list updates, including while connected to a room.
90
- *
91
- * If a callback is provided, it is called each time the room list is updated.
92
- */
93
88
  startRoomUpdates(callback) {
94
89
  return this.roomController.startRoomUpdates(callback);
95
90
  }
@@ -203,7 +198,7 @@ export class P2pLockStepMultiplayerController extends ListenTarget {
203
198
  ...this.frameActions,
204
199
  ...actionArray.map((packet) => {
205
200
  return {
206
- clientId: this.clientId,
201
+ sourceClientId: this.clientId,
207
202
  packet,
208
203
  };
209
204
  }),
@@ -226,28 +221,39 @@ export class P2pLockStepMultiplayerController extends ListenTarget {
226
221
  this.roomController.destroy();
227
222
  super.destroy();
228
223
  }
229
- /**
230
- * Join or create a room.
231
- *
232
- * @throws `Error` if this controller is already connected to a room.
233
- */
224
+ /** Join or create a room. */
234
225
  async joinOrCreateRoom(room) {
235
- if (this.currentConnection) {
226
+ if (this.singleplayer) {
236
227
  throw new Error('Cannot join room: connection already established.');
237
228
  }
229
+ const previousRoomConnection = this.roomConnection;
238
230
  this.debugLog(`joining or creating room '${room.roomName}' (${room.roomId})`);
231
+ const roomConnection = await this.joinRoom({
232
+ previousRoomConnection,
233
+ room,
234
+ });
235
+ if (previousRoomConnection) {
236
+ globalThis.clearTimeout(this.timeoutId);
237
+ this.clientsResponded = {};
238
+ this.frameActions = [];
239
+ this.frameTickReady = true;
240
+ }
241
+ this.attachMultiplayerRoomConnection(roomConnection);
242
+ this.debugLog(`attached p2p-lock-step connection; client=${this.getClientId() || 'unknown'} host=${this.isHost()} connected=${this.isConnected()}`);
243
+ }
244
+ /** Join through the core room controller while preserving the wrapper connection on failure. */
245
+ async joinRoom({ previousRoomConnection, room, }) {
239
246
  try {
240
247
  await this.roomController.joinOrCreateRoom(room);
241
248
  this.debugLog(`room controller joined room '${room.roomName}' (${room.roomId}); client=${this.roomController.getClientId() || 'unknown'} host=${this.roomController.isHost()}`);
242
249
  if (!this.roomController.currentConnection) {
243
250
  throw new Error('Cannot start p2p-lock-step multiplayer: room connection is missing.');
244
251
  }
245
- this.attachMultiplayerRoomConnection(this.roomController.currentConnection);
246
- this.debugLog(`attached p2p-lock-step connection; client=${this.getClientId() || 'unknown'} host=${this.isHost()} connected=${this.isConnected()}`);
252
+ return this.roomController.currentConnection;
247
253
  }
248
254
  catch (error) {
249
255
  this.debugLog(`join room failed: ${String(error)}`);
250
- this.roomConnection = undefined;
256
+ this.roomConnection = previousRoomConnection;
251
257
  throw error;
252
258
  }
253
259
  }
@@ -327,7 +333,7 @@ export class P2pLockStepMultiplayerController extends ListenTarget {
327
333
  ...this.frameActions,
328
334
  ...message.actions.map((packet) => {
329
335
  return {
330
- clientId: sourceClientId,
336
+ sourceClientId,
331
337
  packet,
332
338
  };
333
339
  }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antha/multiplayer-p2p-lock-step",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "Multiplayer mod for the Antha engine.",
5
5
  "keywords": [
6
6
  "vir",
@@ -49,7 +49,7 @@
49
49
  "istanbul-smart-text-reporter": "^1.1.5"
50
50
  },
51
51
  "peerDependencies": {
52
- "@antha/multiplayer-core": "^0.0.3"
52
+ "@antha/multiplayer-core": "^0.0.5"
53
53
  },
54
54
  "engines": {
55
55
  "node": ">=22"