playsocketjs 1.0.6 → 1.0.7
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 +29 -5
- package/dist/playsocket-server.js +15 -7
- package/package.json +1 -1
|
@@ -16,10 +16,12 @@ class PlaySocket {
|
|
|
16
16
|
|
|
17
17
|
// Room properties
|
|
18
18
|
#storage = {}; // Shared storage object
|
|
19
|
+
#storageTimestamps = {}; // Tracks update timestamps per key
|
|
19
20
|
#isHost = false; // Whether this client is host
|
|
20
21
|
#roomHost;
|
|
21
22
|
#roomId; // ID of the host (client only)
|
|
22
23
|
#connectionCount = 0;
|
|
24
|
+
#serverTimeOffset = 0; // Offset between server time and local time
|
|
23
25
|
|
|
24
26
|
// Event handling
|
|
25
27
|
#callbacks = new Map(); // Event callbacks
|
|
@@ -55,6 +57,14 @@ class PlaySocket {
|
|
|
55
57
|
);
|
|
56
58
|
}
|
|
57
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Get synchronized timestamp
|
|
62
|
+
* @private
|
|
63
|
+
*/
|
|
64
|
+
#getTimestamp() {
|
|
65
|
+
return Date.now() + this.#serverTimeOffset;
|
|
66
|
+
}
|
|
67
|
+
|
|
58
68
|
/**
|
|
59
69
|
* Register an event callback
|
|
60
70
|
* @param {string} event - Event name
|
|
@@ -119,7 +129,8 @@ class PlaySocket {
|
|
|
119
129
|
this.#sendToServer({
|
|
120
130
|
type: 'register',
|
|
121
131
|
id: this.#id,
|
|
122
|
-
customData: this.#customData || undefined
|
|
132
|
+
customData: this.#customData || undefined,
|
|
133
|
+
clientTime: Date.now()
|
|
123
134
|
});
|
|
124
135
|
};
|
|
125
136
|
});
|
|
@@ -140,6 +151,7 @@ class PlaySocket {
|
|
|
140
151
|
// Connected to room
|
|
141
152
|
if (this.#pendingJoin) {
|
|
142
153
|
this.#storage = message.storage;
|
|
154
|
+
this.#storageTimestamps = message.storageTimestamps;
|
|
143
155
|
this.#connectionCount = message.participantCount - 1;
|
|
144
156
|
this.#triggerEvent("status", `Connected to room.`);
|
|
145
157
|
this.#triggerEvent("storageUpdated", { ...this.#storage });
|
|
@@ -184,6 +196,9 @@ class PlaySocket {
|
|
|
184
196
|
|
|
185
197
|
case 'registered':
|
|
186
198
|
if (this.#pendingInit) {
|
|
199
|
+
const roundTripTime = Date.now() - message.clientTime;
|
|
200
|
+
const serverTimeAtClientNow = message.serverTime + (roundTripTime / 2);
|
|
201
|
+
this.#serverTimeOffset = serverTimeAtClientNow - Date.now();
|
|
187
202
|
this.#pendingInit.resolve();
|
|
188
203
|
this.#triggerEvent("status", "Connected to server.");
|
|
189
204
|
this.#pendingInit = null;
|
|
@@ -191,9 +206,13 @@ class PlaySocket {
|
|
|
191
206
|
break;
|
|
192
207
|
|
|
193
208
|
case 'storage_sync':
|
|
194
|
-
if (message.key
|
|
195
|
-
this.#
|
|
196
|
-
|
|
209
|
+
if (message.key) {
|
|
210
|
+
const localTimestamp = this.#storageTimestamps[message.key] || 0;
|
|
211
|
+
if (message.timestamp > localTimestamp && JSON.stringify(this.#storage[message.key]) !== JSON.stringify(message.value)) {
|
|
212
|
+
this.#storage[message.key] = message.value;
|
|
213
|
+
this.#storageTimestamps[message.key] = message.timestamp;
|
|
214
|
+
this.#triggerEvent("storageUpdated", { ...this.#storage });
|
|
215
|
+
}
|
|
197
216
|
}
|
|
198
217
|
break;
|
|
199
218
|
|
|
@@ -333,12 +352,15 @@ class PlaySocket {
|
|
|
333
352
|
*/
|
|
334
353
|
updateStorage(key, value) {
|
|
335
354
|
if (JSON.stringify(this.#storage[key]) === JSON.stringify(value)) return; // Prevent updates without changes
|
|
355
|
+
const timestamp = this.#getTimestamp();
|
|
336
356
|
this.#sendToServer({
|
|
337
357
|
type: 'room_storage_update',
|
|
338
358
|
key,
|
|
339
|
-
value
|
|
359
|
+
value,
|
|
360
|
+
timestamp
|
|
340
361
|
});
|
|
341
362
|
this.#storage[key] = value;
|
|
363
|
+
this.#storageTimestamps[key] = timestamp;
|
|
342
364
|
this.#triggerEvent("storageUpdated", { ...this.#storage });
|
|
343
365
|
}
|
|
344
366
|
|
|
@@ -360,6 +382,7 @@ class PlaySocket {
|
|
|
360
382
|
updateValue
|
|
361
383
|
});
|
|
362
384
|
this.#storage[key] = updatedArray;
|
|
385
|
+
this.#storageTimestamps[key] = this.#getTimestamp();
|
|
363
386
|
this.#triggerEvent("storageUpdated", { ...this.#storage });
|
|
364
387
|
}
|
|
365
388
|
|
|
@@ -416,6 +439,7 @@ class PlaySocket {
|
|
|
416
439
|
this.#isHost = false;
|
|
417
440
|
this.#roomHost = null;
|
|
418
441
|
this.#storage = {};
|
|
442
|
+
this.#storageTimestamps = {};
|
|
419
443
|
this.#roomId = null;
|
|
420
444
|
this.#connectionCount = 0;
|
|
421
445
|
clearTimeout(this.#reconnectTimeout);
|
|
@@ -98,7 +98,7 @@ function requireServer () {
|
|
|
98
98
|
}
|
|
99
99
|
ws.clientId = data.id; // Adds the provided id to the ws object as clientId
|
|
100
100
|
this.#clients.set(data.id, ws);
|
|
101
|
-
ws.send(JSON.stringify({ type: 'registered' }));
|
|
101
|
+
ws.send(JSON.stringify({ type: 'registered', serverTime: Date.now(), clientTime: data.clientTime }));
|
|
102
102
|
this.#triggerEvent("clientRegistered", data.id, data.customData);
|
|
103
103
|
break;
|
|
104
104
|
|
|
@@ -117,6 +117,7 @@ function requireServer () {
|
|
|
117
117
|
participants: [ws.clientId],
|
|
118
118
|
maxSize: data.size || null,
|
|
119
119
|
storage: data.storage || {},
|
|
120
|
+
storageTimestamps: {},
|
|
120
121
|
};
|
|
121
122
|
|
|
122
123
|
this.#clientRooms.set(ws.clientId, newRoomId);
|
|
@@ -148,6 +149,7 @@ function requireServer () {
|
|
|
148
149
|
ws.send(JSON.stringify({
|
|
149
150
|
type: 'connection_accepted',
|
|
150
151
|
storage: room.storage,
|
|
152
|
+
storageTimestamps: room.storageTimestamps,
|
|
151
153
|
participantCount: room.participants.length
|
|
152
154
|
}));
|
|
153
155
|
|
|
@@ -169,9 +171,13 @@ function requireServer () {
|
|
|
169
171
|
case 'room_storage_update':
|
|
170
172
|
const updateRoomId = this.#clientRooms.get(ws.clientId);
|
|
171
173
|
const updateRoom = updateRoomId ? this.#rooms[updateRoomId] : null;
|
|
172
|
-
if (updateRoom && data.key
|
|
173
|
-
updateRoom.
|
|
174
|
-
|
|
174
|
+
if (updateRoom && data.key) {
|
|
175
|
+
const existingTimestamp = updateRoom.storageTimestamps[data.key] || 0;
|
|
176
|
+
if (data.timestamp > existingTimestamp && JSON.stringify(updateRoom.storage[data.key]) !== JSON.stringify(data.value)) {
|
|
177
|
+
updateRoom.storage[data.key] = data.value;
|
|
178
|
+
updateRoom.storageTimestamps[data.key] = data.timestamp;
|
|
179
|
+
this.#syncRoomStorageKey(updateRoomId, data.key, data.timestamp);
|
|
180
|
+
}
|
|
175
181
|
}
|
|
176
182
|
break;
|
|
177
183
|
|
|
@@ -182,7 +188,8 @@ function requireServer () {
|
|
|
182
188
|
const updatedArray = this.#arrayUpdate(arrayRoom.storage, data.key, data.operation, data.value, data.updateValue);
|
|
183
189
|
if (JSON.stringify(arrayRoom.storage[data.key]) !== JSON.stringify(updatedArray)) {
|
|
184
190
|
arrayRoom.storage[data.key] = updatedArray;
|
|
185
|
-
|
|
191
|
+
arrayRoom.storageTimestamps[data.key] = Date.now(); // New date to ensure that they are applied regardless of age (they don't overwrite – they transform)
|
|
192
|
+
this.#syncRoomStorageKey(arrayRoomId, data.key, Date.now());
|
|
186
193
|
}
|
|
187
194
|
}
|
|
188
195
|
break;
|
|
@@ -224,7 +231,7 @@ function requireServer () {
|
|
|
224
231
|
* Sync storage key to all clients in room
|
|
225
232
|
* @private
|
|
226
233
|
*/
|
|
227
|
-
#syncRoomStorageKey(roomId, key) {
|
|
234
|
+
#syncRoomStorageKey(roomId, key, timestamp) {
|
|
228
235
|
const room = this.#rooms[roomId];
|
|
229
236
|
if (!room) return;
|
|
230
237
|
room.participants.forEach(p => {
|
|
@@ -233,7 +240,8 @@ function requireServer () {
|
|
|
233
240
|
client.send(JSON.stringify({
|
|
234
241
|
type: 'storage_sync',
|
|
235
242
|
key,
|
|
236
|
-
value: room.storage[key]
|
|
243
|
+
value: room.storage[key],
|
|
244
|
+
timestamp
|
|
237
245
|
}));
|
|
238
246
|
}
|
|
239
247
|
});
|