playsocketjs 2.2.2 → 2.4.0

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/README.md CHANGED
@@ -219,9 +219,11 @@ Creates a new PlaySocket Server instance with configuration options.
219
219
  - `clientRegistrationRequested`: Client requests to register (returns the client's ID `string`, customData `object`) – return `false` or a rejection reason `string` to block the registration
220
220
  - `clientDisconnected`: Client disconnected from the server (returns the client's ID `string`)
221
221
  - `clientJoinedRoom`: Client joined a room – note that clients can only leave by disconnecting (returns the client's ID `string`, room ID `string`)
222
+ - `clientJoinRequested`: Client requests to join a room (returns the client's ID `string`, room ID `string`) – return `false` or a rejection reason `string` to block them from joining
222
223
  - `roomCreated`: Client created a room (returns room ID `string`)
223
224
  - `roomDestroyed`: Room was destroyed, this happens when all participants leave (returns room ID `string`)
224
225
  - `roomCreationRequested`: Room creation requested by client (returns `object` containing the client's ID `string`, room ID `string` and the initialStorage `object`) – if you return an `object` in the callback, it will take that as the initial storage instead. If you return `false`, the creation will be denied
226
+ - `storageUpdated`: Room storage property updated (returns `object` containing the ID of the client who requested the update `string`, room ID `string`, the update `object`, and the storage `object`)
225
227
  - `storageUpdateRequested`: Room storage property update requested by client (returns `object` containing the client's ID `string`, room ID `string` and the update `object`) – if you return `false` in the callback, the update will be blocked
226
228
  - `requestReceived`: Request from client was received by the server (returns `object` containing client's ID `string`, if in room – room ID `string`, request name `string` and optional passed data of type `any`)
227
229
 
@@ -2505,6 +2505,7 @@ class PlaySocket {
2505
2505
  * @param {*} updateValue - New value for update-matching
2506
2506
  */
2507
2507
  updateStorage(key, type, value, updateValue) {
2508
+ if (!this.#inRoom) return this.#triggerEvent("error", "Cannot update storage when not in a room.");
2508
2509
  if (this.#debug) console.log(LOG_PREFIX + `Property update for key ${key}, operation ${type}, value ${value} and updateValue ${updateValue}.`);
2509
2510
  const propUpdate = this.#crdtManager.updateProperty(key, type, value, updateValue);
2510
2511
  this.#sendToServer({
@@ -2351,7 +2351,7 @@ function requireServer () {
2351
2351
  if (data.sessionToken !== this.#clientTokens.get(data.id)) {
2352
2352
  ws.send(encode({
2353
2353
  type: 'reconnection_failed',
2354
- reason: "Session token does not match"
2354
+ reason: "Session token does not match."
2355
2355
  }), { binary: true });
2356
2356
  return;
2357
2357
  }
@@ -2378,7 +2378,7 @@ function requireServer () {
2378
2378
 
2379
2379
  ws.send(encode({ type: 'reconnected', roomData }), { binary: true });
2380
2380
  } else {
2381
- ws.send(encode({ type: 'reconnection_failed', reason: "Client unknown to server" }), { binary: true });
2381
+ ws.send(encode({ type: 'reconnection_failed', reason: "Client unknown to server." }), { binary: true });
2382
2382
  }
2383
2383
  break;
2384
2384
 
@@ -2389,7 +2389,7 @@ function requireServer () {
2389
2389
  if (this.#clientRooms.get(ws.clientId) || this.#rooms[newRoomId]) {
2390
2390
  ws.send(encode({
2391
2391
  type: 'room_creation_failed',
2392
- reason: this.#clientRooms.get(ws.clientId) ? 'Already in a room' : 'Room ID is taken'
2392
+ reason: this.#clientRooms.get(ws.clientId) ? 'Already in a room.' : 'Room ID is taken.'
2393
2393
  }), { binary: true });
2394
2394
  return;
2395
2395
  }
@@ -2440,17 +2440,17 @@ function requireServer () {
2440
2440
  const roomId = data.roomId;
2441
2441
  const room = this.#rooms[roomId];
2442
2442
 
2443
- if (!room ||
2444
- (room.participants.length >= room.maxSize) ||
2445
- this.#clientRooms.get(ws.clientId)) {
2446
- ws.send(encode({
2447
- type: 'join_rejected',
2448
- reason: !room ? 'Room not found' :
2449
- room.participants.length >= room.maxSize ? 'Room full' :
2450
- 'Already in a room'
2451
- }), { binary: true });
2452
- return;
2453
- }
2443
+ const rejectJoin = (reason) => {
2444
+ ws.send(encode({ type: 'join_rejected', reason }), { binary: true });
2445
+ };
2446
+
2447
+ // Event callback
2448
+ const joinAllowed = await this.#triggerEvent("clientJoinRequested", ws.clientId, roomId);
2449
+ if (joinAllowed === false || typeof joinAllowed === 'string') return rejectJoin(typeof joinAllowed === 'string' ? joinAllowed : 'Denied.');
2450
+
2451
+ if (!room) return rejectJoin("Room not found.");
2452
+ if (this.#clientRooms.get(ws.clientId)) return rejectJoin("Already in a room.");
2453
+ if (room.participants.length >= room.maxSize) return rejectJoin("Room full.");
2454
2454
 
2455
2455
  room.participants.push(ws.clientId);
2456
2456
  this.#clientRooms.set(ws.clientId, roomId);
@@ -2500,7 +2500,6 @@ function requireServer () {
2500
2500
  // Increment version for this room
2501
2501
  const currentVersion = this.#roomVersions.get(updateRoomId) + 1;
2502
2502
  this.#roomVersions.set(updateRoomId, currentVersion);
2503
- if (this.#debug) console.log("Property update received and imported:", data.update);
2504
2503
 
2505
2504
  updateRoom.participants?.forEach(p => {
2506
2505
  const client = this.#clients.get(p);
@@ -2512,6 +2511,9 @@ function requireServer () {
2512
2511
  }), { binary: true });
2513
2512
  }
2514
2513
  });
2514
+
2515
+ this.#triggerEvent("storageUpdated", { roomId: updateRoomId, clientId: ws.clientId, update: structuredClone(data.update), storage: this.getRoomStorage(updateRoomId) });
2516
+ if (this.#debug) console.log("Property update received and imported:", data.update);
2515
2517
  }
2516
2518
  break;
2517
2519
 
@@ -2660,7 +2662,7 @@ function requireServer () {
2660
2662
  * @param {Function} callback - Callback function
2661
2663
  */
2662
2664
  onEvent(event, callback) {
2663
- const validEvents = ["clientRegistered", "clientRegistrationRequested", "clientDisconnected", "clientJoinedRoom", "roomCreationRequested", "requestReceived", "roomCreated", "storageUpdateRequested", "roomDestroyed"];
2665
+ const validEvents = ["clientRegistered", "clientRegistrationRequested", "clientDisconnected", "clientJoinedRoom", "clientJoinRequested", "roomCreated", "roomCreationRequested", "requestReceived", "storageUpdated", "storageUpdateRequested", "roomDestroyed"];
2664
2666
  if (!validEvents.includes(event)) return console.warn(`Invalid PlaySocket event type "${event}"`);
2665
2667
  if (!this.#callbacks.has(event)) this.#callbacks.set(event, []);
2666
2668
  this.#callbacks.get(event).push(callback);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playsocketjs",
3
- "version": "2.2.2",
3
+ "version": "2.4.0",
4
4
  "description": "WebSocket wrapper for creating simple multiplayer systems with ease.",
5
5
  "module": "dist/playsocket-client.js",
6
6
  "exports": {