@mml-io/3d-web-user-networking 0.26.0 → 0.27.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/build/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  // src/UserNetworkingServer.ts
2
- import { encodeError, DeltaNetV01ServerErrors } from "@mml-io/delta-net-protocol";
2
+ import { encodeError, DeltaNetServerErrors } from "@mml-io/delta-net-protocol";
3
3
  import {
4
4
  DeltaNetServer,
5
- DeltaNetServerError as DeltaNetServerError2
5
+ DeltaNetServerError
6
6
  } from "@mml-io/delta-net-server";
7
7
 
8
8
  // src/DeltaNetComponentMapping.ts
@@ -11,13 +11,13 @@ var COMPONENT_POSITION_X = 1;
11
11
  var COMPONENT_POSITION_Y = 2;
12
12
  var COMPONENT_POSITION_Z = 3;
13
13
  var COMPONENT_ROTATION_Y = 4;
14
- var COMPONENT_ROTATION_W = 5;
15
- var COMPONENT_STATE = 6;
14
+ var COMPONENT_STATE = 5;
16
15
  var STATE_INTERNAL_CONNECTION_ID = 0;
17
16
  var STATE_CHARACTER_DESCRIPTION = 1;
18
17
  var STATE_USERNAME = 2;
19
18
  var STATE_COLORS = 3;
20
- var rotationMultiplier = 360;
19
+ var STATE_USER_ID = 4;
20
+ var rotationMultiplier = 1e4;
21
21
  var positionMultiplier = 100;
22
22
  var textDecoder = new TextDecoder();
23
23
  var DeltaNetComponentMapping = class _DeltaNetComponentMapping {
@@ -40,11 +40,7 @@ var DeltaNetComponentMapping = class _DeltaNetComponentMapping {
40
40
  );
41
41
  components.set(
42
42
  COMPONENT_ROTATION_Y,
43
- BigInt(Math.round(update.rotation.quaternionY * rotationMultiplier))
44
- );
45
- components.set(
46
- COMPONENT_ROTATION_W,
47
- BigInt(Math.round(update.rotation.quaternionW * rotationMultiplier))
43
+ BigInt(Math.round(update.rotation.eulerY * rotationMultiplier))
48
44
  );
49
45
  components.set(COMPONENT_STATE, BigInt(update.state));
50
46
  return components;
@@ -56,12 +52,11 @@ var DeltaNetComponentMapping = class _DeltaNetComponentMapping {
56
52
  const positionX = Number(components.get(COMPONENT_POSITION_X) || BigInt(0)) / positionMultiplier;
57
53
  const positionY = Number(components.get(COMPONENT_POSITION_Y) || BigInt(0)) / positionMultiplier;
58
54
  const positionZ = Number(components.get(COMPONENT_POSITION_Z) || BigInt(0)) / positionMultiplier;
59
- const rotationY = Number(components.get(COMPONENT_ROTATION_Y) || BigInt(0)) / rotationMultiplier;
60
- const rotationW = Number(components.get(COMPONENT_ROTATION_W) || BigInt(0)) / rotationMultiplier;
55
+ const eulerY = Number(components.get(COMPONENT_ROTATION_Y) || BigInt(0)) / rotationMultiplier;
61
56
  const state = Number(components.get(COMPONENT_STATE) || BigInt(0));
62
57
  return {
63
58
  position: { x: positionX, y: positionY, z: positionZ },
64
- rotation: { quaternionY: rotationY, quaternionW: rotationW },
59
+ rotation: { eulerY },
65
60
  state
66
61
  };
67
62
  }
@@ -71,6 +66,9 @@ var DeltaNetComponentMapping = class _DeltaNetComponentMapping {
71
66
  static toStates(userIdentity) {
72
67
  const states = /* @__PURE__ */ new Map();
73
68
  const textEncoder = new TextEncoder();
69
+ if (userIdentity.userId !== void 0 && userIdentity.userId !== null) {
70
+ states.set(STATE_USER_ID, textEncoder.encode(userIdentity.userId));
71
+ }
74
72
  if (userIdentity.username) {
75
73
  states.set(STATE_USERNAME, textEncoder.encode(userIdentity.username));
76
74
  }
@@ -85,6 +83,15 @@ var DeltaNetComponentMapping = class _DeltaNetComponentMapping {
85
83
  }
86
84
  return states;
87
85
  }
86
+ /**
87
+ * Decode persistent userId from binary state
88
+ */
89
+ static persistentUserIdFromBytes(bytes) {
90
+ if (bytes.length === 0) {
91
+ return null;
92
+ }
93
+ return textDecoder.decode(bytes);
94
+ }
88
95
  /**
89
96
  * Encode username to binary state
90
97
  */
@@ -136,6 +143,11 @@ var DeltaNetComponentMapping = class _DeltaNetComponentMapping {
136
143
  states.set(stateId, _DeltaNetComponentMapping.encodeColors(value));
137
144
  }
138
145
  break;
146
+ case STATE_USER_ID:
147
+ if (typeof value === "string") {
148
+ states.set(stateId, textEncoder.encode(value));
149
+ }
150
+ break;
139
151
  }
140
152
  return states;
141
153
  }
@@ -171,13 +183,15 @@ var DeltaNetComponentMapping = class _DeltaNetComponentMapping {
171
183
  }
172
184
  }
173
185
  static fromUserStates(states, logger) {
186
+ const userIdBytes = states.get(STATE_USER_ID);
187
+ const userId = userIdBytes ? _DeltaNetComponentMapping.persistentUserIdFromBytes(userIdBytes) ?? "" : "";
174
188
  const usernameBytes = states.get(STATE_USERNAME);
175
189
  const username = usernameBytes ? _DeltaNetComponentMapping.usernameFromBytes(usernameBytes) : null;
176
190
  const characterDescBytes = states.get(STATE_CHARACTER_DESCRIPTION);
177
191
  const characterDescription = characterDescBytes ? _DeltaNetComponentMapping.characterDescriptionFromBytes(characterDescBytes) : null;
178
192
  const colorsBytes = states.get(STATE_COLORS);
179
- const colorsArray = colorsBytes ? _DeltaNetComponentMapping.decodeColors(colorsBytes, logger) : [];
180
- return { username, characterDescription, colors: colorsArray };
193
+ const colorsArray = colorsBytes ? _DeltaNetComponentMapping.decodeColors(colorsBytes, logger) : null;
194
+ return { userId, username, characterDescription, colors: colorsArray };
181
195
  }
