playsocketjs 1.0.11 → 1.0.12
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/dist/playsocket-client.js +3 -26
- package/dist/playsocket-server.js +9 -16
- package/package.json +1 -1
|
@@ -17,11 +17,9 @@ class PlaySocket {
|
|
|
17
17
|
|
|
18
18
|
// Room properties
|
|
19
19
|
#storage = {}; // Shared storage object
|
|
20
|
-
#storageTimestamps = {}; // Tracks update timestamps per key to ensure that not-yet synced updates don't get overwritten
|
|
21
20
|
#roomHost;
|
|
22
21
|
#roomId; // ID of the host (client only)
|
|
23
22
|
#connectionCount = 0;
|
|
24
|
-
#serverTimeOffset = 0; // Offset between server time and local time
|
|
25
23
|
|
|
26
24
|
// Event handling
|
|
27
25
|
#callbacks = new Map(); // Event callbacks
|
|
@@ -61,14 +59,6 @@ class PlaySocket {
|
|
|
61
59
|
);
|
|
62
60
|
}
|
|
63
61
|
|
|
64
|
-
/**
|
|
65
|
-
* Get synchronized timestamp
|
|
66
|
-
* @private
|
|
67
|
-
*/
|
|
68
|
-
#getTimestamp() {
|
|
69
|
-
return Date.now() + this.#serverTimeOffset;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
62
|
/**
|
|
73
63
|
* Register an event callback
|
|
74
64
|
* @param {string} event - Event name
|
|
@@ -119,8 +109,7 @@ class PlaySocket {
|
|
|
119
109
|
this.#sendToServer({
|
|
120
110
|
type: 'register',
|
|
121
111
|
id: this.#id,
|
|
122
|
-
customData: this.#customData || undefined
|
|
123
|
-
clientTime: Date.now()
|
|
112
|
+
customData: this.#customData || undefined
|
|
124
113
|
});
|
|
125
114
|
}),
|
|
126
115
|
this.#createTimeout("Registration")
|
|
@@ -163,7 +152,6 @@ class PlaySocket {
|
|
|
163
152
|
// Connected to room
|
|
164
153
|
if (this.#pendingJoin) {
|
|
165
154
|
this.#storage = message.storage;
|
|
166
|
-
this.#storageTimestamps = message.storageTimestamps;
|
|
167
155
|
this.#connectionCount = message.participantCount - 1; // Counted without the user themselves
|
|
168
156
|
this.#roomHost = message.host;
|
|
169
157
|
this.#triggerEvent("status", `Connected to room.`);
|
|
@@ -187,7 +175,6 @@ class PlaySocket {
|
|
|
187
175
|
this.#reconnectCount = 0;
|
|
188
176
|
if (message.roomData) {
|
|
189
177
|
this.#storage = message.roomData.storage;
|
|
190
|
-
this.#storageTimestamps = message.roomData.storageTimestamps;
|
|
191
178
|
this.#connectionCount = message.roomData.participantCount - 1; // Counted without the user themselves
|
|
192
179
|
this.#setHost(message.roomData.host);
|
|
193
180
|
this.#triggerEvent("storageUpdated", { ...this.#storage });
|
|
@@ -233,9 +220,6 @@ class PlaySocket {
|
|
|
233
220
|
|
|
234
221
|
case 'registered':
|
|
235
222
|
if (this.#pendingRegistration) {
|
|
236
|
-
const roundTripTime = Date.now() - message.clientTime;
|
|
237
|
-
const serverTimeAtClientNow = message.serverTime + (roundTripTime / 2);
|
|
238
|
-
this.#serverTimeOffset = serverTimeAtClientNow - Date.now();
|
|
239
223
|
this.#sessionToken = message.sessionToken;
|
|
240
224
|
this.#initialized = true;
|
|
241
225
|
this.#pendingRegistration.resolve();
|
|
@@ -245,10 +229,8 @@ class PlaySocket {
|
|
|
245
229
|
|
|
246
230
|
case 'storage_sync':
|
|
247
231
|
if (message.key) {
|
|
248
|
-
|
|
249
|
-
if (message.timestamp > localTimestamp && JSON.stringify(this.#storage[message.key]) !== JSON.stringify(message.value)) {
|
|
232
|
+
if (JSON.stringify(this.#storage[message.key]) !== JSON.stringify(message.value)) {
|
|
250
233
|
this.#storage[message.key] = message.value;
|
|
251
|
-
this.#storageTimestamps[message.key] = message.timestamp;
|
|
252
234
|
this.#triggerEvent("storageUpdated", { ...this.#storage });
|
|
253
235
|
}
|
|
254
236
|
}
|
|
@@ -417,16 +399,13 @@ class PlaySocket {
|
|
|
417
399
|
*/
|
|
418
400
|
updateStorage(key, value) {
|
|
419
401
|
if (JSON.stringify(this.#storage[key]) === JSON.stringify(value)) return; // Prevent updates without changes
|
|
420
|
-
const timestamp = this.#getTimestamp();
|
|
421
402
|
this.#sendToServer({
|
|
422
403
|
type: 'room_storage_update',
|
|
423
404
|
key,
|
|
424
|
-
value
|
|
425
|
-
timestamp
|
|
405
|
+
value
|
|
426
406
|
});
|
|
427
407
|
// Optimistic update for regular storage updates
|
|
428
408
|
this.#storage[key] = value;
|
|
429
|
-
this.#storageTimestamps[key] = timestamp;
|
|
430
409
|
this.#triggerEvent("storageUpdated", { ...this.#storage });
|
|
431
410
|
}
|
|
432
411
|
|
|
@@ -470,8 +449,6 @@ class PlaySocket {
|
|
|
470
449
|
clearTimeout(this.#reconnectTimeout);
|
|
471
450
|
this.#roomHost = null;
|
|
472
451
|
this.#storage = {};
|
|
473
|
-
this.#storageTimestamps = {};
|
|
474
|
-
this.#serverTimeOffset = 0;
|
|
475
452
|
this.#roomId = null;
|
|
476
453
|
this.#connectionCount = 0;
|
|
477
454
|
this.#isReconnecting = false;
|
|
@@ -102,7 +102,7 @@ function requireServer () {
|
|
|
102
102
|
this.#clients.set(data.id, ws);
|
|
103
103
|
const sessionToken = this.#generateSessionToken();
|
|
104
104
|
this.#clientTokens.set(data.id, sessionToken); // Token is used when reconnecting to prevent impersonation attacks
|
|
105
|
-
ws.send(JSON.stringify({ type: 'registered', sessionToken
|
|
105
|
+
ws.send(JSON.stringify({ type: 'registered', sessionToken }));
|
|
106
106
|
this.#triggerEvent("clientRegistered", data.id, data.customData);
|
|
107
107
|
break;
|
|
108
108
|
|
|
@@ -127,7 +127,6 @@ function requireServer () {
|
|
|
127
127
|
if (formerRoom) {
|
|
128
128
|
roomData = {
|
|
129
129
|
storage: formerRoom.storage,
|
|
130
|
-
storageTimestamps: formerRoom.storageTimestamps,
|
|
131
130
|
participantCount: formerRoom.participants.length,
|
|
132
131
|
host: formerRoom.participants[0]
|
|
133
132
|
};
|
|
@@ -153,8 +152,7 @@ function requireServer () {
|
|
|
153
152
|
this.#rooms[newRoomId] = {
|
|
154
153
|
participants: [ws.clientId],
|
|
155
154
|
maxSize: data.size || null,
|
|
156
|
-
storage: data.storage || {}
|
|
157
|
-
storageTimestamps: {},
|
|
155
|
+
storage: data.storage || {}
|
|
158
156
|
};
|
|
159
157
|
|
|
160
158
|
this.#clientRooms.set(ws.clientId, newRoomId);
|
|
@@ -186,7 +184,6 @@ function requireServer () {
|
|
|
186
184
|
ws.send(JSON.stringify({
|
|
187
185
|
type: 'join_accepted',
|
|
188
186
|
storage: room.storage,
|
|
189
|
-
storageTimestamps: room.storageTimestamps,
|
|
190
187
|
participantCount: room.participants.length,
|
|
191
188
|
host: room.participants[0]
|
|
192
189
|
}));
|
|
@@ -210,11 +207,9 @@ function requireServer () {
|
|
|
210
207
|
const updateRoomId = this.#clientRooms.get(ws.clientId);
|
|
211
208
|
const updateRoom = updateRoomId ? this.#rooms[updateRoomId] : null;
|
|
212
209
|
if (updateRoom && data.key) {
|
|
213
|
-
|
|
214
|
-
if (data.timestamp > existingTimestamp && JSON.stringify(updateRoom.storage[data.key]) !== JSON.stringify(data.value)) {
|
|
210
|
+
if (JSON.stringify(updateRoom.storage[data.key]) !== JSON.stringify(data.value)) {
|
|
215
211
|
updateRoom.storage[data.key] = data.value;
|
|
216
|
-
updateRoom
|
|
217
|
-
this.#syncRoomStorageKey(updateRoom, data.key, data.timestamp);
|
|
212
|
+
this.#syncRoomStorageKey(updateRoom, data.key, ws.clientId);
|
|
218
213
|
}
|
|
219
214
|
}
|
|
220
215
|
break;
|
|
@@ -223,12 +218,10 @@ function requireServer () {
|
|
|
223
218
|
const arrayRoomId = this.#clientRooms.get(ws.clientId);
|
|
224
219
|
const arrayRoom = arrayRoomId ? this.#rooms[arrayRoomId] : null;
|
|
225
220
|
if (arrayRoom && data.key) {
|
|
226
|
-
// No timestamp check for array operations as they are designed to work unordered
|
|
227
221
|
const updatedArray = this.#arrayUpdate(arrayRoom.storage, data.key, data.operation, data.value, data.updateValue);
|
|
228
222
|
if (JSON.stringify(arrayRoom.storage[data.key]) !== JSON.stringify(updatedArray)) {
|
|
229
223
|
arrayRoom.storage[data.key] = updatedArray;
|
|
230
|
-
arrayRoom
|
|
231
|
-
this.#syncRoomStorageKey(arrayRoom, data.key, Date.now());
|
|
224
|
+
this.#syncRoomStorageKey(arrayRoom, data.key);
|
|
232
225
|
}
|
|
233
226
|
}
|
|
234
227
|
break;
|
|
@@ -286,17 +279,17 @@ function requireServer () {
|
|
|
286
279
|
* @private
|
|
287
280
|
* @param {Object} room
|
|
288
281
|
* @param {string} key
|
|
289
|
-
* @param {
|
|
282
|
+
* @param {string} exclude
|
|
290
283
|
*/
|
|
291
|
-
#syncRoomStorageKey(room, key,
|
|
284
|
+
#syncRoomStorageKey(room, key, exclude) {
|
|
292
285
|
room?.participants?.forEach(p => {
|
|
286
|
+
if (p === exclude) return;
|
|
293
287
|
const client = this.#clients.get(p);
|
|
294
288
|
if (client) {
|
|
295
289
|
client.send(JSON.stringify({
|
|
296
290
|
type: 'storage_sync',
|
|
297
291
|
key,
|
|
298
|
-
value: room?.storage?.[key]
|
|
299
|
-
timestamp
|
|
292
|
+
value: room?.storage?.[key]
|
|
300
293
|
}));
|
|
301
294
|
}
|
|
302
295
|
});
|