playsocketjs 1.1.8 → 1.1.9

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.
@@ -2287,9 +2287,17 @@ class PlaySocket {
2287
2287
  }
2288
2288
  break;
2289
2289
 
2290
+ case 'server_stopped':
2291
+ this.#triggerEvent("error", "Server restart.");
2292
+ this.destroy();
2293
+ break;
2294
+
2295
+ case 'host_migrated':
2296
+ this.#setHost(message.newHost);
2297
+ break;
2298
+
2290
2299
  case 'client_disconnected':
2291
2300
  this.#connectionCount = message.participantCount - 1; // Counted without the user themselves
2292
- this.#setHost(message.host);
2293
2301
  this.#triggerEvent("clientDisconnected", message.client);
2294
2302
  this.#triggerEvent("status", `Client ${message.client} disconnected.`);
2295
2303
  break;
@@ -2306,7 +2306,7 @@ function requireServer () {
2306
2306
  roomData = {
2307
2307
  state: formerRoom.crdtManager.getState,
2308
2308
  participantCount: formerRoom.participants.length,
2309
- host: formerRoom.participants[0],
2309
+ host: formerRoom.host,
2310
2310
  version: this.#roomVersions.get(formerRoomId)
2311
2311
  };
2312
2312
  }
@@ -2332,6 +2332,7 @@ function requireServer () {
2332
2332
  this.#roomVersions.set(newRoomId, 0); // Start with version 0
2333
2333
  this.#rooms[newRoomId] = {
2334
2334
  participants: [ws.clientId],
2335
+ host: ws.clientId,
2335
2336
  maxSize: data.size || null,
2336
2337
  crdtManager: new CRDTManager(crypto.randomUUID(), this.#debug)
2337
2338
  };
@@ -2373,7 +2374,7 @@ function requireServer () {
2373
2374
  type: 'join_accepted',
2374
2375
  state: room.crdtManager.getState,
2375
2376
  participantCount: room.participants.length,
2376
- host: room.participants[0],
2377
+ host: room.host,
2377
2378
  version: this.#roomVersions.get(roomId)
2378
2379
  }), { binary: true });
2379
2380
 
@@ -2427,6 +2428,29 @@ function requireServer () {
2427
2428
  }
2428
2429
  }
2429
2430
 
2431
+ /**
2432
+ * If the client that disconnected (and is now in the reconnection-phase) was the room host,
2433
+ * pick a new room host immediately to avoid host-less phase (in case important logic is attached to the host)
2434
+ * @param {string} roomId
2435
+ * @param {string} clientId
2436
+ */
2437
+ #changeHostIfDisconnected(roomId, clientId) {
2438
+ const room = this.#rooms[roomId];
2439
+ if (room && room.host === clientId && room.participants.length > 1) {
2440
+ const participantsWithoutClient = room.participants.filter((e) => e !== clientId);
2441
+ room.host = participantsWithoutClient[0]; // Set new host
2442
+
2443
+ // Inform all participants about the new host
2444
+ participantsWithoutClient.forEach(p => {
2445
+ const client = this.#clients.get(p);
2446
+ if (client) client.send(encode({
2447
+ type: 'host_migrated',
2448
+ newHost: room.host,
2449
+ }), { binary: true });
2450
+ });
2451
+ }
2452
+ }
2453
+
2430
2454
  /**
2431
2455
  * Generate a random token to prevent malicious reconnect attempts
2432
2456
  * @returns {string} - Token
@@ -2473,6 +2497,10 @@ function requireServer () {
2473
2497
  if (!ws.clientId) return;
2474
2498
  this.#clients.delete(ws.clientId); // Immediately remove from active clients (otherwise, server would try to message this client)
2475
2499
 
2500
+ // If client was in a room, check if they were the host & migrate
2501
+ const roomId = this.#clientRooms.get(ws.clientId);
2502
+ if (roomId != null) this.#changeHostIfDisconnected(roomId, ws.clientId);
2503
+
2476
2504
  if (ws.willfulDisconnect) {
2477
2505
  this.#disconnectClient(ws); // Immediate disconnection
2478
2506
  } else {
@@ -2512,7 +2540,6 @@ function requireServer () {
2512
2540
  if (client) client.send(encode({
2513
2541
  type: 'client_disconnected',
2514
2542
  client: ws.clientId,
2515
- host: room.participants[0],
2516
2543
  participantCount: room.participants.length
2517
2544
  }), { binary: true });
2518
2545
  });
@@ -2551,7 +2578,10 @@ function requireServer () {
2551
2578
  stop() {
2552
2579
  clearInterval(this.#heartbeatInterval);
2553
2580
  if (this.#wss) {
2554
- this.#wss.clients.forEach(client => client.close());
2581
+ this.#wss.clients.forEach(client => {
2582
+ client.send(encode({ type: 'server_stopped' }), { binary: true });
2583
+ client.close();
2584
+ });
2555
2585
  this.#wss.close();
2556
2586
  }
2557
2587
  if (this.#server && this.#ownsServer) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playsocketjs",
3
- "version": "1.1.8",
3
+ "version": "1.1.9",
4
4
  "description": "WebSocket wrapper for creating simple multiplayer systems with ease.",
5
5
  "module": "dist/playsocket-client.js",
6
6
  "exports": {