182
196
  static userIdFromBytes(bytes) {
183
197
  if (bytes.length === 0) {
@@ -196,486 +210,24 @@ var DeltaNetComponentMapping = class _DeltaNetComponentMapping {
196
210
  if (bytes.length === 0) {
197
211
  return null;
198
212
  }
199
- return JSON.parse(textDecoder.decode(bytes));
213
+ try {
214
+ return JSON.parse(textDecoder.decode(bytes));
215
+ } catch {
216
+ return null;
217
+ }
200
218
  }
201
219
  /**
202
220
  * Decode binary states back to username and character description
203
221
  */
204
222
  static fromStates(states, logger) {
205
- const userIdBytes = states.get(STATE_INTERNAL_CONNECTION_ID);
206
- let userId = null;
207
- if (userIdBytes) {
208
- const reader = new BufferReader(userIdBytes);
209
- userId = reader.readUVarint(false);
223
+ const connectionIdBytes = states.get(STATE_INTERNAL_CONNECTION_ID);
224
+ let connectionId = null;
225
+ if (connectionIdBytes) {
226
+ const reader = new BufferReader(connectionIdBytes);
227
+ connectionId = reader.readUVarint(false);
210
228
  }
211
229
  const userStates = _DeltaNetComponentMapping.fromUserStates(states, logger);
212
- return { userId, ...userStates };
213
- }
214
- };
215
-
216
- // src/UserNetworkingMessages.ts
217
- import { DeltaNetServerError } from "@mml-io/delta-net-server";
218
- var UserNetworkingServerError = class extends DeltaNetServerError {
219
- };
220
- var SERVER_BROADCAST_MESSAGE_TYPE = 1;
221
- var FROM_CLIENT_CHAT_MESSAGE_TYPE = 2;
222
- var FROM_SERVER_CHAT_MESSAGE_TYPE = 3;
223
- function parseClientChatMessage(contents) {
224
- try {
225
- const parsed = JSON.parse(contents);
226
- if (typeof parsed === "object" && parsed !== null && "message" in parsed && typeof parsed.message === "string") {
227
- return {
228
- message: parsed.message
229
- };
230
- } else {
231
- throw new Error("Invalid chat message");
232
- }
233
- } catch (error) {
234
- return new Error(`Invalid chat message: ${error}`);
235
- }
236
- }
237
- function parseServerChatMessage(contents) {
238
- try {
239
- const parsed = JSON.parse(contents);
240
- if (typeof parsed === "object" && parsed !== null && "fromUserId" in parsed && typeof parsed.fromUserId === "number" && "message" in parsed && typeof parsed.message === "string") {
241
- return {
242
- fromUserId: parsed.fromUserId,
243
- message: parsed.message
244
- };
245
- } else {
246
- throw new Error("Invalid server chat message");
247
- }
248
- } catch (error) {
249
- return new Error(`Invalid server chat message: ${error}`);
250
- }
251
- }
252
- function parseServerBroadcastMessage(contents) {
253
- try {
254
- const parsed = JSON.parse(contents);
255
- if (typeof parsed === "object" && parsed !== null && "broadcastType" in parsed && typeof parsed.broadcastType === "string" && "payload" in parsed && typeof parsed.payload === "object") {
256
- return {
257
- broadcastType: parsed.broadcastType,
258
- payload: parsed.payload
259
- };
260
- } else {
261
- throw new Error("Invalid server broadcast message");
262
- }
263
- } catch (error) {
264
- return new Error(`Invalid server broadcast message: ${error}`);
265
- }
266
- }
267
-
268
- // src/legacy/LegacyUserNetworkingCodec.ts
269
- var LegacyUserNetworkingCodec = class {
270
- static encodeUpdate(update) {
271
- const buffer = new ArrayBuffer(19);
272
- const dataView = new DataView(buffer);
273
- dataView.setUint16(0, update.id);
274
- dataView.setFloat32(2, update.position.x);
275
- dataView.setFloat32(6, update.position.y);
276
- dataView.setFloat32(10, update.position.z);
277
- dataView.setInt16(14, update.rotation.quaternionY * 32767);
278
- dataView.setInt16(16, update.rotation.quaternionW * 32767);
279
- dataView.setUint8(18, update.state);
280
- return new Uint8Array(buffer);
281
- }
282
- static decodeUpdate(buffer) {
283
- const dataView = new DataView(buffer);
284
- const id = dataView.getUint16(0);
285
- const x = dataView.getFloat32(2);
286
- const y = dataView.getFloat32(6);
287
- const z = dataView.getFloat32(10);
288
- const quaternionY = dataView.getInt16(14) / 32767;
289
- const quaternionW = dataView.getInt16(16) / 32767;
290
- const state = dataView.getUint8(18);
291
- const position = { x, y, z };
292
- const rotation = { quaternionY, quaternionW };
293
- return { id, position, rotation, state };
294
- }
295
- };
296
-
297
- // src/legacy/LegacyUserNetworkingMessages.ts
298
- var LEGACY_USER_NETWORKING_DISCONNECTED_MESSAGE_TYPE = "disconnected";
299
- var LEGACY_USER_NETWORKING_IDENTITY_MESSAGE_TYPE = "identity";
300
- var LEGACY_USER_NETWORKING_USER_AUTHENTICATE_MESSAGE_TYPE = "user_auth";
301
- var LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE = "user_profile";
302
- var LEGACY_USER_NETWORKING_USER_UPDATE_MESSAGE_TYPE = "user_update";
303
- var LEGACY_USER_NETWORKING_SERVER_BROADCAST_MESSAGE_TYPE = "broadcast";
304
- var LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE = "error";
305
- var LEGACY_USER_NETWORKING_PING_MESSAGE_TYPE = "ping";
306
- var LEGACY_USER_NETWORKING_PONG_MESSAGE_TYPE = "pong";
307
- var LEGACY_USER_NETWORKING_CONNECTION_LIMIT_REACHED_ERROR_TYPE = "CONNECTION_LIMIT_REACHED";
308
- var LEGACY_USER_NETWORKING_AUTHENTICATION_FAILED_ERROR_TYPE = "AUTHENTICATION_FAILED";
309
- var LEGACY_USER_NETWORKING_SERVER_SHUTDOWN_ERROR_TYPE = "SERVER_SHUTDOWN";
310
- var LEGACY_USER_NETWORKING_UNKNOWN_ERROR = "UNKNOWN_ERROR";
311
-
312
- // src/legacy/LegacyAdapter.ts
313
- function toArrayBuffer(buffer) {
314
- const arrayBuffer = new ArrayBuffer(buffer.length);
315
- const view = new Uint8Array(arrayBuffer);
316
- for (let i = 0; i < buffer.length; ++i) {
317
- view[i] = buffer[i];
318
- }
319
- return arrayBuffer;
320
- }
321
- var WebSocketOpenStatus = 1;
322
- var LegacyAdapter = class {
323
- constructor(userNetworkingServer, deltaNetServer, logger) {
324
- this.userNetworkingServer = userNetworkingServer;
325
- this.deltaNetServer = deltaNetServer;
326
- this.logger = logger;
327
- }
328
- allClientsById = /* @__PURE__ */ new Map();
329
- legacyAuthenticatedClientsById = /* @__PURE__ */ new Map();
330
- broadcastMessage(broadcastType, broadcastPayload) {
331
- if (broadcastType !== SERVER_BROADCAST_MESSAGE_TYPE) {
332
- return;
333
- }
334
- const parsedPayload = parseServerBroadcastMessage(broadcastPayload);
335
- if (parsedPayload instanceof Error) {
336
- this.logger.error("Error parsing server broadcast message", parsedPayload);
337
- return;
338
- }
339
- const { broadcastType: broadcastTypeString, payload } = parsedPayload;
340
- const message = {
341
- type: "broadcast",
342
- broadcastType: broadcastTypeString,
343
- payload
344
- };
345
- const messageString = JSON.stringify(message);
346
- for (const [, client] of this.legacyAuthenticatedClientsById) {
347
- if (client.socket.readyState === WebSocketOpenStatus) {
348
- client.socket.send(messageString);
349
- }
350
- }
351
- }
352
- addWebSocket(socket) {
353
- const id = this.userNetworkingServer.getLegacyClientId();
354
- const client = {
355
- id,
356
- lastPong: Date.now(),
357
- socket,
358
- authenticatedUser: null,
359
- update: {
360
- id,
361
- position: { x: 0, y: 0, z: 0 },
362
- rotation: { quaternionY: 0, quaternionW: 1 },
363
- state: 0
364
- }
365
- };
366
- this.allClientsById.set(id, client);
367
- socket.addEventListener("message", (message) => {
368
- try {
369
- if (message.data instanceof ArrayBuffer || message.data instanceof Buffer) {
370
- if (client.authenticatedUser) {
371
- const arrayBuffer = message.data instanceof ArrayBuffer ? message.data : toArrayBuffer(message.data);
372
- const update = LegacyUserNetworkingCodec.decodeUpdate(arrayBuffer);
373
- update.id = id;
374
- const index = this.deltaNetServer.dangerouslyGetConnectionsToComponentIndex().get(id);
375
- client.update = update;
376
- if (index !== void 0) {
377
- this.deltaNetServer.setComponentValue(
378
- COMPONENT_POSITION_X,
379
- index,
380
- BigInt(Math.round(update.position.x * positionMultiplier))
381
- );
382
- this.deltaNetServer.setComponentValue(
383
- COMPONENT_POSITION_Y,
384
- index,
385
- BigInt(Math.round(update.position.y * positionMultiplier))
386
- );
387
- this.deltaNetServer.setComponentValue(
388
- COMPONENT_POSITION_Z,
389
- index,
390
- BigInt(Math.round(update.position.z * positionMultiplier))
391
- );
392
- this.deltaNetServer.setComponentValue(
393
- COMPONENT_ROTATION_Y,
394
- index,
395
- BigInt(Math.round(update.rotation.quaternionY * rotationMultiplier))
396
- );
397
- this.deltaNetServer.setComponentValue(
398
- COMPONENT_ROTATION_W,
399
- index,
400
- BigInt(Math.round(update.rotation.quaternionW * rotationMultiplier))
401
- );
402
- this.deltaNetServer.setComponentValue(
403
- COMPONENT_STATE,
404
- index,
405
- BigInt(Math.round(update.state))
406
- );
407
- }
408
- }
409
- } else {
410
- let parsed;
411
- try {
412
- parsed = JSON.parse(message.data);
413
- } catch (e) {
414
- this.logger.error("Error parsing JSON message", message, e);
415
- return;
416
- }
417
- if (!client.authenticatedUser) {
418
- if (parsed.type === LEGACY_USER_NETWORKING_USER_AUTHENTICATE_MESSAGE_TYPE) {
419
- this.handleUserAuth(client, parsed).then((authResult) => {
420
- if (client.socket.readyState !== WebSocketOpenStatus) {
421
- return;
422
- }
423
- if (!authResult) {
424
- this.logger.error(`Client-id ${client.id} user_auth failed`, authResult);
425
- const serverError = JSON.stringify({
426
- type: LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE,
427
- errorType: LEGACY_USER_NETWORKING_AUTHENTICATION_FAILED_ERROR_TYPE,
428
- message: "Authentication failed"
429
- });
430
- socket.send(serverError);
431
- socket.close();
432
- } else {
433
- if (!this.userNetworkingServer.hasCapacityForLegacyClient()) {
434
- const serverError = JSON.stringify({
435
- type: LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE,
436
- errorType: LEGACY_USER_NETWORKING_CONNECTION_LIMIT_REACHED_ERROR_TYPE,
437
- message: "Connection limit reached"
438
- });
439
- socket.send(serverError);
440
- socket.close();
441
- return;
442
- }
443
- const userData = authResult;
444
- this.deltaNetServer.dangerouslyAddNewJoinerCallback((index) => {
445
- if (client.socket.readyState !== WebSocketOpenStatus) {
446
- return null;
447
- }
448
- client.authenticatedUser = userData;
449
- this.deltaNetServer.setComponentValue(COMPONENT_POSITION_X, index, BigInt(0));
450
- this.deltaNetServer.setComponentValue(COMPONENT_POSITION_Y, index, BigInt(0));
451
- this.deltaNetServer.setComponentValue(COMPONENT_POSITION_Z, index, BigInt(0));
452
- this.deltaNetServer.setComponentValue(COMPONENT_ROTATION_Y, index, BigInt(0));
453
- this.deltaNetServer.setComponentValue(COMPONENT_ROTATION_W, index, BigInt(0));
454
- this.deltaNetServer.setComponentValue(COMPONENT_STATE, index, BigInt(0));
455
- const asUserData = {
456
- ...userData,
457
- colors: []
458
- };
459
- return {
460
- id: client.id,
461
- afterAddCallback: () => {
462
- this.userNetworkingServer.setAuthenticatedLegacyClientConnection(
463
- client.id,
464
- client.socket,
465
- asUserData
466
- );
467
- this.userNetworkingServer.updateUserCharacter(client.id, asUserData);
468
- }
469
- };
470
- });
471
- const userProfileMessage = JSON.stringify({
472
- id: client.id,
473
- type: LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE,
474
- username: userData.username,
475
- characterDescription: userData.characterDescription
476
- });
477
- client.socket.send(userProfileMessage);
478
- const identityMessage = JSON.stringify({
479
- id: client.id,
480
- type: LEGACY_USER_NETWORKING_IDENTITY_MESSAGE_TYPE
481
- });
482
- client.socket.send(identityMessage);
483
- const allUsers = this.deltaNetServer.dangerouslyGetConnectionsToComponentIndex();
484
- for (const [connectionId, componentIndex] of allUsers) {
485
- if (connectionId === client.id) {
486
- continue;
487
- }
488
- const x = this.deltaNetServer.getComponentValue(COMPONENT_POSITION_X, componentIndex) ?? 0 / positionMultiplier;
489
- const y = this.deltaNetServer.getComponentValue(COMPONENT_POSITION_Y, componentIndex) ?? 0 / positionMultiplier;
490
- const z = this.deltaNetServer.getComponentValue(COMPONENT_POSITION_Z, componentIndex) ?? 0 / positionMultiplier;
491
- const quaternionY = this.deltaNetServer.getComponentValue(COMPONENT_ROTATION_Y, componentIndex) ?? 0 / rotationMultiplier;
492
- const quaternionW = this.deltaNetServer.getComponentValue(COMPONENT_ROTATION_W, componentIndex) ?? 0 / rotationMultiplier;
493
- const state = this.deltaNetServer.getComponentValue(COMPONENT_STATE, componentIndex) ?? 0;
494
- const update = LegacyUserNetworkingCodec.encodeUpdate({
495
- id: connectionId,
496
- position: { x, y, z },
497
- rotation: { quaternionY, quaternionW },
498
- state
499
- });
500
- client.socket.send(
501
- JSON.stringify({
502
- id: connectionId,
503
- type: LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE,
504
- username: this.userNetworkingServer.getUsername(connectionId),
505
- characterDescription: this.userNetworkingServer.getCharacterDescription(connectionId)
506
- })
507
- );
508
- client.socket.send(update);
509
- }
510
- this.legacyAuthenticatedClientsById.set(id, client);
511
- }
512
- });
513
- } else {
514
- this.logger.error(`Unhandled message pre-auth: ${JSON.stringify(parsed)}`);
515
- socket.close();
516
- }
517
- } else {
518
- switch (parsed.type) {
519
- case LEGACY_USER_NETWORKING_PONG_MESSAGE_TYPE:
520
- client.lastPong = Date.now();
521
- break;
522
- case LEGACY_USER_NETWORKING_USER_UPDATE_MESSAGE_TYPE:
523
- this.handleUserUpdate(id, parsed);
524
- break;
525
- default:
526
- this.logger.error(`Unhandled message: ${JSON.stringify(parsed)}`);
527
- }
528
- }
529
- }
530
- } catch (e) {
531
- this.logger.error("Error handling message", message, e);
532
- socket.send(
533
- JSON.stringify({
534
- type: LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE,
535
- errorType: LEGACY_USER_NETWORKING_UNKNOWN_ERROR,
536
- message: "Error handling message"
537
- })
538
- );
539
- socket.close();
540
- }
541
- });
542
- socket.addEventListener("close", () => {
543
- this.handleDisconnectedClient(client);
544
- });
545
- }
546
- handleDisconnectedClient(client) {
547
- if (!this.allClientsById.has(client.id)) {
548
- return;
549
- }
550
- this.allClientsById.delete(client.id);
551
- if (client.authenticatedUser !== null) {
552
- this.userNetworkingServer.onLegacyClientDisconnect(client.id);
553
- this.legacyAuthenticatedClientsById.delete(client.id);
554
- this.deltaNetServer.clearInternalConnectionId(client.id);
555
- }
556
- }
557
- async handleUserAuth(client, credentials) {
558
- const userData = this.userNetworkingServer.onLegacyClientConnect(
559
- client.id,
560
- credentials.sessionToken,
561
- credentials.userIdentity
562
- );
563
- let resolvedUserData;
564
- if (userData instanceof Promise) {
565
- resolvedUserData = await userData;
566
- } else {
567
- resolvedUserData = userData;
568
- }
569
- if (resolvedUserData instanceof Error) {
570
- this.logger.error(`Client-id ${client.id} user_auth failed`, resolvedUserData);
571
- return false;
572
- } else if (resolvedUserData === true) {
573
- this.logger.error(`Client-id ${client.id} user_auth failed`, resolvedUserData);
574
- resolvedUserData = credentials.userIdentity;
575
- } else {
576
- resolvedUserData = resolvedUserData;
577
- }
578
- if (resolvedUserData === null) {
579
- this.logger.error(`Client-id ${client.id} user_auth unauthorized and ignored`);
580
- return false;
581
- }
582
- return resolvedUserData;
583
- }
584
- updateUserCharacter(clientId, userData) {
585
- this.internalUpdateUser(clientId, userData);
586
- }
587
- internalUpdateUser(clientId, userData) {
588
- const client = this.legacyAuthenticatedClientsById.get(clientId);
589
- client.authenticatedUser = userData;
590
- this.legacyAuthenticatedClientsById.set(clientId, client);
591
- this.userNetworkingServer.updateUserCharacter(client.id, { ...userData, colors: [] });
592
- }
593
- async handleUserUpdate(clientId, message) {
594
- const client = this.legacyAuthenticatedClientsById.get(clientId);
595
- if (!client) {
596
- this.logger.error(`Client-id ${clientId} user_update ignored, client not found`);
597
- return;
598
- }
599
- const authorizedUserData = message.userIdentity;
600
- let resolvedAuthorizedUserData;
601
- if (authorizedUserData instanceof Promise) {
602
- resolvedAuthorizedUserData = await authorizedUserData;
603
- } else {
604
- resolvedAuthorizedUserData = authorizedUserData;
605
- }
606
- if (!resolvedAuthorizedUserData) {
607
- this.logger.warn(`Client-id ${clientId} user_update unauthorized and ignored`);
608
- return;
609
- }
610
- this.internalUpdateUser(clientId, resolvedAuthorizedUserData);
611
- }
612
- sendUpdates(removedIds, addedIds, updateUserProfilesInTick) {
613
- for (const id of removedIds) {
614
- const disconnectMessage = JSON.stringify({
615
- id,
616
- type: LEGACY_USER_NETWORKING_DISCONNECTED_MESSAGE_TYPE
617
- });
618
- for (const [, otherClient] of this.legacyAuthenticatedClientsById) {
619
- if (otherClient.socket.readyState === WebSocketOpenStatus) {
620
- otherClient.socket.send(disconnectMessage);
621
- }
622
- }
623
- }
624
- for (const id of addedIds) {
625
- const identityMessage = JSON.stringify({
626
- id,
627
- type: LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE,
628
- username: this.userNetworkingServer.getUsername(id),
629
- characterDescription: this.userNetworkingServer.getCharacterDescription(id)
630
- });
631
- for (const [, otherClient] of this.legacyAuthenticatedClientsById) {
632
- if (otherClient.socket.readyState === WebSocketOpenStatus) {
633
- otherClient.socket.send(identityMessage);
634
- }
635
- }
636
- }
637
- for (const id of updateUserProfilesInTick) {
638
- const identityMessage = JSON.stringify({
639
- id,
640
- type: LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE,
641
- username: this.userNetworkingServer.getUsername(id),
642
- characterDescription: this.userNetworkingServer.getCharacterDescription(id)
643
- });
644
- for (const [, otherClient] of this.legacyAuthenticatedClientsById) {
645
- if (otherClient.socket.readyState === WebSocketOpenStatus) {
646
- otherClient.socket.send(identityMessage);
647
- }
648
- }
649
- }
650
- const allUsers = this.deltaNetServer.dangerouslyGetConnectionsToComponentIndex();
651
- for (const [connectionId, componentIndex] of allUsers) {
652
- const x = this.deltaNetServer.getComponentValue(COMPONENT_POSITION_X, componentIndex) ?? 0 / positionMultiplier;
653
- const y = this.deltaNetServer.getComponentValue(COMPONENT_POSITION_Y, componentIndex) ?? 0 / positionMultiplier;
654
- const z = this.deltaNetServer.getComponentValue(COMPONENT_POSITION_Z, componentIndex) ?? 0 / positionMultiplier;
655
- const quaternionY = this.deltaNetServer.getComponentValue(COMPONENT_ROTATION_Y, componentIndex) ?? 0 / rotationMultiplier;
656
- const quaternionW = this.deltaNetServer.getComponentValue(COMPONENT_ROTATION_W, componentIndex) ?? 0 / rotationMultiplier;
657
- const state = this.deltaNetServer.getComponentValue(COMPONENT_STATE, componentIndex) ?? 0;
658
- const encodedUpdate = LegacyUserNetworkingCodec.encodeUpdate({
659
- id: connectionId,
660
- position: { x, y, z },
661
- rotation: { quaternionY, quaternionW },
662
- state
663
- });
664
- for (const [otherClientId, otherClient] of this.legacyAuthenticatedClientsById) {
665
- if (otherClientId !== connectionId && otherClient.socket.readyState === WebSocketOpenStatus) {
666
- otherClient.socket.send(encodedUpdate);
667
- }
668
- }
669
- }
670
- }
671
- dispose(clientCloseError) {
672
- const stringifiedError = clientCloseError ? JSON.stringify(clientCloseError) : void 0;
673
- for (const [, client] of this.legacyAuthenticatedClientsById) {
674
- if (stringifiedError) {
675
- client.socket.send(stringifiedError);
676
- }
677
- client.socket.close();
678
- }
230
+ return { connectionId, ...userStates };
679
231
  }
680
232
  };
681
233
 
@@ -721,184 +273,114 @@ var UserNetworkingServer = class {
721
273
  this.handleCustomMessage(customMessage);
722
274
  }
723
275
  });
