playsocketjs 1.1.4 → 1.1.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.
@@ -1731,9 +1731,9 @@ function requireCrdtManager () {
1731
1731
  this.#propertyStore = {};
1732
1732
  this.#lastPropertyStore = {};
1733
1733
 
1734
- this.#keyOperations = new Map(keyOperations); // Rebuild the map
1735
- this.#vectorClock = new Map(vectorClock); // Also rebuild the map here
1736
- if (!this.#vectorClock.has(this.#replicaId)) this.#vectorClock.set(this.#replicaId, 0); // Reset own vector clock if it wasn't present in the imported state
1734
+ this.#keyOperations = new Map(keyOperations); // Rebuild the operations map
1735
+ this.#vectorClock = new Map(vectorClock); // Rebuild the vector clock map
1736
+ if (!this.#vectorClock.has(this.#replicaId)) this.#vectorClock.set(this.#replicaId, 0); // Add own vector clock if it wasn't present in the imported state
1737
1737
 
1738
1738
  // Map operation uuids to timestamp
1739
1739
  this.#keyOperations.forEach((value, key) => {
@@ -2065,7 +2065,6 @@ class PlaySocket {
2065
2065
  #connectionCount = 0;
2066
2066
  #crdtManager;
2067
2067
  #roomVersion = 0; // Update version (used to compare local vs. remote state to detect package loss)
2068
- #sentUpdates = new Set(); // Contains update uuids
2069
2068
 
2070
2069
  // Event handling
2071
2070
  #callbacks = new Map(); // Event callbacks
@@ -2076,7 +2075,6 @@ class PlaySocket {
2076
2075
  #pendingRegistration;
2077
2076
  #pendingConnect;
2078
2077
  #pendingReconnect;
2079
- #pendingStateRequest;
2080
2078
 
2081
2079
  // Timeouts or intervals
2082
2080
  #reconnectTimeout;
@@ -2281,24 +2279,15 @@ class PlaySocket {
2281
2279
  }
2282
2280
  break;
2283
2281
 
2284
- case 'state_sync':
2285
- if (this.#pendingStateRequest) {
2286
- if (this.#debug) console.log(LOG_PREFIX + "State received following state request:", message.state);
2287
- this.#roomVersion = message.version;
2288
- this.#crdtManager.importState(message.state);
2289
- this.#triggerEvent("storageUpdated", this.getStorage);
2290
- this.#triggerEvent("status", "State synchronized.");
2291
- this.#pendingStateRequest.resolve();
2292
- }
2293
- break;
2294
-
2295
2282
  case 'property_update':
2296
2283
  this.#roomVersion++; // Increment room version
2297
2284
  if (this.#debug) console.log(LOG_PREFIX + "Property update received:", message.update);
2298
- this.#sentUpdates.delete(message.uuid); // If this is our sent update, delete it so that timeout check knows it was received
2299
2285
  this.#crdtManager.importPropertyUpdate(message.update);
2300
2286
  if (this.#crdtManager.didPropertiesChange) this.#triggerEvent("storageUpdated", this.getStorage);
2301
- if (this.#roomVersion != message.version) this.#requestStateSyncIfConnected();
2287
+ if (this.#roomVersion != message.version && this.#initialized && this.#socket?.readyState === WebSocket.OPEN) {
2288
+ this.#triggerEvent("error", "Detected skipped update – forcing reconnect.");
2289
+ this.#socket?.close();
2290
+ }
2302
2291
  break;
2303
2292
 
2304
2293
  case 'client_disconnected':
@@ -2368,33 +2357,6 @@ class PlaySocket {
2368
2357
  }
2369
2358
  }
2370
2359
 
2371
- /**
2372
- * If the local state is out of sync, request the room state
2373
- */
2374
- async #requestStateSyncIfConnected(notSent = false) {
2375
- if (this.#pendingStateRequest || !this.#initialized || this.#socket?.readyState !== WebSocket.OPEN) return; // Return if already requested, destroyed or connection not open
2376
-
2377
- // Trigger corresponding events
2378
- if (!notSent) this.#triggerEvent("error", "Detected skipped update – requesting state.");
2379
- else this.#triggerEvent("error", "Sent update did not go through – requesting state.");
2380
-
2381
- try {
2382
- await Promise.race([
2383
- new Promise(async (resolve, reject) => {
2384
- this.#pendingStateRequest = { resolve, reject };
2385
- this.#sendToServer({ type: 'request_state' });
2386
- }),
2387
- this.#createTimeout("State request")
2388
- ]).finally(() => {
2389
- this.#pendingStateRequest = null;
2390
- });
2391
- } catch (error) {
2392
- if (!this.#initialized) return;
2393
- this.#triggerEvent("error", "Failed to re-sync state: " + error.message);
2394
- this.destroy();
2395
- }
2396
- }
2397
-
2398
2360
  /**
2399
2361
  * Update the host in case a new one was chosen
2400
2362
  * @param {string} hostId - Client id of new host
@@ -2493,17 +2455,11 @@ class PlaySocket {
2493
2455
  updateStorage(key, value) {
2494
2456
  if (this.#debug) console.log(LOG_PREFIX + "Property set update for key '" + key + "':", value);
2495
2457
  const propUpdate = this.#crdtManager.updateProperty(key, "set", value);
2496
- const updateUuid = crypto.randomUUID();
2497
- this.#sentUpdates.add(updateUuid);
2498
2458
  this.#sendToServer({
2499
2459
  type: 'property_update',
2500
2460
  key,
2501
- update: propUpdate,
2502
- uuid: updateUuid
2461
+ update: propUpdate
2503
2462
  });
2504
- setTimeout(() => {
2505
- if (this.#sentUpdates.has(updateUuid)) this.#requestStateSyncIfConnected(true);
2506
- }, TIMEOUT_MS);
2507
2463
  if (this.#crdtManager.didPropertiesChange) this.#triggerEvent("storageUpdated", this.getStorage); // Always trigger callback after send in case msgs are sent in the callback (which would break the order)
2508
2464
  }
2509
2465
 
@@ -2517,17 +2473,11 @@ class PlaySocket {
2517
2473
  updateStorageArray(key, operation, value, updateValue) {
2518
2474
  if (this.#debug) console.log(LOG_PREFIX + `Property array update for key '${key}', operation '${operation}', value '${value}' and updateValue '${updateValue}'.`);
2519
2475
  const propUpdate = this.#crdtManager.updateProperty(key, "array-" + operation, value, updateValue);
2520
- const updateUuid = crypto.randomUUID();
2521
- this.#sentUpdates.add(updateUuid);
2522
2476
  this.#sendToServer({
2523
2477
  type: 'property_update',
2524
2478
  key,
2525
- update: propUpdate,
2526
- uuid: updateUuid
2479
+ update: propUpdate
2527
2480
  });
2528
- setTimeout(() => {
2529
- if (this.#sentUpdates.has(updateUuid)) this.#requestStateSyncIfConnected(true);
2530
- }, TIMEOUT_MS);
2531
2481
  if (this.#crdtManager.didPropertiesChange) this.#triggerEvent("storageUpdated", this.getStorage);
2532
2482
  }
2533
2483
 
@@ -2556,7 +2506,6 @@ class PlaySocket {
2556
2506
  this.#isReconnecting = false;
2557
2507
  this.#reconnectCount = 0;
2558
2508
  this.#roomVersion = 0;
2559
- this.#sentUpdates.clear();
2560
2509
 
2561
2510
  // Reject timeouts if currently active
2562
2511
  if (this.#pendingJoin) this.#pendingJoin.reject();
@@ -2564,7 +2513,6 @@ class PlaySocket {
2564
2513
  if (this.#pendingRegistration) this.#pendingRegistration.reject();
2565
2514
  if (this.#pendingConnect) this.#pendingConnect.reject();
2566
2515
  if (this.#pendingReconnect) this.#pendingReconnect.reject();
2567
- if (this.#pendingStateRequest) this.#pendingStateRequest.reject();
2568
2516
  }
2569
2517
 
2570
2518
  // Public getters
@@ -1857,9 +1857,9 @@ function requireCrdtManager () {
1857
1857
  this.#propertyStore = {};
1858
1858
  this.#lastPropertyStore = {};
1859
1859
 
1860
- this.#keyOperations = new Map(keyOperations); // Rebuild the map
1861
- this.#vectorClock = new Map(vectorClock); // Also rebuild the map here
1862
- if (!this.#vectorClock.has(this.#replicaId)) this.#vectorClock.set(this.#replicaId, 0); // Reset own vector clock if it wasn't present in the imported state
1860
+ this.#keyOperations = new Map(keyOperations); // Rebuild the operations map
1861
+ this.#vectorClock = new Map(vectorClock); // Rebuild the vector clock map
1862
+ if (!this.#vectorClock.has(this.#replicaId)) this.#vectorClock.set(this.#replicaId, 0); // Add own vector clock if it wasn't present in the imported state
1863
1863
 
1864
1864
  // Map operation uuids to timestamp
1865
1865
  this.#keyOperations.forEach((value, key) => {
@@ -2239,7 +2239,7 @@ function requireServer () {
2239
2239
  ws.isAlive = false;
2240
2240
  ws.ping();
2241
2241
  });
2242
- }, 30000);
2242
+ }, 15000);
2243
2243
  }
2244
2244
 
2245
2245
  /**
@@ -2309,18 +2309,6 @@ function requireServer () {
2309
2309
  }
2310
2310
  break;
2311
2311
 
2312
- case 'request_state':
2313
- const stateRoomId = this.#clientRooms.get(ws.clientId);
2314
- const stateRoom = stateRoomId ? this.#rooms[stateRoomId] : null;
2315
- if (stateRoom) {
2316
- ws.send(encode({
2317
- type: 'state_sync',
2318
- state: stateRoom.crdtManager.getState,
2319
- version: this.#roomVersions.get(stateRoomId)
2320
- }), { binary: true });
2321
- }
2322
- break;
2323
-
2324
2312
  case 'create_room':
2325
2313
  if (!ws.clientId) return;
2326
2314
  const newRoomId = ws.clientId;
@@ -2400,7 +2388,7 @@ function requireServer () {
2400
2388
  const updateRoomId = this.#clientRooms.get(ws.clientId);
2401
2389
  const updateRoom = updateRoomId ? this.#rooms[updateRoomId] : null;
2402
2390
 
2403
- if (updateRoom && data.key && data.update && data.uuid) {
2391
+ if (updateRoom && data.key && data.update) {
2404
2392
  updateRoom.crdtManager.importPropertyUpdate(data.update);
2405
2393
 
2406
2394
  // Increment version for this room
@@ -2414,8 +2402,7 @@ function requireServer () {
2414
2402
  client.send(encode({
2415
2403
  type: 'property_update',
2416
2404
  update: data.update,
2417
- version: currentVersion,
2418
- uuid: data.uuid
2405
+ version: currentVersion
2419
2406
  }), { binary: true });
2420
2407
  }
2421
2408
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playsocketjs",
3
- "version": "1.1.4",
3
+ "version": "1.1.5",
4
4
  "description": "WebSocket wrapper for creating simple multiplayer systems with ease.",
5
5
  "module": "dist/playsocket-client.js",
6
6
  "exports": {