724
- if (this.options.legacyAdapterEnabled) {
725
- this.legacyAdapter = new LegacyAdapter(this, this.deltaNetServer, this.logger);
726
- }
727
276
  this.tickInterval = setInterval(() => {
728
- const { removedIds, addedIds } = this.deltaNetServer.tick();
729
- if (this.legacyAdapter) {
730
- this.legacyAdapter.sendUpdates(removedIds, addedIds, this.updatedUserProfilesInTick);
731
- this.updatedUserProfilesInTick.clear();
277
+ const { addedIds, addedObserverIds } = this.deltaNetServer.tick();
278
+ if (this.options.onClientAuthenticated) {
279
+ for (const connectionId of addedIds) {
280
+ this.options.onClientAuthenticated(connectionId);
281
+ }
282
+ for (const connectionId of addedObserverIds) {
283
+ this.options.onClientAuthenticated(connectionId);
284
+ }
732
285
  }
733
286
  }, 50);
734
287
  }
735
288
  deltaNetServer;
736
289
  authenticatedClientsById = /* @__PURE__ */ new Map();
290
+ connectionIdByUserId = /* @__PURE__ */ new Map();
737
291
  tickInterval;
738
- legacyAdapter = null;
739
- updatedUserProfilesInTick = /* @__PURE__ */ new Set();
740
- getCharacterDescription(connectionId) {
741
- var _a;
742
- const client = this.authenticatedClientsById.get(connectionId);
743
- return ((_a = client == null ? void 0 : client.authenticatedUser) == null ? void 0 : _a.characterDescription) ?? { mmlCharacterUrl: "" };
744
- }
745
- getUsername(connectionId) {
746
- var _a, _b;
747
- const client = this.authenticatedClientsById.get(connectionId);
748
- this.logger.info("getUsername", connectionId, (_a = client == null ? void 0 : client.authenticatedUser) == null ? void 0 : _a.username);
749
- return ((_b = client == null ? void 0 : client.authenticatedUser) == null ? void 0 : _b.username) ?? "";
750
- }
751
- getLegacyClientId() {
752
- return this.deltaNetServer.getNextConnectionId();
753
- }
754
- hasCapacityForLegacyClient() {
755
- return true;
756
- }
757
- onLegacyClientConnect(id, sessionToken, userIdentity) {
758
- return this.options.onClientConnect(id, sessionToken, {
759
- username: (userIdentity == null ? void 0 : userIdentity.username) ?? null,
760
- characterDescription: (userIdentity == null ? void 0 : userIdentity.characterDescription) ?? null,
761
- colors: null
762
- });
763
- }
764
- setAuthenticatedLegacyClientConnection(clientId, webSocket, userData) {
765
- this.logger.info("setAuthenticatedLegacyClientConnection", clientId, userData);
766
- const authenticatedClient = {
767
- id: clientId,
768
- socket: webSocket,
769
- lastPong: Date.now(),
770
- authenticatedUser: userData,
771
- deltaNetConnection: null
772
- };
773
- this.authenticatedClientsById.set(clientId, authenticatedClient);
774
- }
775
- onLegacyClientDisconnect(id) {
776
- this.options.onClientDisconnect(id);
777
- }
778
292
  handleStatesUpdate(update) {
779
- const deltaNetConnection = update.deltaNetV01Connection;
780
- const clientId = deltaNetConnection.internalConnectionId;
293
+ var _a, _b, _c;
294
+ const deltaNetConnection = update.connection;
295
+ const connectionId = deltaNetConnection.internalConnectionId;
781
296
  const updatedStates = update.states;
782
297
  const updatedStatesMap = new Map(updatedStates);
783
- const updatedUserData = DeltaNetComponentMapping.fromUserStates(
784
- updatedStatesMap,
785
- this.logger
786
- );
787
- const existingClient = this.authenticatedClientsById.get(clientId);
298
+ const decoded = DeltaNetComponentMapping.fromUserStates(updatedStatesMap, this.logger);
299
+ const existingClient = this.authenticatedClientsById.get(connectionId);
788
300
  if (!existingClient) {
789
- return new DeltaNetServerError2(
790
- DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
301
+ return new DeltaNetServerError(
302
+ DeltaNetServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
791
303
  "User not authenticated - no client found",
792
304
  false
793
305
  );
794
306
  }
795
- const existingUserData = existingClient.authenticatedUser ?? {};
796
- const userData = {
797
- ...existingUserData,
798
- ...updatedUserData
307
+ const identityUpdate = {
308
+ username: decoded.username ?? ((_a = existingClient.authenticatedUser) == null ? void 0 : _a.username) ?? null,
309
+ characterDescription: decoded.characterDescription ?? ((_b = existingClient.authenticatedUser) == null ? void 0 : _b.characterDescription) ?? null,
310
+ colors: decoded.colors ?? ((_c = existingClient.authenticatedUser) == null ? void 0 : _c.colors) ?? null
799
311
  };
800
- const res = this.options.onClientUserIdentityUpdate(clientId, userData);
312
+ const res = this.options.onClientUserIdentityUpdate(connectionId, identityUpdate);
801
313
  if (res instanceof Promise) {
802
314
  return res.then((res2) => {
803
- if (!this.authenticatedClientsById.get(clientId)) {
804
- return new DeltaNetServerError2(
805
- DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
806
- "User not authenticated - client disconnected",
807
- false
808
- );
809
- }
810
- if (res2 instanceof DeltaNetServerError2) {
811
- return res2;
812
- }
813
- if (res2 instanceof Error) {
814
- return new DeltaNetServerError2(
815
- DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
816
- "User identity update failed",
817
- false
818
- );
819
- }
820
- if (res2 === null) {
821
- return new DeltaNetServerError2(
822
- DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
823
- "User identity update failed",
824
- false
825
- );
826
- }
827
- if (res2 === false) {
828
- return new DeltaNetServerError2(
829
- DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
830
- "User identity update failed",
831
- false
832
- );
833
- }
834
- if (!res2 || typeof res2 !== "object") {
835
- return new DeltaNetServerError2(
836
- DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
837
- "User identity update failed",
838
- false
839
- );
840
- }
841
- this.updatedUserProfilesInTick.add(clientId);
842
- existingClient.authenticatedUser = {
843
- ...existingClient.authenticatedUser,
844
- ...res2
845
- };
846
- return {
847
- success: true,
848
- stateOverrides: Array.from(DeltaNetComponentMapping.toStates(res2).entries())
849
- };
315
+ return this.applyIdentityUpdateResult(existingClient, connectionId, identityUpdate, res2);
850
316
  });
851
317
  }
852
- if (res instanceof DeltaNetServerError2) {
318
+ return this.applyIdentityUpdateResult(existingClient, connectionId, identityUpdate, res);
319
+ }
320
+ applyIdentityUpdateResult(existingClient, connectionId, identityUpdate, res) {
321
+ var _a, _b;
322
+ if (this.authenticatedClientsById.get(connectionId) !== existingClient) {
323
+ return new DeltaNetServerError(
324
+ DeltaNetServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
325
+ "User not authenticated - client disconnected",
326
+ false
327
+ );
328
+ }
329
+ if (res instanceof DeltaNetServerError) {
853
330
  return res;
854
331
  }
855
332
  if (res instanceof Error) {
856
- return new DeltaNetServerError2(
857
- DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
333
+ return new DeltaNetServerError(
334
+ DeltaNetServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
858
335
  "User identity update failed",
859
336
  false
860
337
  );
861
338
  }
862
- if (res === null) {
863
- return new DeltaNetServerError2(
864
- DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
339
+ if (res === null || res === false) {
340
+ return new DeltaNetServerError(
341
+ DeltaNetServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
865
342
  "User identity update failed",
866
343
  false
867
344
  );
868
345
  }
869
- if (res === false) {
870
- return new DeltaNetServerError2(
871
- DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
872
- "User identity update failed",
873
- false
874
- );
346
+ if (res === true) {
347
+ existingClient.authenticatedUser = {
348
+ userId: ((_a = existingClient.authenticatedUser) == null ? void 0 : _a.userId) ?? "",
349
+ username: identityUpdate.username,
350
+ characterDescription: identityUpdate.characterDescription,
351
+ colors: identityUpdate.colors
352
+ };
353
+ return { success: true };
875
354
  }
876
355
  if (!res || typeof res !== "object") {
877
- return new DeltaNetServerError2(
878
- DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
356
+ return new DeltaNetServerError(
357
+ DeltaNetServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
879
358
  "User identity update failed",
880
359
  false
881
360
  );
882
361
  }
883
- this.updatedUserProfilesInTick.add(clientId);
884
362
  existingClient.authenticatedUser = {
885
- ...existingClient.authenticatedUser,
886
- ...res
363
+ userId: ((_b = existingClient.authenticatedUser) == null ? void 0 : _b.userId) ?? "",
364
+ username: res.username,
365
+ characterDescription: res.characterDescription,
366
+ colors: res.colors
887
367
  };
888
368
  return {
889
369
  success: true,
890
- stateOverrides: Array.from(DeltaNetComponentMapping.toStates(res).entries())
370
+ stateOverrides: Array.from(
371
+ DeltaNetComponentMapping.toStates(existingClient.authenticatedUser).entries()
372
+ )
891
373
  };
892
374
  }
893
375
  handleJoiner(joiner) {
894
- const deltaNetConnection = joiner.deltaNetV01Connection;
376
+ const deltaNetConnection = joiner.connection;
895
377
  const webSocket = deltaNetConnection.webSocket;
896
378
  const states = joiner.states;
897
- const clientId = joiner.internalConnectionId;
379
+ const connectionId = joiner.internalConnectionId;
898
380
  const statesMap = new Map(states);
899
381
  const userData = DeltaNetComponentMapping.fromUserStates(statesMap, this.logger);
900
382
  return this.handleDeltaNetAuthentication(
901
- clientId,
383
+ connectionId,
902
384
  webSocket,
903
385
  deltaNetConnection,
904
386
  joiner.token,
@@ -906,9 +388,12 @@ var UserNetworkingServer = class {
906
388
  ).then((authResult) => {
907
389
  var _a;
908
390
  if (!authResult.success) {
909
- this.logger.warn(`Authentication failed for client ID: ${clientId}`, authResult.error);
910
- return new DeltaNetServerError2(
911
- DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
391
+ this.logger.warn(
392
+ `Authentication failed for connection ID: ${connectionId}`,
393
+ authResult.error
394
+ );
395
+ return new DeltaNetServerError(
396
+ DeltaNetServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
912
397
  ((_a = authResult.error) == null ? void 0 : _a.message) || "Authentication failed",
913
398
  false
914
399
  );
@@ -919,54 +404,52 @@ var UserNetworkingServer = class {
919
404
  };
920
405
  }
921
406
  }).catch((error) => {
922
- this.logger.error(`Authentication error for client ID: ${clientId}:`, error);
923
- return new DeltaNetServerError2(
924
- DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
407
+ this.logger.error(`Authentication error for connection ID: ${connectionId}:`, error);
408
+ return new DeltaNetServerError(
409
+ DeltaNetServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
925
410
  "Authentication error",
926
411
  false
927
412
  );
928
413
  });
929
414
  }
930
415
  handleLeave(leave) {
931
- const deltaNetConnection = leave.deltaNetV01Connection;
932
- const clientId = deltaNetConnection.internalConnectionId;
933
- if (clientId !== void 0) {
934
- const client = this.authenticatedClientsById.get(clientId);
416
+ var _a;
417
+ const deltaNetConnection = leave.connection;
418
+ const connectionId = deltaNetConnection.internalConnectionId;
419
+ if (connectionId !== void 0) {
420
+ const client = this.authenticatedClientsById.get(connectionId);
935
421
  if (client) {
936
- this.options.onClientDisconnect(clientId);
937
- this.authenticatedClientsById.delete(clientId);
422
+ if ((_a = client.authenticatedUser) == null ? void 0 : _a.userId) {
423
+ this.connectionIdByUserId.delete(client.authenticatedUser.userId);
424
+ }
425
+ this.options.onClientDisconnect(connectionId);
426
+ this.authenticatedClientsById.delete(connectionId);
938
427
  }
939
428
  }
940
429
  }
941
430
  handleCustomMessage(customMessage) {
942
- const deltaNetConnection = customMessage.deltaNetV01Connection;
943
- const clientId = deltaNetConnection.internalConnectionId;
944
- const client = this.authenticatedClientsById.get(clientId);
431
+ var _a, _b;
432
+ const deltaNetConnection = customMessage.connection;
433
+ const connectionId = deltaNetConnection.internalConnectionId;
434
+ const client = this.authenticatedClientsById.get(connectionId);
945
435
  if (client && client.authenticatedUser) {
946
- if (customMessage.customType === FROM_CLIENT_CHAT_MESSAGE_TYPE) {
947
- const chatMessage = parseClientChatMessage(customMessage.contents);
948
- if (chatMessage instanceof Error) {
949
- this.logger.error(`Invalid chat message from client ${clientId}:`, chatMessage);
950
- } else {
951
- const serverChatMessage = {
952
- fromUserId: clientId,
953
- message: chatMessage.message
954
- };
955
- this.deltaNetServer.broadcastCustomMessage(
956
- FROM_SERVER_CHAT_MESSAGE_TYPE,
957
- JSON.stringify(serverChatMessage)
958
- );
959
- }
960
- }
436
+ (_b = (_a = this.options).onCustomMessage) == null ? void 0 : _b.call(
437
+ _a,
438
+ connectionId,
439
+ customMessage.customType,
440
+ customMessage.contents
441
+ );
961
442
  } else {
962
- this.logger.warn(`Custom message from unauthenticated client ${clientId} - ignoring`);
443
+ this.logger.warn(`Custom message from unauthenticated client ${connectionId} - ignoring`);
963
444
  }
964
445
  }
965
- async handleDeltaNetAuthentication(clientId, webSocket, deltaNetConnection, sessionToken, userIdentity) {
446
+ async handleDeltaNetAuthentication(connectionId, webSocket, deltaNetConnection, sessionToken, userIdentity) {
966
447
  try {
967
- let onClientConnectReturn = deltaNetConnection.isObserver ? null : await this.options.onClientConnect(clientId, sessionToken, userIdentity);
448
+ let onClientConnectReturn = deltaNetConnection.isObserver ? null : await this.options.onClientConnect(connectionId, sessionToken, userIdentity);
968
449
  if (!deltaNetConnection.isObserver && !onClientConnectReturn) {
969
- this.logger.warn(`Authentication failed for client ${clientId} - no user data returned`);
450
+ this.logger.warn(
451
+ `Authentication failed for connection ${connectionId} - no user data returned`
452
+ );
970
453
  return { success: false };
971
454
  }
972
455
  if (onClientConnectReturn instanceof Error) {
@@ -975,15 +458,31 @@ var UserNetworkingServer = class {
975
458
  if (onClientConnectReturn === true) {
976
459
  onClientConnectReturn = userIdentity;
977
460
  }
461
+ if (onClientConnectReturn && !onClientConnectReturn.userId) {
462
+ onClientConnectReturn = {
463
+ ...onClientConnectReturn,
464
+ userId: crypto.randomUUID()
465
+ };
466
+ }
467
+ if (onClientConnectReturn && this.connectionIdByUserId.has(onClientConnectReturn.userId)) {
468
+ this.options.onClientDisconnect(connectionId);
469
+ return {
470
+ success: false,
471
+ error: new Error(`userId "${onClientConnectReturn.userId}" is already connected`)
472
+ };
473
+ }
978
474
  const authenticatedUser = onClientConnectReturn;
979
475
  const authenticatedClient = {
980
- id: clientId,
476
+ connectionId,
981
477
  socket: webSocket,
982
478
  lastPong: Date.now(),
983
479
  authenticatedUser,
984
480
  deltaNetConnection
985
481
  };
986
- this.authenticatedClientsById.set(clientId, authenticatedClient);
482
+ this.authenticatedClientsById.set(connectionId, authenticatedClient);
483
+ if (authenticatedUser == null ? void 0 : authenticatedUser.userId) {
484
+ this.connectionIdByUserId.set(authenticatedUser.userId, connectionId);
485
+ }
987
486
  let stateOverrides = [];
988
487
  if (onClientConnectReturn) {
989
488
  const officialStates = DeltaNetComponentMapping.toStates(onClientConnectReturn);
@@ -999,128 +498,145 @@ var UserNetworkingServer = class {
999
498
  }
1000
499
  }
1001
500
  connectClient(socket) {
1002
- if (socket.protocol === "") {
1003
- if (this.legacyAdapter) {
1004
- this.legacyAdapter.addWebSocket(socket);
1005
- return;
1006
- } else {
1007
- socket.close(1e3, "Legacy client detected (no subprotocol) - not supported");
1008
- return;
1009
- }
501
+ const resolvedProtocol = this.options.resolveProtocol ? this.options.resolveProtocol(socket.protocol) : void 0;
502
+ if (resolvedProtocol === null) {
503
+ this.logger.warn(
504
+ `Rejecting client: unsupported WebSocket sub-protocol "${socket.protocol}". resolveProtocol returned null, indicating no matching protocol version.`
505
+ );
506
+ socket.close(1002, "Unsupported sub-protocol");
507
+ return;
1010
508
  }
1011
- this.deltaNetServer.addWebSocket(socket);
509
+ this.deltaNetServer.addWebSocket(
510
+ socket,
511
+ resolvedProtocol ?? void 0
512
+ );
1012
513
  socket.addEventListener("close", () => {
1013
514
  this.deltaNetServer.removeWebSocket(socket);
1014
515
  });
1015
516
  }
1016
517
  broadcastMessage(broadcastType, broadcastPayload) {
1017
518
  this.deltaNetServer.broadcastCustomMessage(broadcastType, broadcastPayload);
1018
- if (this.legacyAdapter) {
1019
- this.legacyAdapter.broadcastMessage(broadcastType, broadcastPayload);
519
+ }
520
+ sendCustomMessageToClient(connectionId, customType, payload) {
521
+ const client = this.authenticatedClientsById.get(connectionId);
522
+ if (!client) {
523
+ return;
1020
524
  }
525
+ this.deltaNetServer.sendCustomMessageToConnection(connectionId, customType, payload);
526
+ }
527
+ getAuthenticatedUser(connectionId) {
528
+ const client = this.authenticatedClientsById.get(connectionId);
529
+ return (client == null ? void 0 : client.authenticatedUser) ?? null;
1021
530
  }
1022
- updateUserCharacter(clientId, userData) {
1023
- this.logger.info("updateUserCharacter", clientId, userData);
1024
- this.internalUpdateUser(clientId, userData);
531
+ updateUserCharacter(connectionId, userData) {
532
+ this.logger.info("updateUserCharacter", connectionId, userData);
533
+ this.internalUpdateUser(connectionId, userData);
1025
534
  }
1026
- updateUserUsername(clientId, username) {
1027
- const client = this.authenticatedClientsById.get(clientId);
535
+ updateUserUsername(connectionId, username) {
536
+ const client = this.authenticatedClientsById.get(connectionId);
1028
537
  if (!client || !client.authenticatedUser) return;
1029
538
  client.authenticatedUser = {
1030
539
  ...client.authenticatedUser,
1031
540
  username
1032
541
  };
1033
- this.updatedUserProfilesInTick.add(clientId);
1034
542
  const states = DeltaNetComponentMapping.toUsernameState(username);
1035
543
  const asArray = Array.from(states.entries());
1036
- this.deltaNetServer.overrideUserStates(client.deltaNetConnection, clientId, asArray);
544
+ this.deltaNetServer.overrideUserStates(client.deltaNetConnection, connectionId, asArray);
1037
545
  }
1038
- updateUserCharacterDescription(clientId, characterDescription) {
1039
- const client = this.authenticatedClientsById.get(clientId);
546
+ updateUserCharacterDescription(connectionId, characterDescription) {
547
+ const client = this.authenticatedClientsById.get(connectionId);
1040
548
  if (!client || !client.authenticatedUser) return;
1041
549
  client.authenticatedUser = {
1042
550
  ...client.authenticatedUser,
1043
551
  characterDescription
1044
552
  };
1045
- this.updatedUserProfilesInTick.add(clientId);
1046
553
  const states = DeltaNetComponentMapping.toCharacterDescriptionState(characterDescription);
1047
554
  const asArray = Array.from(states.entries());
1048
- this.deltaNetServer.overrideUserStates(client.deltaNetConnection, clientId, asArray);
555
+ this.deltaNetServer.overrideUserStates(client.deltaNetConnection, connectionId, asArray);
1049
556
  }
1050
- updateUserColors(clientId, colors) {
1051
- const client = this.authenticatedClientsById.get(clientId);
557
+ updateUserColors(connectionId, colors) {
558
+ const client = this.authenticatedClientsById.get(connectionId);
1052
559
  if (!client || !client.authenticatedUser) return;
1053
560
  client.authenticatedUser = {
1054
561
  ...client.authenticatedUser,
1055
562
  colors
1056
563
  };
1057
- this.updatedUserProfilesInTick.add(clientId);
1058
564
  const states = DeltaNetComponentMapping.toColorsState(colors);
1059
565
  const asArray = Array.from(states.entries());
1060
- this.deltaNetServer.overrideUserStates(client.deltaNetConnection, clientId, asArray);
566
+ this.deltaNetServer.overrideUserStates(client.deltaNetConnection, connectionId, asArray);
1061
567
  }
1062
- updateUserStates(clientId, updates) {
1063
- const client = this.authenticatedClientsById.get(clientId);
568
+ updateUserStates(connectionId, updates) {
569
+ const client = this.authenticatedClientsById.get(connectionId);
1064
570
  if (!client || !client.authenticatedUser) return;
1065
571
  const states = /* @__PURE__ */ new Map();
1066
572
  let hasUpdates = false;
1067
573
  let updatedUserData = client.authenticatedUser;
1068
- this.updatedUserProfilesInTick.add(clientId);
1069
- if (updates.username !== null) {
574
+ if (updates.username !== void 0) {
1070
575
  updatedUserData = {
1071
576
  ...updatedUserData,
1072
577
  username: updates.username
1073
578
  };
1074
- const usernameStates = DeltaNetComponentMapping.toUsernameState(updates.username);
1075
- for (const [stateId, stateValue] of usernameStates) {
1076
- states.set(stateId, stateValue);
579
+ if (updates.username !== null) {
580
+ const usernameStates = DeltaNetComponentMapping.toUsernameState(updates.username);
581
+ for (const [stateId, stateValue] of usernameStates) {
582
+ states.set(stateId, stateValue);
583
+ }
584
+ } else {
585
+ states.set(STATE_USERNAME, new Uint8Array(0));
1077
586
  }
1078
587
  hasUpdates = true;
1079
588
  }
1080
- if (updates.characterDescription !== null) {
589
+ if (updates.characterDescription !== void 0) {
1081
590
  updatedUserData = {
1082
591
  ...updatedUserData,
1083
592
  characterDescription: updates.characterDescription
1084
593
  };
1085
- const characterDescStates = DeltaNetComponentMapping.toCharacterDescriptionState(
1086
- updates.characterDescription
1087
- );
1088
- for (const [stateId, stateValue] of characterDescStates) {
1089
- states.set(stateId, stateValue);
594
+ if (updates.characterDescription !== null) {
595
+ const characterDescStates = DeltaNetComponentMapping.toCharacterDescriptionState(
596
+ updates.characterDescription
597
+ );
598
+ for (const [stateId, stateValue] of characterDescStates) {
599
+ states.set(stateId, stateValue);
600
+ }
601
+ } else {
602
+ states.set(STATE_CHARACTER_DESCRIPTION, new Uint8Array(0));
1090
603
  }
1091
604
  hasUpdates = true;
1092
605
  }
1093
- if (updates.colors !== null) {
606
+ if (updates.colors !== void 0) {
1094
607
  updatedUserData = {
1095
608
  ...updatedUserData,
1096
609
  colors: updates.colors
1097
610
  };
1098
- const colorsStates = DeltaNetComponentMapping.toColorsState(updates.colors);
1099
- for (const [stateId, stateValue] of colorsStates) {
1100
- states.set(stateId, stateValue);
611
+ if (updates.colors !== null) {
612
+ const colorsStates = DeltaNetComponentMapping.toColorsState(updates.colors);
613
+ for (const [stateId, stateValue] of colorsStates) {
614
+ states.set(stateId, stateValue);
615
+ }
616
+ } else {
617
+ states.set(STATE_COLORS, new Uint8Array(0));
1101
618
  }
1102
619
  hasUpdates = true;
1103
620
  }
1104
621
  if (hasUpdates) {
1105
622
  client.authenticatedUser = updatedUserData;
1106
623
  const asArray = Array.from(states.entries());
1107
- this.deltaNetServer.overrideUserStates(client.deltaNetConnection, clientId, asArray);
624
+ this.deltaNetServer.overrideUserStates(client.deltaNetConnection, connectionId, asArray);
1108
625
  }
1109
626
  }
1110
- internalUpdateUser(clientId, userData) {
1111
- const client = this.authenticatedClientsById.get(clientId);
627
+ internalUpdateUser(connectionId, userData) {
628
+ const client = this.authenticatedClientsById.get(connectionId);
1112
629
  if (!client) {
1113
- throw new Error(`internalUpdateUser - client not found for clientId ${clientId}`);
630
+ throw new Error(`internalUpdateUser - client not found for connectionId ${connectionId}`);
1114
631
  }
1115
- this.logger.info("internalUpdateUser", clientId, userData);
1116
- this.updatedUserProfilesInTick.add(clientId);
632
+ this.logger.info("internalUpdateUser", connectionId, userData);
1117
633
  client.authenticatedUser = {
1118
634
  ...client.authenticatedUser,
1119
635
  ...userData
1120
636
  };
1121
637
  const states = DeltaNetComponentMapping.toStates(userData);
1122
638
  const asArray = Array.from(states.entries());
1123
- this.deltaNetServer.overrideUserStates(client.deltaNetConnection, clientId, asArray);
639
+ this.deltaNetServer.overrideUserStates(client.deltaNetConnection, connectionId, asArray);
1124
640
  }
1125
641
  dispose(clientCloseError) {
1126
642
  if (this.tickInterval) {
@@ -1142,6 +658,8 @@ var UserNetworkingServer = class {
1142
658
  client.socket.close();
1143
659
  }
1144
660
  this.authenticatedClientsById.clear();
661
+ this.connectionIdByUserId.clear();
662
+ this.deltaNetServer.dispose();
1145
663
  }
1146
664
  };
1147
665
 
@@ -1168,10 +686,11 @@ var UserNetworkingClient = class {
1168
686
  this.logger = logger;
1169
687
  this.pendingUpdate = initialUpdate ?? {
1170
688
  position: { x: 0, y: 0, z: 0 },
1171
- rotation: { quaternionY: 0, quaternionW: 1 },
689
+ rotation: { eulerY: 0 },
1172
690
  state: 0
1173
691
  };
1174
692
  this.userState = initialUserState ?? {
693
+ userId: "",
1175
694
  username: null,
1176
695
  characterDescription: null,
1177
696
  colors: null
@@ -1191,19 +710,19 @@ var UserNetworkingClient = class {
1191
710
  const networkUpdate = this.processNetworkUpdate([], addedStableIds, []);
1192
711
  this.config.onUpdate(networkUpdate);
1193
712
  if (this.userIndex !== null) {
1194
- const userIds = this.deltaNetState.getStableIds();
1195
- if (this.userIndex < userIds.length) {
1196
- const stableId = userIds[this.userIndex];
1197
- const userId = this.stableIdToUserId.get(stableId);
1198
- if (!userId) {
1199
- throw new Error(`No userId found for stableId ${stableId}`);
713
+ const stableIds = this.deltaNetState.getStableIds();
714
+ if (this.userIndex < stableIds.length) {
715
+ const stableId = stableIds[this.userIndex];
716
+ const connId = this.stableIdToConnectionId.get(stableId);
717
+ if (!connId) {
718
+ throw new Error(`No connectionId found for stableId ${stableId}`);
1200
719
  }
1201
- this.userId = userId;
720
+ this.connectionId = connId;
1202
721
  this.isAuthenticated = true;
1203
- this.config.assignedIdentity(this.userId);
722
+ this.config.assignedIdentity(this.connectionId);
1204
723
  } else {
1205
724
  this.logger.error(
1206
- `Invalid userIndex ${this.userIndex}, userIds length: ${userIds.length}`
725
+ `Invalid userIndex ${this.userIndex}, stableIds length: ${stableIds.length}`
1207
726
  );
1208
727
  }
1209
728
  }
@@ -1244,7 +763,7 @@ var UserNetworkingClient = class {
1244
763
  }
1245
764
  },
1246
765
  void 0,
1247
- // timeCallback is optional
766
+ // timeCallback
1248
767
  (status) => {
1249
768
  let mappedStatus;
1250
769
  switch (status) {
@@ -1267,28 +786,30 @@ var UserNetworkingClient = class {
1267
786
  mappedStatus = 3 /* Disconnected */;
1268
787
  }
1269
788
  this.config.statusUpdateCallback(mappedStatus);
1270
- }
789
+ },
790
+ config.resolveProtocol
1271
791
  );
1272
792
  }
1273
793
  deltaNetClient;
1274
794
  deltaNetState;
1275
- userId = null;
795
+ connectionId = null;
1276
796
  userIndex = null;
1277
797
  userState = {
798
+ userId: "",
1278
799
  username: null,
1279
800
  characterDescription: null,
1280
801
  colors: null
1281
802
  };
1282
- stableIdToUserId = /* @__PURE__ */ new Map();
803
+ stableIdToConnectionId = /* @__PURE__ */ new Map();
1283
804
  userProfiles = /* @__PURE__ */ new Map();
1284
805
  isAuthenticated = false;
1285
806
  pendingUpdate;
1286
807
  reset() {
1287
808
  this.deltaNetState.reset();
1288
809
  this.userProfiles.clear();
1289
- this.stableIdToUserId.clear();
810
+ this.stableIdToConnectionId.clear();
1290
811
  this.isAuthenticated = false;
1291
- this.userId = null;
812
+ this.connectionId = null;
1292
813
  this.userIndex = null;
1293
814
  }
1294
815
  sendInitialAuthentication() {
@@ -1297,16 +818,16 @@ var UserNetworkingClient = class {
1297
818
  this.deltaNetClient.setUserComponents(components, states);
1298
819
  }
1299
820
  processNetworkUpdate(removedStableIds, addedStableIdsArray, stateUpdates) {
1300
- const addedUserIds = /* @__PURE__ */ new Map();
1301
- const removedUserIds = /* @__PURE__ */ new Set();
821
+ const addedConnectionIds = /* @__PURE__ */ new Map();
822
+ const removedConnectionIds = /* @__PURE__ */ new Set();
1302
823
  for (const stableId of removedStableIds) {
1303
- const userId = this.stableIdToUserId.get(stableId);
1304
- if (userId) {
1305
- removedUserIds.add(userId);
1306
- this.userProfiles.delete(userId);
1307
- this.stableIdToUserId.delete(stableId);
824
+ const connId = this.stableIdToConnectionId.get(stableId);
825
+ if (connId) {
826
+ removedConnectionIds.add(connId);
827
+ this.userProfiles.delete(connId);
828
+ this.stableIdToConnectionId.delete(stableId);
1308
829
  } else {
1309
- throw new Error(`No userId found for stableId ${stableId}`);
830
+ throw new Error(`No connectionId found for stableId ${stableId}`);
1310
831
  }
1311
832
  }
1312
833
  for (const stableId of addedStableIdsArray) {
@@ -1314,33 +835,33 @@ var UserNetworkingClient = class {
1314
835
  if (!stableUserData) {
1315
836
  throw new Error(`No stableUserData found for stableId ${stableId}`);
1316
837
  }
1317
- const userIdState = stableUserData.states.get(STATE_INTERNAL_CONNECTION_ID);
1318
- if (!userIdState) {
1319
- throw new Error(`No userIdState found for stableId ${stableId}`);
838
+ const connectionIdState = stableUserData.states.get(STATE_INTERNAL_CONNECTION_ID);
839
+ if (!connectionIdState) {
840
+ throw new Error(`No connectionIdState found for stableId ${stableId}`);
1320
841
  }
1321
- const userId = DeltaNetComponentMapping.userIdFromBytes(userIdState);
1322
- if (!userId) {
1323
- throw new Error(`Failed to extract userId from bytes for stableId ${stableId}`);
842
+ const connId = DeltaNetComponentMapping.userIdFromBytes(connectionIdState);
843
+ if (!connId) {
844
+ throw new Error(`Failed to extract connectionId from bytes for stableId ${stableId}`);
1324
845
  }
1325
- this.stableIdToUserId.set(stableId, userId);
846
+ this.stableIdToConnectionId.set(stableId, connId);
1326
847
  const newProfile = DeltaNetComponentMapping.fromStates(stableUserData.states, this.logger);
1327
- this.userProfiles.set(userId, newProfile);
848
+ this.userProfiles.set(connId, newProfile);
1328
849
  const clientUpdate = DeltaNetComponentMapping.fromComponents(stableUserData.components);
1329
- addedUserIds.set(userId, {
850
+ addedConnectionIds.set(connId, {
1330
851
  userState: newProfile,
1331
852
  components: clientUpdate
1332
853
  });
1333
854
  }
1334
855
  const updatedUsers = /* @__PURE__ */ new Map();
1335
856
  for (const [stableUserId, userInfo] of this.deltaNetState.byStableId) {
1336
- const userId = this.stableIdToUserId.get(stableUserId);
1337
- if (!userId) {
1338
- throw new Error(`No userId found for stableUserId ${stableUserId}`);
857
+ const connId = this.stableIdToConnectionId.get(stableUserId);
858
+ if (!connId) {
859
+ throw new Error(`No connectionId found for stableUserId ${stableUserId}`);
1339
860
  }
1340
- if (!addedUserIds.has(userId)) {
861
+ if (!addedConnectionIds.has(connId)) {
1341
862
  if (userInfo.components.size > 0) {
1342
863
  const clientUpdate = DeltaNetComponentMapping.fromComponents(userInfo.components);
1343
- updatedUsers.set(userId, {
864
+ updatedUsers.set(connId, {
1344
865
  components: clientUpdate
1345
866
  });
1346
867
  }
@@ -1348,19 +869,25 @@ var UserNetworkingClient = class {
1348
869
  }
1349
870
  for (const update of stateUpdates) {
1350
871
  const stableUserId = update.stableId;
1351
- const userId = this.stableIdToUserId.get(stableUserId);
1352
- if (!userId) {
1353
- throw new Error(`No userId found for stableUserId ${stableUserId}`);
872
+ const connId = this.stableIdToConnectionId.get(stableUserId);
873
+ if (!connId) {
874
+ throw new Error(`No connectionId found for stableUserId ${stableUserId}`);
1354
875
  }
1355
- if (addedUserIds.has(userId)) {
876
+ if (addedConnectionIds.has(connId)) {
1356
877
  continue;
1357
878
  }
1358
- const profile = this.userProfiles.get(userId);
879
+ const profile = this.userProfiles.get(connId);
1359
880
  if (!profile) {
1360
- this.logger.warn(`No profile found for user ${userId}, skipping update`);
881
+ this.logger.warn(`No profile found for connection ${connId}, skipping update`);
1361
882
  continue;
1362
883
  }
1363
- const existingUpdate = updatedUsers.get(userId);
884
+ let existingUpdate = updatedUsers.get(connId);
885
+ if (!existingUpdate) {
886
+ const stableUserData = this.deltaNetState.byStableId.get(stableUserId);
887
+ const components = stableUserData ? DeltaNetComponentMapping.fromComponents(stableUserData.components) : { position: { x: 0, y: 0, z: 0 }, rotation: { eulerY: 0 }, state: 0 };
888
+ existingUpdate = { components };
889
+ updatedUsers.set(connId, existingUpdate);
890
+ }
1364
891
  let existingUserStateUpdate = existingUpdate.userState;
1365
892
  if (!existingUserStateUpdate) {
1366
893
  existingUserStateUpdate = {};
@@ -1372,37 +899,48 @@ var UserNetworkingClient = class {
1372
899
  "STATE_INTERNAL_CONNECTION_ID is not expected to change in state updates"
1373
900
  );
1374
901
  break;
1375
- case STATE_USERNAME:
902
+ case STATE_USER_ID: {
903
+ const persistentUserId = DeltaNetComponentMapping.persistentUserIdFromBytes(update.state);
904
+ if (persistentUserId) {
905
+ profile.userId = persistentUserId;
906
+ existingUserStateUpdate.userId = persistentUserId;
907
+ }
908
+ break;
909
+ }
910
+ case STATE_USERNAME: {
1376
911
  const username = DeltaNetComponentMapping.usernameFromBytes(update.state);
1377
912
  if (username) {
1378
913
  profile.username = username;
1379
914
  existingUserStateUpdate.username = username;
1380
915
  }
1381
916
  break;
1382
- case STATE_CHARACTER_DESCRIPTION:
917
+ }
918
+ case STATE_CHARACTER_DESCRIPTION: {
1383
919
  const characterDescription = DeltaNetComponentMapping.characterDescriptionFromBytes(
1384
920
  update.state
1385
921
  );
1386
922
  profile.characterDescription = characterDescription;
1387
923
  existingUserStateUpdate.characterDescription = characterDescription;
1388
924
  break;
1389
- case STATE_COLORS:
925
+ }
926
+ case STATE_COLORS: {
1390
927
  const colors = DeltaNetComponentMapping.decodeColors(update.state, this.logger);
1391
928
  profile.colors = colors;
1392
929
  existingUserStateUpdate.colors = colors;
1393
930
  break;
931
+ }
1394
932
  default:
1395
933
  this.logger.warn(`Unknown state ID: ${update.stateId}`);
1396
934
  }
1397
935
  }
1398
936
  return {
1399
- removedUserIds,
1400
- addedUserIds,
937
+ removedConnectionIds,
938
+ addedConnectionIds,
1401
939
  updatedUsers
1402
940
  };
1403
941
  }
1404
942
  sendUpdate(update) {
1405
- if (!this.isAuthenticated || this.userId === null) {
943
+ if (!this.isAuthenticated || this.connectionId === null) {
1406
944
  this.pendingUpdate = update;
1407
945
  return;
1408
946
  }
@@ -1410,14 +948,14 @@ var UserNetworkingClient = class {
1410
948
  this.deltaNetClient.setUserComponents(components, /* @__PURE__ */ new Map());
1411
949
  }
1412
950
  sendCustomMessage(customType, contents) {
1413
- if (!this.isAuthenticated || this.userId === null) {
951
+ if (!this.isAuthenticated || this.connectionId === null) {
1414
952
  this.logger.warn("Cannot send custom message before authentication");
1415
953
  return;
1416
954
  }
1417
955
  this.deltaNetClient.sendCustomMessage(customType, contents);
1418
956
  }
1419
957
  updateUsername(username) {
1420
- if (!this.isAuthenticated || this.userId === null) {
958
+ if (!this.isAuthenticated || this.connectionId === null) {
1421
959
  return;
1422
960
  }
1423
961
  this.userState.username = username;
@@ -1425,7 +963,7 @@ var UserNetworkingClient = class {
1425
963
  this.deltaNetClient.setUserComponents(/* @__PURE__ */ new Map(), states);
1426
964
  }
1427
965
  updateCharacterDescription(characterDescription) {
1428
- if (!this.isAuthenticated || this.userId === null) {
966
+ if (!this.isAuthenticated || this.connectionId === null) {
1429
967
  return;
1430
968
  }
1431
969
  this.userState.characterDescription = characterDescription;
@@ -1433,7 +971,7 @@ var UserNetworkingClient = class {
1433
971
  this.deltaNetClient.setUserComponents(/* @__PURE__ */ new Map(), states);
1434
972
  }
1435
973
  updateColors(colors) {
1436
- if (!this.isAuthenticated || this.userId === null) {
974
+ if (!this.isAuthenticated || this.connectionId === null) {
1437
975
  return;
1438
976
  }
1439
977
  this.userState.colors = colors;
@@ -1446,49 +984,31 @@ var UserNetworkingClient = class {
1446
984
  }
1447
985
  };
1448
986
 
987
+ // src/UserNetworkingMessages.ts
988
+ import { DeltaNetServerError as DeltaNetServerError2 } from "@mml-io/delta-net-server";
989
+ var UserNetworkingServerError = class extends DeltaNetServerError2 {
990
+ };
991
+
1449
992
  // src/index.ts
1450
- import {
1451
- DeltaNetV01ServerErrors as DeltaNetV01ServerErrors2,
1452
- deltaNetProtocolSubProtocol_v0_1
1453
- } from "@mml-io/delta-net-protocol";
993
+ import { DeltaNetServerErrors as DeltaNetServerErrors2 } from "@mml-io/delta-net-protocol";
1454
994
  export {
1455
995
  COMPONENT_POSITION_X,
1456
996
  COMPONENT_POSITION_Y,
1457
997
  COMPONENT_POSITION_Z,
1458
- COMPONENT_ROTATION_W,
1459
998
  COMPONENT_ROTATION_Y,
1460
999
  COMPONENT_STATE,
1461
1000
  DeltaNetComponentMapping,
1462
- DeltaNetV01ServerErrors2 as DeltaNetV01ServerErrors,
1463
- FROM_CLIENT_CHAT_MESSAGE_TYPE,
1464
- FROM_SERVER_CHAT_MESSAGE_TYPE,
1465
- LEGACY_USER_NETWORKING_AUTHENTICATION_FAILED_ERROR_TYPE,
1466
- LEGACY_USER_NETWORKING_CONNECTION_LIMIT_REACHED_ERROR_TYPE,
1467
- LEGACY_USER_NETWORKING_DISCONNECTED_MESSAGE_TYPE,
1468
- LEGACY_USER_NETWORKING_IDENTITY_MESSAGE_TYPE,
1469
- LEGACY_USER_NETWORKING_PING_MESSAGE_TYPE,
1470
- LEGACY_USER_NETWORKING_PONG_MESSAGE_TYPE,
1471
- LEGACY_USER_NETWORKING_SERVER_BROADCAST_MESSAGE_TYPE,
1472
- LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE,
1473
- LEGACY_USER_NETWORKING_SERVER_SHUTDOWN_ERROR_TYPE,
1474
- LEGACY_USER_NETWORKING_UNKNOWN_ERROR,
1475
- LEGACY_USER_NETWORKING_USER_AUTHENTICATE_MESSAGE_TYPE,
1476
- LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE,
1477
- LEGACY_USER_NETWORKING_USER_UPDATE_MESSAGE_TYPE,
1478
- SERVER_BROADCAST_MESSAGE_TYPE,
1001
+ DeltaNetServerErrors2 as DeltaNetServerErrors,
1479
1002
  STATE_CHARACTER_DESCRIPTION,
1480
1003
  STATE_COLORS,
1481
1004
  STATE_INTERNAL_CONNECTION_ID,
1482
1005
  STATE_USERNAME,
1006
+ STATE_USER_ID,
1483
1007
  UserNetworkingClient,
1484
1008
  UserNetworkingConsoleLogger,
1485
1009
  UserNetworkingServer,
1486
1010
  UserNetworkingServerError,
1487
1011
  WebsocketStatus,
1488
- deltaNetProtocolSubProtocol_v0_1,
1489
- parseClientChatMessage,
1490
- parseServerBroadcastMessage,
1491
- parseServerChatMessage,
1492
1012
  positionMultiplier,
1493
1013
  rotationMultiplier
1494
1014
  };