@mml-io/3d-web-user-networking 0.0.0-experimental-4fa4c42-20250715 → 0.0.0-experimental-d4f4aa0-20250721

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/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2023 Improbable MV Limited
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -1,5 +1,6 @@
1
1
  import { UserNetworkingClientUpdate } from "./types";
2
2
  import { UserData } from "./UserData";
3
+ import { UserNetworkingLogger } from "./UserNetworkingLogger";
3
4
  import { CharacterDescription } from "./UserNetworkingMessages";
4
5
  export declare const COMPONENT_POSITION_X = 1;
5
6
  export declare const COMPONENT_POSITION_Y = 2;
@@ -43,15 +44,15 @@ export declare class DeltaNetComponentMapping {
43
44
  */
44
45
  static toSingleState(stateId: number, value: any): Map<number, Uint8Array>;
45
46
  static encodeColors(colors: Array<[number, number, number]>): Uint8Array;
46
- static decodeColors(colors: Uint8Array): Array<[number, number, number]>;
47
- static fromUserStates(states: Map<number, Uint8Array>): UserData;
47
+ static decodeColors(colors: Uint8Array, logger: UserNetworkingLogger): Array<[number, number, number]>;
48
+ static fromUserStates(states: Map<number, Uint8Array>, logger: UserNetworkingLogger): UserData;
48
49
  static userIdFromBytes(bytes: Uint8Array): number | null;
49
50
  static usernameFromBytes(bytes: Uint8Array): string | null;
50
51
  static characterDescriptionFromBytes(bytes: Uint8Array): CharacterDescription | null;
51
52
  /**
52
53
  * Decode binary states back to username and character description
53
54
  */
54
- static fromStates(states: Map<number, Uint8Array>): {
55
+ static fromStates(states: Map<number, Uint8Array>, logger: UserNetworkingLogger): {
55
56
  userId: number | null;
56
57
  } & UserData;
57
58
  }
@@ -1,5 +1,6 @@
1
1
  import { UserNetworkingClientUpdate, WebsocketFactory, WebsocketStatus } from "./types";
2
2
  import { UserData } from "./UserData";
3
+ import { UserNetworkingLogger } from "./UserNetworkingLogger";
3
4
  import { CharacterDescription } from "./UserNetworkingMessages";
4
5
  export type UserNetworkingClientConfig = {
5
6
  url: string;
@@ -29,6 +30,7 @@ export type NetworkUpdate = {
29
30
  };
30
31
  export declare class UserNetworkingClient {
31
32
  private config;
33
+ private logger;
32
34
  private deltaNetClient;
33
35
  private deltaNetState;
34
36
  private userId;
@@ -38,7 +40,7 @@ export declare class UserNetworkingClient {
38
40
  private userProfiles;
39
41
  private isAuthenticated;
40
42
  private pendingUpdate;
41
- constructor(config: UserNetworkingClientConfig, initialUserState?: UserData, initialUpdate?: UserNetworkingClientUpdate);
43
+ constructor(config: UserNetworkingClientConfig, initialUserState?: UserData, initialUpdate?: UserNetworkingClientUpdate, logger?: UserNetworkingLogger);
42
44
  private reset;
43
45
  private sendInitialAuthentication;
44
46
  private processNetworkUpdate;
@@ -0,0 +1,15 @@
1
+ export type UserNetworkingServerLogFunction = (...args: Array<any>) => void;
2
+ export type UserNetworkingLogger = {
3
+ trace: UserNetworkingServerLogFunction;
4
+ debug: UserNetworkingServerLogFunction;
5
+ info: UserNetworkingServerLogFunction;
6
+ warn: UserNetworkingServerLogFunction;
7
+ error: UserNetworkingServerLogFunction;
8
+ };
9
+ export declare class UserNetworkingConsoleLogger implements UserNetworkingLogger {
10
+ trace(...args: Array<any>): void;
11
+ debug(...args: Array<any>): void;
12
+ info(...args: Array<any>): void;
13
+ warn(...args: Array<any>): void;
14
+ error(...args: Array<any>): void;
15
+ }
@@ -1,6 +1,7 @@
1
1
  import { DeltaNetV01Connection } from "@mml-io/delta-net-server";
2
- import { LegacyUserIdentity } from "./legacy/LegacyUserNetworkingMessages";
2
+ import { LegacyUserIdentity, LegacyCharacterDescription } from "./legacy/LegacyUserNetworkingMessages";
3
3
  import { UserData } from "./UserData";
4
+ import { UserNetworkingLogger } from "./UserNetworkingLogger";
4
5
  import { UserNetworkingServerError, CharacterDescription } from "./UserNetworkingMessages";
5
6
  export type UserNetworkingServerClient = {
6
7
  socket: WebSocket;
@@ -11,20 +12,20 @@ export type UserNetworkingServerClient = {
11
12
  };
12
13
  export type UserNetworkingServerOptions = {
13
14
  legacyAdapterEnabled?: boolean;
14
- connectionLimit?: number;
15
15
  onClientConnect: (clientId: number, sessionToken: string, userIdentity?: UserData) => Promise<UserData | true | Error> | UserData | true | Error;
16
16
  onClientUserIdentityUpdate: (clientId: number, userIdentity: UserData) => Promise<UserData | null | false | true | Error> | UserData | null | false | true | Error;
17
17
  onClientDisconnect: (clientId: number) => void;
18
18
  };
19
19
  export declare class UserNetworkingServer {
20
20
  private options;
21
+ private logger;
21
22
  private deltaNetServer;
22
23
  private authenticatedClientsById;
23
24
  private tickInterval;
24
25
  private legacyAdapter;
25
26
  private updatedUserProfilesInTick;
26
- constructor(options: UserNetworkingServerOptions);
27
- getCharacterDescription(connectionId: number): import("./legacy/LegacyUserNetworkingMessages").LegacyCharacterDescription;
27
+ constructor(options: UserNetworkingServerOptions, logger?: UserNetworkingLogger);
28
+ getCharacterDescription(connectionId: number): LegacyCharacterDescription;
28
29
  getUsername(connectionId: number): string;
29
30
  getLegacyClientId(): number;
30
31
  hasCapacityForLegacyClient(): boolean;
package/build/index.d.ts CHANGED
@@ -5,4 +5,5 @@ export * from "./types";
5
5
  export * from "./UserNetworkingMessages";
6
6
  export * from "./legacy/LegacyUserNetworkingMessages";
7
7
  export * from "./DeltaNetComponentMapping";
8
+ export * from "./UserNetworkingLogger";
8
9
  export { DeltaNetV01ServerErrors, deltaNetProtocolSubProtocol_v0_1, } from "@mml-io/delta-net-protocol";
package/build/index.js CHANGED
@@ -149,7 +149,7 @@ var DeltaNetComponentMapping = class _DeltaNetComponentMapping {
149
149
  }
150
150
  return bufferWriter.getBuffer();
151
151
  }
152
- static decodeColors(colors) {
152
+ static decodeColors(colors, logger) {
153
153
  if (colors.byteLength === 0) {
154
154
  return [];
155
155
  }
@@ -166,17 +166,17 @@ var DeltaNetComponentMapping = class _DeltaNetComponentMapping {
166
166
  }
167
167
  return colorsArray;
168
168
  } catch (e) {
169
- console.error("Error decoding colors", colors, e);
169
+ logger.error("Error decoding colors", colors, e);
170
170
  return [];
171
171
  }
172
172
  }
173
- static fromUserStates(states) {
173
+ static fromUserStates(states, logger) {
174
174
  const usernameBytes = states.get(STATE_USERNAME);
175
175
  const username = usernameBytes ? _DeltaNetComponentMapping.usernameFromBytes(usernameBytes) : null;
176
176
  const characterDescBytes = states.get(STATE_CHARACTER_DESCRIPTION);
177
177
  const characterDescription = characterDescBytes ? _DeltaNetComponentMapping.characterDescriptionFromBytes(characterDescBytes) : null;
178
178
  const colorsBytes = states.get(STATE_COLORS);
179
- const colorsArray = colorsBytes ? _DeltaNetComponentMapping.decodeColors(colorsBytes) : [];
179
+ const colorsArray = colorsBytes ? _DeltaNetComponentMapping.decodeColors(colorsBytes, logger) : [];
180
180
  return { username, characterDescription, colors: colorsArray };
181
181
  }
182
182
  static userIdFromBytes(bytes) {
@@ -201,14 +201,14 @@ var DeltaNetComponentMapping = class _DeltaNetComponentMapping {
201
201
  /**
202
202
  * Decode binary states back to username and character description
203
203
  */
204
- static fromStates(states) {
204
+ static fromStates(states, logger) {
205
205
  const userIdBytes = states.get(STATE_INTERNAL_CONNECTION_ID);
206
206
  let userId = null;
207
207
  if (userIdBytes) {
208
208
  const reader = new BufferReader(userIdBytes);
209
209
  userId = reader.readUVarint(false);
210
210
  }
211
- const userStates = _DeltaNetComponentMapping.fromUserStates(states);
211
+ const userStates = _DeltaNetComponentMapping.fromUserStates(states, logger);
212
212
  return { userId, ...userStates };
213
213
  }
214
214
  };
@@ -320,19 +320,20 @@ function toArrayBuffer(buffer) {
320
320
  }
321
321
  var WebSocketOpenStatus = 1;
322
322
  var LegacyAdapter = class {
323
- constructor(userNetworkingServer, deltaNetServer) {
323
+ constructor(userNetworkingServer, deltaNetServer, logger) {
324
324
  this.userNetworkingServer = userNetworkingServer;
325
325
  this.deltaNetServer = deltaNetServer;
326
- this.allClientsById = /* @__PURE__ */ new Map();
327
- this.legacyAuthenticatedClientsById = /* @__PURE__ */ new Map();
326
+ this.logger = logger;
328
327
  }
328
+ allClientsById = /* @__PURE__ */ new Map();
329
+ legacyAuthenticatedClientsById = /* @__PURE__ */ new Map();
329
330
  broadcastMessage(broadcastType, broadcastPayload) {
330
331
  if (broadcastType !== SERVER_BROADCAST_MESSAGE_TYPE) {
331
332
  return;
332
333
  }
333
334
  const parsedPayload = parseServerBroadcastMessage(broadcastPayload);
334
335
  if (parsedPayload instanceof Error) {
335
- console.error("Error parsing server broadcast message", parsedPayload);
336
+ this.logger.error("Error parsing server broadcast message", parsedPayload);
336
337
  return;
337
338
  }
338
339
  const { broadcastType: broadcastTypeString, payload } = parsedPayload;
@@ -410,7 +411,7 @@ var LegacyAdapter = class {
410
411
  try {
411
412
  parsed = JSON.parse(message.data);
412
413
  } catch (e) {
413
- console.error("Error parsing JSON message", message, e);
414
+ this.logger.error("Error parsing JSON message", message, e);
414
415
  return;
415
416
  }
416
417
  if (!client.authenticatedUser) {
@@ -420,7 +421,7 @@ var LegacyAdapter = class {
420
421
  return;
421
422
  }
422
423
  if (!authResult) {
423
- console.error(`Client-id ${client.id} user_auth failed`, authResult);
424
+ this.logger.error(`Client-id ${client.id} user_auth failed`, authResult);
424
425
  const serverError = JSON.stringify({
425
426
  type: LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE,
426
427
  errorType: LEGACY_USER_NETWORKING_AUTHENTICATION_FAILED_ERROR_TYPE,
@@ -513,7 +514,7 @@ var LegacyAdapter = class {
513
514
  }
514
515
  });
515
516
  } else {
516
- console.error(`Unhandled message pre-auth: ${JSON.stringify(parsed)}`);
517
+ this.logger.error(`Unhandled message pre-auth: ${JSON.stringify(parsed)}`);
517
518
  socket.close();
518
519
  }
519
520
  } else {
@@ -525,12 +526,12 @@ var LegacyAdapter = class {
525
526
  this.handleUserUpdate(id, parsed);
526
527
  break;
527
528
  default:
528
- console.error(`Unhandled message: ${JSON.stringify(parsed)}`);
529
+ this.logger.error(`Unhandled message: ${JSON.stringify(parsed)}`);
529
530
  }
530
531
  }
531
532
  }
532
533
  } catch (e) {
533
- console.error("Error handling message", message, e);
534
+ this.logger.error("Error handling message", message, e);
534
535
  socket.send(
535
536
  JSON.stringify({
536
537
  type: LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE,
@@ -569,16 +570,16 @@ var LegacyAdapter = class {
569
570
  resolvedUserData = userData;
570
571
  }
571
572
  if (resolvedUserData instanceof Error) {
572
- console.error(`Client-id ${client.id} user_auth failed`, resolvedUserData);
573
+ this.logger.error(`Client-id ${client.id} user_auth failed`, resolvedUserData);
573
574
  return false;
574
575
  } else if (resolvedUserData === true) {
575
- console.error(`Client-id ${client.id} user_auth failed`, resolvedUserData);
576
+ this.logger.error(`Client-id ${client.id} user_auth failed`, resolvedUserData);
576
577
  resolvedUserData = credentials.userIdentity;
577
578
  } else {
578
579
  resolvedUserData = resolvedUserData;
579
580
  }
580
581
  if (resolvedUserData === null) {
581
- console.error(`Client-id ${client.id} user_auth unauthorized and ignored`);
582
+ this.logger.error(`Client-id ${client.id} user_auth unauthorized and ignored`);
582
583
  return false;
583
584
  }
584
585
  return resolvedUserData;
@@ -595,7 +596,7 @@ var LegacyAdapter = class {
595
596
  async handleUserUpdate(clientId, message) {
596
597
  const client = this.legacyAuthenticatedClientsById.get(clientId);
597
598
  if (!client) {
598
- console.error(`Client-id ${clientId} user_update ignored, client not found`);
599
+ this.logger.error(`Client-id ${clientId} user_update ignored, client not found`);
599
600
  return;
600
601
  }
601
602
  const authorizedUserData = message.userIdentity;
@@ -606,7 +607,7 @@ var LegacyAdapter = class {
606
607
  resolvedAuthorizedUserData = authorizedUserData;
607
608
  }
608
609
  if (!resolvedAuthorizedUserData) {
609
- console.warn(`Client-id ${clientId} user_update unauthorized and ignored`);
610
+ this.logger.warn(`Client-id ${clientId} user_update unauthorized and ignored`);
610
611
  return;
611
612
  }
612
613
  this.internalUpdateUser(clientId, resolvedAuthorizedUserData);
@@ -649,14 +650,6 @@ var LegacyAdapter = class {
649
650
  }
650
651
  }
651
652
  }
652
- for (const [clientId, client] of this.legacyAuthenticatedClientsById) {
653
- const encodedUpdate = LegacyUserNetworkingCodec.encodeUpdate(client.update);
654
- for (const [otherClientId, otherClient] of this.legacyAuthenticatedClientsById) {
655
- if (otherClientId !== clientId && otherClient.socket.readyState === WebSocketOpenStatus) {
656
- otherClient.socket.send(encodedUpdate);
657
- }
658
- }
659
- }
660
653
  const allUsers = this.deltaNetServer.dangerouslyGetConnectionsToComponentIndex();
661
654
  for (const [connectionId, componentIndex] of allUsers) {
662
655
  const x = this.deltaNetServer.getComponentValue(COMPONENT_POSITION_X, componentIndex) / positionMultiplier;
@@ -689,13 +682,30 @@ var LegacyAdapter = class {
689
682
  }
690
683
  };
691
684
 
685
+ // src/UserNetworkingLogger.ts
686
+ var UserNetworkingConsoleLogger = class {
687
+ trace(...args) {
688
+ console.trace(...args);
689
+ }
690
+ debug(...args) {
691
+ console.debug(...args);
692
+ }
693
+ info(...args) {
694
+ console.info(...args);
695
+ }
696
+ warn(...args) {
697
+ console.warn(...args);
698
+ }
699
+ error(...args) {
700
+ console.error(...args);
701
+ }
702
+ };
703
+
692
704
  // src/UserNetworkingServer.ts
693
705
  var UserNetworkingServer = class {
694
- constructor(options) {
706
+ constructor(options, logger = new UserNetworkingConsoleLogger()) {
695
707
  this.options = options;
696
- this.authenticatedClientsById = /* @__PURE__ */ new Map();
697
- this.legacyAdapter = null;
698
- this.updatedUserProfilesInTick = /* @__PURE__ */ new Set();
708
+ this.logger = logger;
699
709
  this.deltaNetServer = new DeltaNetServer({
700
710
  serverConnectionIdStateId: 0,
701
711
  onJoiner: (joiner) => {
@@ -715,7 +725,7 @@ var UserNetworkingServer = class {
715
725
  }
716
726
  });
717
727
  if (this.options.legacyAdapterEnabled) {
718
- this.legacyAdapter = new LegacyAdapter(this, this.deltaNetServer);
728
+ this.legacyAdapter = new LegacyAdapter(this, this.deltaNetServer, this.logger);
719
729
  }
720
730
  this.tickInterval = setInterval(() => {
721
731
  const { removedIds, addedIds } = this.deltaNetServer.tick();
@@ -725,6 +735,11 @@ var UserNetworkingServer = class {
725
735
  }
726
736
  }, 50);
727
737
  }
738
+ deltaNetServer;
739
+ authenticatedClientsById = /* @__PURE__ */ new Map();
740
+ tickInterval;
741
+ legacyAdapter = null;
742
+ updatedUserProfilesInTick = /* @__PURE__ */ new Set();
728
743
  getCharacterDescription(connectionId) {
729
744
  var _a;
730
745
  const client = this.authenticatedClientsById.get(connectionId);
@@ -733,7 +748,7 @@ var UserNetworkingServer = class {
733
748
  getUsername(connectionId) {
734
749
  var _a, _b;
735
750
  const client = this.authenticatedClientsById.get(connectionId);
736
- console.log("getUsername", connectionId, (_a = client == null ? void 0 : client.authenticatedUser) == null ? void 0 : _a.username);
751
+ this.logger.info("getUsername", connectionId, (_a = client == null ? void 0 : client.authenticatedUser) == null ? void 0 : _a.username);
737
752
  return ((_b = client == null ? void 0 : client.authenticatedUser) == null ? void 0 : _b.username) ?? "";
738
753
  }
739
754
  getLegacyClientId() {
@@ -750,7 +765,7 @@ var UserNetworkingServer = class {
750
765
  });
751
766
  }
752
767
  setAuthenticatedLegacyClientConnection(clientId, webSocket, userData) {
753
- console.log("setAuthenticatedLegacyClientConnection", clientId, userData);
768
+ this.logger.info("setAuthenticatedLegacyClientConnection", clientId, userData);
754
769
  const authenticatedClient = {
755
770
  id: clientId,
756
771
  socket: webSocket,
@@ -768,7 +783,10 @@ var UserNetworkingServer = class {
768
783
  const clientId = deltaNetConnection.internalConnectionId;
769
784
  const updatedStates = update.states;
770
785
  const updatedStatesMap = new Map(updatedStates);
771
- const updatedUserData = DeltaNetComponentMapping.fromUserStates(updatedStatesMap);
786
+ const updatedUserData = DeltaNetComponentMapping.fromUserStates(
787
+ updatedStatesMap,
788
+ this.logger
789
+ );
772
790
  const existingClient = this.authenticatedClientsById.get(clientId);
773
791
  if (!existingClient) {
774
792
  return new DeltaNetServerError2(
@@ -881,7 +899,7 @@ var UserNetworkingServer = class {
881
899
  const states = joiner.states;
882
900
  const clientId = joiner.internalConnectionId;
883
901
  const statesMap = new Map(states);
884
- const userData = DeltaNetComponentMapping.fromUserStates(statesMap);
902
+ const userData = DeltaNetComponentMapping.fromUserStates(statesMap, this.logger);
885
903
  return this.handleDeltaNetAuthentication(
886
904
  clientId,
887
905
  webSocket,
@@ -889,11 +907,12 @@ var UserNetworkingServer = class {
889
907
  joiner.token,
890
908
  userData
891
909
  ).then((authResult) => {
910
+ var _a;
892
911
  if (!authResult.success) {
893
- console.warn(`Authentication failed for client ID: ${clientId}`);
912
+ this.logger.warn(`Authentication failed for client ID: ${clientId}`, authResult.error);
894
913
  return new DeltaNetServerError2(
895
914
  DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
896
- "Authentication failed",
915
+ ((_a = authResult.error) == null ? void 0 : _a.message) || "Authentication failed",
897
916
  false
898
917
  );
899
918
  } else {
@@ -903,7 +922,7 @@ var UserNetworkingServer = class {
903
922
  };
904
923
  }
905
924
  }).catch((error) => {
906
- console.error(`Authentication error for client ID: ${clientId}:`, error);
925
+ this.logger.error(`Authentication error for client ID: ${clientId}:`, error);
907
926
  return new DeltaNetServerError2(
908
927
  DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
909
928
  "Authentication error",
@@ -930,7 +949,7 @@ var UserNetworkingServer = class {
930
949
  if (customMessage.customType === FROM_CLIENT_CHAT_MESSAGE_TYPE) {
931
950
  const chatMessage = parseClientChatMessage(customMessage.contents);
932
951
  if (chatMessage instanceof Error) {
933
- console.error(`Invalid chat message from client ${clientId}:`, chatMessage);
952
+ this.logger.error(`Invalid chat message from client ${clientId}:`, chatMessage);
934
953
  } else {
935
954
  const serverChatMessage = {
936
955
  fromUserId: clientId,
@@ -943,36 +962,34 @@ var UserNetworkingServer = class {
943
962
  }
944
963
  }
945
964
  } else {
946
- console.warn(`Custom message from unauthenticated client ${clientId} - ignoring`);
965
+ this.logger.warn(`Custom message from unauthenticated client ${clientId} - ignoring`);
947
966
  }
948
967
  }
949
968
  async handleDeltaNetAuthentication(clientId, webSocket, deltaNetConnection, sessionToken, userIdentity) {
950
969
  try {
951
- let userData = deltaNetConnection.isObserver ? null : await this.options.onClientConnect(clientId, sessionToken, userIdentity);
952
- if (!deltaNetConnection.isObserver && !userData) {
953
- console.warn(`Authentication failed for client ${clientId} - no user data returned`);
954
- return { success: false };
955
- }
956
- if (this.options.connectionLimit !== void 0 && this.authenticatedClientsById.size >= this.options.connectionLimit) {
970
+ let onClientConnectReturn = deltaNetConnection.isObserver ? null : await this.options.onClientConnect(clientId, sessionToken, userIdentity);
971
+ if (!deltaNetConnection.isObserver && !onClientConnectReturn) {
972
+ this.logger.warn(`Authentication failed for client ${clientId} - no user data returned`);
957
973
  return { success: false };
958
974
  }
959
- if (userData instanceof Error) {
960
- return { success: false, error: userData };
975
+ if (onClientConnectReturn instanceof Error) {
976
+ return { success: false, error: onClientConnectReturn };
961
977
  }
962
- if (userData === true) {
963
- userData = userIdentity;
978
+ if (onClientConnectReturn === true) {
979
+ onClientConnectReturn = userIdentity;
964
980
  }
981
+ const authenticatedUser = onClientConnectReturn;
965
982
  const authenticatedClient = {
966
983
  id: clientId,
967
984
  socket: webSocket,
968
985
  lastPong: Date.now(),
969
- authenticatedUser: userData,
986
+ authenticatedUser,
970
987
  deltaNetConnection
971
988
  };
972
989
  this.authenticatedClientsById.set(clientId, authenticatedClient);
973
990
  let stateOverrides = [];
974
- if (userData) {
975
- const officialStates = DeltaNetComponentMapping.toStates(userData);
991
+ if (onClientConnectReturn) {
992
+ const officialStates = DeltaNetComponentMapping.toStates(onClientConnectReturn);
976
993
  stateOverrides = Array.from(officialStates.entries());
977
994
  }
978
995
  return {
@@ -980,7 +997,7 @@ var UserNetworkingServer = class {
980
997
  stateOverrides
981
998
  };
982
999
  } catch (error) {
983
- console.error("Authentication error:", error);
1000
+ this.logger.error("Authentication error:", error);
984
1001
  return { success: false };
985
1002
  }
986
1003
  }
@@ -1006,7 +1023,7 @@ var UserNetworkingServer = class {
1006
1023
  }
1007
1024
  }
1008
1025
  updateUserCharacter(clientId, userData) {
1009
- console.log("updateUserCharacter", clientId, userData);
1026
+ this.logger.info("updateUserCharacter", clientId, userData);
1010
1027
  this.internalUpdateUser(clientId, userData);
1011
1028
  }
1012
1029
  updateUserUsername(clientId, username) {
@@ -1098,7 +1115,7 @@ var UserNetworkingServer = class {
1098
1115
  if (!client) {
1099
1116
  throw new Error(`internalUpdateUser - client not found for clientId ${clientId}`);
1100
1117
  }
1101
- console.log("internalUpdateUser", clientId, userData);
1118
+ this.logger.info("internalUpdateUser", clientId, userData);
1102
1119
  this.updatedUserProfilesInTick.add(clientId);
1103
1120
  client.authenticatedUser = {
1104
1121
  ...client.authenticatedUser,
@@ -1149,18 +1166,9 @@ var WebsocketStatus = /* @__PURE__ */ ((WebsocketStatus2) => {
1149
1166
 
1150
1167
  // src/UserNetworkingClient.ts
1151
1168
  var UserNetworkingClient = class {
1152
- constructor(config, initialUserState, initialUpdate) {
1169
+ constructor(config, initialUserState, initialUpdate, logger = new UserNetworkingConsoleLogger()) {
1153
1170
  this.config = config;
1154
- this.userId = null;
1155
- this.userIndex = null;
1156
- this.userState = {
1157
- username: null,
1158
- characterDescription: null,
1159
- colors: null
1160
- };
1161
- this.stableIdToUserId = /* @__PURE__ */ new Map();
1162
- this.userProfiles = /* @__PURE__ */ new Map();
1163
- this.isAuthenticated = false;
1171
+ this.logger = logger;
1164
1172
  this.pendingUpdate = initialUpdate ?? {
1165
1173
  position: { x: 0, y: 0, z: 0 },
1166
1174
  rotation: { quaternionY: 0, quaternionW: 1 },
@@ -1197,7 +1205,7 @@ var UserNetworkingClient = class {
1197
1205
  this.isAuthenticated = true;
1198
1206
  this.config.assignedIdentity(this.userId);
1199
1207
  } else {
1200
- console.error(
1208
+ this.logger.error(
1201
1209
  `Invalid userIndex ${this.userIndex}, userIds length: ${userIds.length}`
1202
1210
  );
1203
1211
  }
@@ -1217,7 +1225,7 @@ var UserNetworkingClient = class {
1217
1225
  this.deltaNetState.setLocalIndex(userIndex.userIndex);
1218
1226
  },
1219
1227
  onError: (errorType, errorMessage, retryable) => {
1220
- console.error(
1228
+ this.logger.error(
1221
1229
  "DeltaNet error:",
1222
1230
  errorType,
1223
1231
  "errorMessage:",
@@ -1231,7 +1239,7 @@ var UserNetworkingClient = class {
1231
1239
  });
1232
1240
  },
1233
1241
  onWarning: (warning) => {
1234
- console.warn("DeltaNet warning:", warning);
1242
+ this.logger.warn("DeltaNet warning:", warning);
1235
1243
  },
1236
1244
  onServerCustom: (customType, contents) => {
1237
1245
  var _a, _b;
@@ -1265,6 +1273,19 @@ var UserNetworkingClient = class {
1265
1273
  }
1266
1274
  );
1267
1275
  }
1276
+ deltaNetClient;
1277
+ deltaNetState;
1278
+ userId = null;
1279
+ userIndex = null;
1280
+ userState = {
1281
+ username: null,
1282
+ characterDescription: null,
1283
+ colors: null
1284
+ };
1285
+ stableIdToUserId = /* @__PURE__ */ new Map();
1286
+ userProfiles = /* @__PURE__ */ new Map();
1287
+ isAuthenticated = false;
1288
+ pendingUpdate;
1268
1289
  reset() {
1269
1290
  this.deltaNetState.reset();
1270
1291
  this.userProfiles.clear();
@@ -1305,7 +1326,7 @@ var UserNetworkingClient = class {
1305
1326
  throw new Error(`Failed to extract userId from bytes for stableId ${stableId}`);
1306
1327
  }
1307
1328
  this.stableIdToUserId.set(stableId, userId);
1308
- const newProfile = DeltaNetComponentMapping.fromStates(stableUserData.states);
1329
+ const newProfile = DeltaNetComponentMapping.fromStates(stableUserData.states, this.logger);
1309
1330
  this.userProfiles.set(userId, newProfile);
1310
1331
  const clientUpdate = DeltaNetComponentMapping.fromComponents(stableUserData.components);
1311
1332
  addedUserIds.set(userId, {
@@ -1339,7 +1360,7 @@ var UserNetworkingClient = class {
1339
1360
  }
1340
1361
  const profile = this.userProfiles.get(userId);
1341
1362
  if (!profile) {
1342
- console.warn(`No profile found for user ${userId}, skipping update`);
1363
+ this.logger.warn(`No profile found for user ${userId}, skipping update`);
1343
1364
  continue;
1344
1365
  }
1345
1366
  const existingUpdate = updatedUsers.get(userId);
@@ -1350,7 +1371,9 @@ var UserNetworkingClient = class {
1350
1371
  }
1351
1372
  switch (update.stateId) {
1352
1373
  case STATE_INTERNAL_CONNECTION_ID:
1353
- console.error("STATE_INTERNAL_CONNECTION_ID is not expected to change in state updates");
1374
+ this.logger.error(
1375
+ "STATE_INTERNAL_CONNECTION_ID is not expected to change in state updates"
1376
+ );
1354
1377
  break;
1355
1378
  case STATE_USERNAME:
1356
1379
  const username = DeltaNetComponentMapping.usernameFromBytes(update.state);
@@ -1367,12 +1390,12 @@ var UserNetworkingClient = class {
1367
1390
  existingUserStateUpdate.characterDescription = characterDescription;
1368
1391
  break;
1369
1392
  case STATE_COLORS:
1370
- const colors = DeltaNetComponentMapping.decodeColors(update.state);
1393
+ const colors = DeltaNetComponentMapping.decodeColors(update.state, this.logger);
1371
1394
  profile.colors = colors;
1372
1395
  existingUserStateUpdate.colors = colors;
1373
1396
  break;
1374
1397
  default:
1375
- console.warn(`Unknown state ID: ${update.stateId}`);
1398
+ this.logger.warn(`Unknown state ID: ${update.stateId}`);
1376
1399
  }
1377
1400
  }
1378
1401
  return {
@@ -1391,7 +1414,7 @@ var UserNetworkingClient = class {
1391
1414
  }
1392
1415
  sendCustomMessage(customType, contents) {
1393
1416
  if (!this.isAuthenticated || this.userId === null) {
1394
- console.warn("Cannot send custom message before authentication");
1417
+ this.logger.warn("Cannot send custom message before authentication");
1395
1418
  return;
1396
1419
  }
1397
1420
  this.deltaNetClient.sendCustomMessage(customType, contents);
@@ -1461,6 +1484,7 @@ export {
1461
1484
  STATE_INTERNAL_CONNECTION_ID,
1462
1485
  STATE_USERNAME,
1463
1486
  UserNetworkingClient,
1487
+ UserNetworkingConsoleLogger,
1464
1488
  UserNetworkingServer,
1465
1489
  UserNetworkingServerError,
1466
1490
  WebsocketStatus,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/UserNetworkingServer.ts", "../src/DeltaNetComponentMapping.ts", "../src/UserNetworkingMessages.ts", "../src/legacy/LegacyUserNetworkingCodec.ts", "../src/legacy/LegacyUserNetworkingMessages.ts", "../src/legacy/LegacyAdapter.ts", "../src/UserNetworkingClient.ts", "../src/types.ts", "../src/index.ts"],
4
- "sourcesContent": ["import { encodeError, DeltaNetV01ServerErrors } from \"@mml-io/delta-net-protocol\";\nimport {\n DeltaNetServer,\n DeltaNetServerError,\n DeltaNetV01Connection,\n onComponentsUpdateOptions,\n onCustomMessageOptions,\n onJoinerOptions,\n onLeaveOptions,\n onStatesUpdateOptions,\n} from \"@mml-io/delta-net-server\";\n\nimport { DeltaNetComponentMapping } from \"./DeltaNetComponentMapping\";\nimport { LegacyAdapter } from \"./legacy/LegacyAdapter\";\nimport { LegacyUserIdentity } from \"./legacy/LegacyUserNetworkingMessages\";\nimport { UserData } from \"./UserData\";\nimport {\n FROM_CLIENT_CHAT_MESSAGE_TYPE,\n FROM_SERVER_CHAT_MESSAGE_TYPE,\n parseClientChatMessage,\n ServerChatMessage,\n UserNetworkingServerError,\n CharacterDescription,\n} from \"./UserNetworkingMessages\";\n\nexport type UserNetworkingServerClient = {\n socket: WebSocket;\n id: number;\n lastPong: number;\n authenticatedUser: UserData | null;\n // May be null for legacy clients\n deltaNetConnection: DeltaNetV01Connection | null;\n};\n\nexport type UserNetworkingServerOptions = {\n legacyAdapterEnabled?: boolean;\n connectionLimit?: number;\n onClientConnect: (\n clientId: number,\n sessionToken: string,\n userIdentity?: UserData,\n ) => Promise<UserData | true | Error> | UserData | true | Error;\n onClientUserIdentityUpdate: (\n clientId: number,\n userIdentity: UserData,\n ) => Promise<UserData | null | false | true | Error> | UserData | null | false | true | Error;\n onClientDisconnect: (clientId: number) => void;\n};\n\nexport class UserNetworkingServer {\n private deltaNetServer: DeltaNetServer;\n private authenticatedClientsById: Map<number, UserNetworkingServerClient> = new Map();\n private tickInterval: NodeJS.Timeout;\n private legacyAdapter: LegacyAdapter | null = null;\n private updatedUserProfilesInTick: Set<number> = new Set();\n\n constructor(private options: UserNetworkingServerOptions) {\n this.deltaNetServer = new DeltaNetServer({\n serverConnectionIdStateId: 0,\n onJoiner: (joiner: onJoinerOptions) => {\n return this.handleJoiner(joiner);\n },\n onLeave: (leave: onLeaveOptions) => {\n this.handleLeave(leave);\n },\n onComponentsUpdate: (update: onComponentsUpdateOptions) => {\n // TODO - potentially check that components are valid (e.g. rotation is 0 to 2pi)\n return; // No error\n },\n onStatesUpdate: (update: onStatesUpdateOptions) => {\n return this.handleStatesUpdate(update);\n },\n onCustomMessage: (customMessage: onCustomMessageOptions) => {\n this.handleCustomMessage(customMessage);\n },\n });\n if (this.options.legacyAdapterEnabled) {\n this.legacyAdapter = new LegacyAdapter(this, this.deltaNetServer);\n }\n\n // Start the deltanet server tick\n this.tickInterval = setInterval(() => {\n const { removedIds, addedIds } = this.deltaNetServer.tick();\n if (this.legacyAdapter) {\n this.legacyAdapter.sendUpdates(removedIds, addedIds, this.updatedUserProfilesInTick);\n this.updatedUserProfilesInTick.clear();\n }\n }, 50);\n }\n\n getCharacterDescription(\n connectionId: number,\n ): import(\"./legacy/LegacyUserNetworkingMessages\").LegacyCharacterDescription {\n const client = this.authenticatedClientsById.get(connectionId);\n return client?.authenticatedUser?.characterDescription ?? { mmlCharacterUrl: \"\" };\n }\n getUsername(connectionId: number): string {\n const client = this.authenticatedClientsById.get(connectionId);\n console.log(\"getUsername\", connectionId, client?.authenticatedUser?.username);\n return client?.authenticatedUser?.username ?? \"\";\n }\n\n public getLegacyClientId() {\n return this.deltaNetServer.getNextConnectionId();\n }\n\n public hasCapacityForLegacyClient() {\n return true;\n }\n\n public onLegacyClientConnect(\n id: number,\n sessionToken: string,\n userIdentity: LegacyUserIdentity | undefined,\n ): Promise<UserData | true | Error> | UserData | true | Error {\n return this.options.onClientConnect(id, sessionToken, {\n username: userIdentity?.username ?? null,\n characterDescription: userIdentity?.characterDescription ?? null,\n colors: null,\n });\n }\n\n public setAuthenticatedLegacyClientConnection(\n clientId: number,\n webSocket: WebSocket,\n userData: UserData,\n ) {\n console.log(\"setAuthenticatedLegacyClientConnection\", clientId, userData);\n const authenticatedClient: UserNetworkingServerClient = {\n id: clientId,\n socket: webSocket,\n lastPong: Date.now(),\n authenticatedUser: userData,\n deltaNetConnection: null,\n };\n this.authenticatedClientsById.set(clientId, authenticatedClient);\n }\n\n public onLegacyClientDisconnect(id: number) {\n this.options.onClientDisconnect(id);\n }\n\n private handleStatesUpdate(\n update: onStatesUpdateOptions,\n ):\n | DeltaNetServerError\n | void\n | { success: true; stateOverrides?: Array<[number, Uint8Array]> }\n | Promise<\n DeltaNetServerError | void | { success: true; stateOverrides?: Array<[number, Uint8Array]> }\n > {\n const deltaNetConnection = update.deltaNetV01Connection;\n const clientId = deltaNetConnection.internalConnectionId;\n const updatedStates = update.states;\n const updatedStatesMap = new Map<number, Uint8Array>(updatedStates);\n const updatedUserData: UserData = DeltaNetComponentMapping.fromUserStates(updatedStatesMap);\n\n const existingClient = this.authenticatedClientsById.get(clientId);\n if (!existingClient) {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User not authenticated - no client found\",\n false,\n );\n }\n const existingUserData = existingClient.authenticatedUser ?? {};\n const userData = {\n ...existingUserData,\n ...updatedUserData,\n };\n\n const res = this.options.onClientUserIdentityUpdate(clientId, userData);\n if (res instanceof Promise) {\n return res.then((res) => {\n if (!this.authenticatedClientsById.get(clientId)) {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User not authenticated - client disconnected\",\n false,\n );\n }\n\n if (res instanceof DeltaNetServerError) {\n return res;\n }\n if (res instanceof Error) {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User identity update failed\",\n false,\n );\n }\n if (res === null) {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User identity update failed\",\n false,\n );\n }\n if (res === false) {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User identity update failed\",\n false,\n );\n }\n if (!res || typeof res !== \"object\") {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User identity update failed\",\n false,\n );\n }\n\n this.updatedUserProfilesInTick.add(clientId);\n\n existingClient.authenticatedUser = {\n ...existingClient.authenticatedUser,\n ...res,\n };\n\n return {\n success: true,\n stateOverrides: Array.from(DeltaNetComponentMapping.toStates(res).entries()),\n };\n });\n }\n if (res instanceof DeltaNetServerError) {\n return res;\n }\n if (res instanceof Error) {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User identity update failed\",\n false,\n );\n }\n if (res === null) {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User identity update failed\",\n false,\n );\n }\n if (res === false) {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User identity update failed\",\n false,\n );\n }\n if (!res || typeof res !== \"object\") {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User identity update failed\",\n false,\n );\n }\n\n this.updatedUserProfilesInTick.add(clientId);\n\n existingClient.authenticatedUser = {\n ...existingClient.authenticatedUser,\n ...res,\n };\n\n return {\n success: true,\n stateOverrides: Array.from(DeltaNetComponentMapping.toStates(res).entries()),\n };\n }\n\n private handleJoiner(\n joiner: onJoinerOptions,\n ):\n | DeltaNetServerError\n | void\n | { success: true; stateOverrides?: Array<[number, Uint8Array]> }\n | Promise<\n DeltaNetServerError | void | { success: true; stateOverrides?: Array<[number, Uint8Array]> }\n > {\n const deltaNetConnection = joiner.deltaNetV01Connection as DeltaNetV01Connection;\n const webSocket = deltaNetConnection.webSocket as unknown as WebSocket;\n const states = joiner.states as Array<[number, Uint8Array]>;\n const clientId = joiner.internalConnectionId;\n\n const statesMap = new Map<number, Uint8Array>(states);\n const userData: UserData = DeltaNetComponentMapping.fromUserStates(statesMap);\n\n // Handle authentication and return the result with state overrides\n return this.handleDeltaNetAuthentication(\n clientId,\n webSocket,\n deltaNetConnection,\n joiner.token,\n userData,\n )\n .then((authResult) => {\n if (!authResult.success) {\n // Authentication failed - return error to reject connection\n console.warn(`Authentication failed for client ID: ${clientId}`);\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"Authentication failed\",\n false,\n );\n } else {\n // Return success with state overrides\n return {\n success: true as const,\n stateOverrides: authResult.stateOverrides,\n };\n }\n })\n .catch((error) => {\n console.error(`Authentication error for client ID: ${clientId}:`, error);\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"Authentication error\",\n false,\n );\n });\n }\n\n private handleLeave(leave: onLeaveOptions): void {\n const deltaNetConnection = leave.deltaNetV01Connection as DeltaNetV01Connection;\n const clientId = deltaNetConnection.internalConnectionId;\n\n if (clientId !== undefined) {\n const client = this.authenticatedClientsById.get(clientId);\n if (client) {\n this.options.onClientDisconnect(clientId);\n this.authenticatedClientsById.delete(clientId);\n }\n }\n }\n\n private handleCustomMessage(customMessage: onCustomMessageOptions): void {\n const deltaNetConnection = customMessage.deltaNetV01Connection;\n const clientId = deltaNetConnection.internalConnectionId;\n\n const client = this.authenticatedClientsById.get(clientId);\n if (client && client.authenticatedUser) {\n // Handle chat messages\n if (customMessage.customType === FROM_CLIENT_CHAT_MESSAGE_TYPE) {\n const chatMessage = parseClientChatMessage(customMessage.contents);\n if (chatMessage instanceof Error) {\n console.error(`Invalid chat message from client ${clientId}:`, chatMessage);\n } else {\n const serverChatMessage: ServerChatMessage = {\n fromUserId: clientId,\n message: chatMessage.message,\n };\n // Broadcast the chat message to all other clients\n this.deltaNetServer.broadcastCustomMessage(\n FROM_SERVER_CHAT_MESSAGE_TYPE,\n JSON.stringify(serverChatMessage),\n );\n }\n }\n } else {\n console.warn(`Custom message from unauthenticated client ${clientId} - ignoring`);\n }\n }\n\n private async handleDeltaNetAuthentication(\n clientId: number,\n webSocket: WebSocket,\n deltaNetConnection: DeltaNetV01Connection,\n sessionToken: string,\n userIdentity: UserData,\n ): Promise<\n | { success: true; stateOverrides?: Array<[number, Uint8Array]> }\n | { success: false; error?: Error }\n > {\n try {\n // For observers, we might want to allow anonymous access or use a different authentication flow\n let userData = deltaNetConnection.isObserver\n ? null // Observers don't need user data\n : await this.options.onClientConnect(clientId, sessionToken, userIdentity);\n\n if (!deltaNetConnection.isObserver && !userData) {\n console.warn(`Authentication failed for client ${clientId} - no user data returned`);\n return { success: false };\n }\n\n // Check connection limit\n if (\n this.options.connectionLimit !== undefined &&\n this.authenticatedClientsById.size >= this.options.connectionLimit\n ) {\n return { success: false };\n }\n\n if (userData instanceof Error) {\n return { success: false, error: userData };\n }\n\n if (userData === true) {\n userData = userIdentity;\n }\n\n // Create authenticated client\n const authenticatedClient: UserNetworkingServerClient = {\n id: clientId,\n socket: webSocket,\n lastPong: Date.now(),\n authenticatedUser: userData,\n deltaNetConnection: deltaNetConnection,\n };\n this.authenticatedClientsById.set(clientId, authenticatedClient);\n\n // Create state overrides with the user data from the authenticator\n // Observers don't have user data, so no state overrides\n let stateOverrides: Array<[number, Uint8Array]> = [];\n if (userData) {\n const officialStates = DeltaNetComponentMapping.toStates(userData);\n stateOverrides = Array.from(officialStates.entries());\n }\n\n return {\n success: true,\n stateOverrides: stateOverrides,\n };\n } catch (error) {\n console.error(\"Authentication error:\", error);\n return { success: false };\n }\n }\n\n public connectClient(socket: WebSocket): void {\n if (socket.protocol === \"\") {\n // This is likely a legacy client that does not support deltanet - use legacy adapter if enabled\n if (this.legacyAdapter) {\n this.legacyAdapter.addWebSocket(socket as unknown as globalThis.WebSocket);\n return;\n } else {\n socket.close(1000, \"Legacy client detected (no subprotocol) - not supported\");\n return;\n }\n }\n\n // Add websocket to deltanet server\n this.deltaNetServer.addWebSocket(socket as unknown as globalThis.WebSocket);\n\n socket.addEventListener(\"close\", () => {\n this.deltaNetServer.removeWebSocket(socket as unknown as globalThis.WebSocket);\n });\n }\n\n public broadcastMessage(broadcastType: number, broadcastPayload: string): void {\n this.deltaNetServer.broadcastCustomMessage(broadcastType, broadcastPayload);\n if (this.legacyAdapter) {\n this.legacyAdapter.broadcastMessage(broadcastType, broadcastPayload);\n }\n }\n\n public updateUserCharacter(clientId: number, userData: UserData): void {\n console.log(\"updateUserCharacter\", clientId, userData);\n this.internalUpdateUser(clientId, userData);\n }\n\n public updateUserUsername(clientId: number, username: string): void {\n const client = this.authenticatedClientsById.get(clientId);\n if (!client || !client.authenticatedUser) return;\n\n // Update local user data by creating a new UserData object\n client.authenticatedUser = {\n ...client.authenticatedUser,\n username: username,\n };\n\n this.updatedUserProfilesInTick.add(clientId);\n\n // Update deltanet states with just the username\n const states = DeltaNetComponentMapping.toUsernameState(username);\n const asArray = Array.from(states.entries());\n this.deltaNetServer.overrideUserStates(client.deltaNetConnection, clientId, asArray);\n }\n\n public updateUserCharacterDescription(\n clientId: number,\n characterDescription: CharacterDescription,\n ): void {\n const client = this.authenticatedClientsById.get(clientId);\n if (!client || !client.authenticatedUser) return;\n\n // Update local user data by creating a new UserData object\n client.authenticatedUser = {\n ...client.authenticatedUser,\n characterDescription: characterDescription,\n };\n\n this.updatedUserProfilesInTick.add(clientId);\n\n // Update deltanet states with just the character description\n const states = DeltaNetComponentMapping.toCharacterDescriptionState(characterDescription);\n const asArray = Array.from(states.entries());\n this.deltaNetServer.overrideUserStates(client.deltaNetConnection, clientId, asArray);\n }\n\n public updateUserColors(clientId: number, colors: Array<[number, number, number]>): void {\n const client = this.authenticatedClientsById.get(clientId);\n if (!client || !client.authenticatedUser) return;\n\n // Update local user data by creating a new UserData object\n client.authenticatedUser = {\n ...client.authenticatedUser,\n colors: colors,\n };\n\n this.updatedUserProfilesInTick.add(clientId);\n\n // Update deltanet states with just the colors\n const states = DeltaNetComponentMapping.toColorsState(colors);\n const asArray = Array.from(states.entries());\n this.deltaNetServer.overrideUserStates(client.deltaNetConnection, clientId, asArray);\n }\n\n public updateUserStates(clientId: number, updates: UserData): void {\n const client = this.authenticatedClientsById.get(clientId);\n if (!client || !client.authenticatedUser) return;\n\n const states = new Map<number, Uint8Array>();\n let hasUpdates = false;\n let updatedUserData = client.authenticatedUser;\n\n this.updatedUserProfilesInTick.add(clientId);\n\n // Update username if provided\n if (updates.username !== null) {\n updatedUserData = {\n ...updatedUserData,\n username: updates.username,\n };\n const usernameStates = DeltaNetComponentMapping.toUsernameState(updates.username);\n for (const [stateId, stateValue] of usernameStates) {\n states.set(stateId, stateValue);\n }\n hasUpdates = true;\n }\n\n // Update character description if provided\n if (updates.characterDescription !== null) {\n updatedUserData = {\n ...updatedUserData,\n characterDescription: updates.characterDescription,\n };\n const characterDescStates = DeltaNetComponentMapping.toCharacterDescriptionState(\n updates.characterDescription,\n );\n for (const [stateId, stateValue] of characterDescStates) {\n states.set(stateId, stateValue);\n }\n hasUpdates = true;\n }\n\n // Update colors if provided\n if (updates.colors !== null) {\n updatedUserData = {\n ...updatedUserData,\n colors: updates.colors,\n };\n const colorsStates = DeltaNetComponentMapping.toColorsState(updates.colors);\n for (const [stateId, stateValue] of colorsStates) {\n states.set(stateId, stateValue);\n }\n hasUpdates = true;\n }\n\n // Only send update if there are changes\n if (hasUpdates) {\n client.authenticatedUser = updatedUserData;\n const asArray = Array.from(states.entries());\n this.deltaNetServer.overrideUserStates(client.deltaNetConnection, clientId, asArray);\n }\n }\n\n private internalUpdateUser(clientId: number, userData: UserData): void {\n const client = this.authenticatedClientsById.get(clientId);\n if (!client) {\n throw new Error(`internalUpdateUser - client not found for clientId ${clientId}`);\n }\n console.log(\"internalUpdateUser\", clientId, userData);\n\n this.updatedUserProfilesInTick.add(clientId);\n\n client.authenticatedUser = {\n ...client.authenticatedUser,\n ...userData,\n };\n\n // Update deltanet states\n const states = DeltaNetComponentMapping.toStates(userData);\n\n const asArray = Array.from(states.entries());\n this.deltaNetServer.overrideUserStates(client.deltaNetConnection, clientId, asArray);\n }\n\n public dispose(clientCloseError?: UserNetworkingServerError): void {\n if (this.tickInterval) {\n clearInterval(this.tickInterval);\n }\n\n let errorMessage: Uint8Array | null = null;\n if (clientCloseError) {\n errorMessage = encodeError({\n type: \"error\",\n errorType: clientCloseError.errorType,\n message: clientCloseError.message,\n retryable: clientCloseError.retryable,\n }).getBuffer();\n }\n\n // Close all client connections\n for (const [, client] of this.authenticatedClientsById) {\n if (errorMessage) {\n client.socket.send(errorMessage);\n }\n client.socket.close();\n }\n\n this.authenticatedClientsById.clear();\n }\n}\n", "import { BufferReader, BufferWriter } from \"@mml-io/delta-net-protocol\";\n\nimport { UserNetworkingClientUpdate } from \"./types\";\nimport { UserData } from \"./UserData\";\nimport { CharacterDescription } from \"./UserNetworkingMessages\";\n\n// Component IDs used in the deltanet implementation\nexport const COMPONENT_POSITION_X = 1;\nexport const COMPONENT_POSITION_Y = 2;\nexport const COMPONENT_POSITION_Z = 3;\nexport const COMPONENT_ROTATION_Y = 4;\nexport const COMPONENT_ROTATION_W = 5;\nexport const COMPONENT_STATE = 6;\n\n// State IDs for binary data\nexport const STATE_INTERNAL_CONNECTION_ID = 0;\nexport const STATE_CHARACTER_DESCRIPTION = 1;\nexport const STATE_USERNAME = 2;\nexport const STATE_COLORS = 3;\n\nexport const rotationMultiplier = 360;\nexport const positionMultiplier = 100;\nconst textDecoder = new TextDecoder();\n\nexport class DeltaNetComponentMapping {\n /**\n * Convert UserNetworkingClientUpdate to deltanet components\n */\n static toComponents(update: UserNetworkingClientUpdate): Map<number, bigint> {\n const components = new Map<number, bigint>();\n\n // Convert position values to fixed-point representation\n components.set(\n COMPONENT_POSITION_X,\n BigInt(Math.round(update.position.x * positionMultiplier)),\n );\n components.set(\n COMPONENT_POSITION_Y,\n BigInt(Math.round(update.position.y * positionMultiplier)),\n );\n components.set(\n COMPONENT_POSITION_Z,\n BigInt(Math.round(update.position.z * positionMultiplier)),\n );\n\n // Convert quaternion values to fixed-point representation\n // Using 32767 scale to match original codec precision\n components.set(\n COMPONENT_ROTATION_Y,\n BigInt(Math.round(update.rotation.quaternionY * rotationMultiplier)),\n );\n components.set(\n COMPONENT_ROTATION_W,\n BigInt(Math.round(update.rotation.quaternionW * rotationMultiplier)),\n );\n\n // State is already an integer\n components.set(COMPONENT_STATE, BigInt(update.state));\n\n return components;\n }\n\n /**\n * Convert deltanet components back to UserNetworkingClientUpdate\n */\n static fromComponents(components: Map<number, bigint>): UserNetworkingClientUpdate {\n const positionX =\n Number(components.get(COMPONENT_POSITION_X) || BigInt(0)) / positionMultiplier;\n const positionY =\n Number(components.get(COMPONENT_POSITION_Y) || BigInt(0)) / positionMultiplier;\n const positionZ =\n Number(components.get(COMPONENT_POSITION_Z) || BigInt(0)) / positionMultiplier;\n const rotationY =\n Number(components.get(COMPONENT_ROTATION_Y) || BigInt(0)) / rotationMultiplier;\n const rotationW =\n Number(components.get(COMPONENT_ROTATION_W) || BigInt(0)) / rotationMultiplier;\n\n const state = Number(components.get(COMPONENT_STATE) || BigInt(0));\n\n return {\n position: { x: positionX, y: positionY, z: positionZ },\n rotation: { quaternionY: rotationY, quaternionW: rotationW },\n state,\n };\n }\n\n /**\n * Encode character description and username to binary states\n */\n static toStates(userIdentity: UserData): Map<number, Uint8Array> {\n const states = new Map<number, Uint8Array>();\n const textEncoder = new TextEncoder();\n\n if (userIdentity.username) {\n // Encode username\n states.set(STATE_USERNAME, textEncoder.encode(userIdentity.username));\n }\n\n // Encode character description as JSON\n if (userIdentity.characterDescription) {\n states.set(\n STATE_CHARACTER_DESCRIPTION,\n textEncoder.encode(JSON.stringify(userIdentity.characterDescription)),\n );\n }\n\n if (userIdentity.colors) {\n states.set(STATE_COLORS, DeltaNetComponentMapping.encodeColors(userIdentity.colors));\n }\n\n return states;\n }\n\n /**\n * Encode username to binary state\n */\n static toUsernameState(username: string): Map<number, Uint8Array> {\n const states = new Map<number, Uint8Array>();\n const textEncoder = new TextEncoder();\n states.set(STATE_USERNAME, textEncoder.encode(username));\n return states;\n }\n\n /**\n * Encode character description to binary state\n */\n static toCharacterDescriptionState(\n characterDescription: CharacterDescription,\n ): Map<number, Uint8Array> {\n const states = new Map<number, Uint8Array>();\n const textEncoder = new TextEncoder();\n states.set(\n STATE_CHARACTER_DESCRIPTION,\n textEncoder.encode(JSON.stringify(characterDescription)),\n );\n return states;\n }\n\n /**\n * Encode colors to binary state\n */\n static toColorsState(colors: Array<[number, number, number]>): Map<number, Uint8Array> {\n const states = new Map<number, Uint8Array>();\n states.set(STATE_COLORS, DeltaNetComponentMapping.encodeColors(colors));\n return states;\n }\n\n /**\n * Encode single state value\n */\n static toSingleState(stateId: number, value: any): Map<number, Uint8Array> {\n const states = new Map<number, Uint8Array>();\n const textEncoder = new TextEncoder();\n\n switch (stateId) {\n case STATE_USERNAME:\n if (typeof value === \"string\") {\n states.set(stateId, textEncoder.encode(value));\n }\n break;\n case STATE_CHARACTER_DESCRIPTION:\n if (typeof value === \"object\" && value !== null) {\n states.set(stateId, textEncoder.encode(JSON.stringify(value)));\n }\n break;\n case STATE_COLORS:\n if (Array.isArray(value)) {\n states.set(stateId, DeltaNetComponentMapping.encodeColors(value));\n }\n break;\n }\n\n return states;\n }\n\n static encodeColors(colors: Array<[number, number, number]>): Uint8Array {\n const bufferWriter = new BufferWriter(3 * colors.length + 1);\n bufferWriter.writeUVarint(colors.length);\n for (const color of colors) {\n bufferWriter.writeUVarint(color[0]);\n bufferWriter.writeUVarint(color[1]);\n bufferWriter.writeUVarint(color[2]);\n }\n return bufferWriter.getBuffer();\n }\n\n static decodeColors(colors: Uint8Array): Array<[number, number, number]> {\n if (colors.byteLength === 0) {\n return [];\n }\n try {\n const bufferReader = new BufferReader(colors);\n const colorsArray: Array<[number, number, number]> = [];\n const count = bufferReader.readUVarint();\n for (let i = 0; i < count; i++) {\n colorsArray.push([\n bufferReader.readUVarint(),\n bufferReader.readUVarint(),\n bufferReader.readUVarint(),\n ]);\n }\n return colorsArray;\n } catch (e) {\n console.error(\"Error decoding colors\", colors, e);\n return [];\n }\n }\n\n static fromUserStates(states: Map<number, Uint8Array>): UserData {\n const usernameBytes = states.get(STATE_USERNAME);\n const username = usernameBytes\n ? DeltaNetComponentMapping.usernameFromBytes(usernameBytes)\n : null;\n\n const characterDescBytes = states.get(STATE_CHARACTER_DESCRIPTION);\n const characterDescription = characterDescBytes\n ? DeltaNetComponentMapping.characterDescriptionFromBytes(characterDescBytes)\n : null;\n\n const colorsBytes = states.get(STATE_COLORS);\n const colorsArray = colorsBytes ? DeltaNetComponentMapping.decodeColors(colorsBytes) : [];\n\n return { username, characterDescription, colors: colorsArray };\n }\n\n static userIdFromBytes(bytes: Uint8Array): number | null {\n if (bytes.length === 0) {\n return null;\n }\n const reader = new BufferReader(bytes);\n return reader.readUVarint(false);\n }\n\n static usernameFromBytes(bytes: Uint8Array): string | null {\n if (bytes.length === 0) {\n return null;\n }\n return textDecoder.decode(bytes);\n }\n static characterDescriptionFromBytes(bytes: Uint8Array): CharacterDescription | null {\n if (bytes.length === 0) {\n return null;\n }\n return JSON.parse(textDecoder.decode(bytes));\n }\n\n /**\n * Decode binary states back to username and character description\n */\n static fromStates(states: Map<number, Uint8Array>): {\n userId: number | null;\n } & UserData {\n const userIdBytes = states.get(STATE_INTERNAL_CONNECTION_ID);\n let userId: number | null = null;\n if (userIdBytes) {\n const reader = new BufferReader(userIdBytes);\n userId = reader.readUVarint(false);\n }\n\n const userStates = DeltaNetComponentMapping.fromUserStates(states);\n\n return { userId, ...userStates };\n }\n}\n", "import { DeltaNetServerError } from \"@mml-io/delta-net-server\";\n\nexport type CharacterDescription =\n | {\n meshFileUrl: string;\n mmlCharacterString?: null;\n mmlCharacterUrl?: null;\n }\n | {\n meshFileUrl?: null;\n mmlCharacterString: string;\n mmlCharacterUrl?: null;\n }\n | {\n meshFileUrl?: null;\n mmlCharacterString?: null;\n mmlCharacterUrl: string;\n };\n\nexport class UserNetworkingServerError extends DeltaNetServerError {}\n\nexport type ClientChatMessage = {\n message: string;\n};\n\nexport type ServerChatMessage = {\n fromUserId: number;\n message: string;\n};\n\nexport type ServerBroadcastMessage = {\n broadcastType: string;\n payload: any;\n};\n\n// Custom message types\nexport const SERVER_BROADCAST_MESSAGE_TYPE = 1;\nexport const FROM_CLIENT_CHAT_MESSAGE_TYPE = 2;\nexport const FROM_SERVER_CHAT_MESSAGE_TYPE = 3;\n\nexport function parseClientChatMessage(contents: string): ClientChatMessage | Error {\n try {\n const parsed = JSON.parse(contents) as unknown;\n if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n \"message\" in parsed &&\n typeof parsed.message === \"string\"\n ) {\n return {\n message: parsed.message as string,\n };\n } else {\n throw new Error(\"Invalid chat message\");\n }\n } catch (error) {\n return new Error(`Invalid chat message: ${error}`);\n }\n}\n\nexport function parseServerChatMessage(contents: string): ServerChatMessage | Error {\n try {\n const parsed = JSON.parse(contents) as unknown;\n if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n \"fromUserId\" in parsed &&\n typeof parsed.fromUserId === \"number\" &&\n \"message\" in parsed &&\n typeof parsed.message === \"string\"\n ) {\n return {\n fromUserId: parsed.fromUserId as number,\n message: parsed.message as string,\n };\n } else {\n throw new Error(\"Invalid server chat message\");\n }\n } catch (error) {\n return new Error(`Invalid server chat message: ${error}`);\n }\n}\n\nexport function parseServerBroadcastMessage(contents: string): ServerBroadcastMessage | Error {\n try {\n const parsed = JSON.parse(contents) as unknown;\n if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n \"broadcastType\" in parsed &&\n typeof parsed.broadcastType === \"string\" &&\n \"payload\" in parsed &&\n typeof parsed.payload === \"object\"\n ) {\n return {\n broadcastType: parsed.broadcastType as string,\n payload: parsed.payload as any,\n };\n } else {\n throw new Error(\"Invalid server broadcast message\");\n }\n } catch (error) {\n return new Error(`Invalid server broadcast message: ${error}`);\n }\n}\n", "export type LegacyUserNetworkingClientUpdate = {\n id: number;\n position: { x: number; y: number; z: number };\n rotation: { quaternionY: number; quaternionW: number };\n state: number;\n};\n\nexport class LegacyUserNetworkingCodec {\n static encodeUpdate(update: LegacyUserNetworkingClientUpdate): Uint8Array {\n const buffer = new ArrayBuffer(19);\n const dataView = new DataView(buffer);\n dataView.setUint16(0, update.id); // id\n dataView.setFloat32(2, update.position.x); // position.x\n dataView.setFloat32(6, update.position.y); // position.y\n dataView.setFloat32(10, update.position.z); // position.z\n dataView.setInt16(14, update.rotation.quaternionY * 32767); // quaternion.y\n dataView.setInt16(16, update.rotation.quaternionW * 32767); // quaternion.w\n dataView.setUint8(18, update.state); // animationState\n return new Uint8Array(buffer);\n }\n\n static decodeUpdate(buffer: ArrayBuffer): LegacyUserNetworkingClientUpdate {\n const dataView = new DataView(buffer);\n const id = dataView.getUint16(0); // id\n const x = dataView.getFloat32(2); // position.x\n const y = dataView.getFloat32(6); // position.y\n const z = dataView.getFloat32(10); // position.z\n const quaternionY = dataView.getInt16(14) / 32767; // quaternion.y\n const quaternionW = dataView.getInt16(16) / 32767; // quaternion.w\n const state = dataView.getUint8(18); // animationState\n const position = { x, y, z };\n const rotation = { quaternionY, quaternionW };\n return { id, position, rotation, state };\n }\n}\n", "export const LEGACY_USER_NETWORKING_DISCONNECTED_MESSAGE_TYPE = \"disconnected\";\nexport const LEGACY_USER_NETWORKING_IDENTITY_MESSAGE_TYPE = \"identity\";\nexport const LEGACY_USER_NETWORKING_USER_AUTHENTICATE_MESSAGE_TYPE = \"user_auth\";\nexport const LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE = \"user_profile\";\nexport const LEGACY_USER_NETWORKING_USER_UPDATE_MESSAGE_TYPE = \"user_update\";\nexport const LEGACY_USER_NETWORKING_SERVER_BROADCAST_MESSAGE_TYPE = \"broadcast\";\nexport const LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE = \"error\";\nexport const LEGACY_USER_NETWORKING_PING_MESSAGE_TYPE = \"ping\";\nexport const LEGACY_USER_NETWORKING_PONG_MESSAGE_TYPE = \"pong\";\n\nexport type LegacyUserNetworkingIdentityMessage = {\n type: typeof LEGACY_USER_NETWORKING_IDENTITY_MESSAGE_TYPE;\n id: number;\n};\n\nexport type LegacyCharacterDescription =\n | {\n meshFileUrl: string;\n mmlCharacterString?: null;\n mmlCharacterUrl?: null;\n }\n | {\n meshFileUrl?: null;\n mmlCharacterString: string;\n mmlCharacterUrl?: null;\n }\n | {\n meshFileUrl?: null;\n mmlCharacterString?: null;\n mmlCharacterUrl: string;\n };\n\nexport type LegacyUserData = {\n readonly username: string;\n readonly characterDescription: LegacyCharacterDescription;\n};\n\nexport type LegacyUserNetworkingProfileMessage = {\n type: typeof LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE;\n id: number;\n username: string;\n characterDescription: LegacyCharacterDescription;\n};\n\nexport type LegacyUserNetworkingDisconnectedMessage = {\n type: typeof LEGACY_USER_NETWORKING_DISCONNECTED_MESSAGE_TYPE;\n id: number;\n};\n\nexport const LEGACY_USER_NETWORKING_CONNECTION_LIMIT_REACHED_ERROR_TYPE =\n \"CONNECTION_LIMIT_REACHED\";\nexport const LEGACY_USER_NETWORKING_AUTHENTICATION_FAILED_ERROR_TYPE = \"AUTHENTICATION_FAILED\";\nexport const LEGACY_USER_NETWORKING_SERVER_SHUTDOWN_ERROR_TYPE = \"SERVER_SHUTDOWN\";\nexport const LEGACY_USER_NETWORKING_UNKNOWN_ERROR = \"UNKNOWN_ERROR\";\n\nexport type LegacyUserNetworkingServerErrorType =\n | typeof LEGACY_USER_NETWORKING_CONNECTION_LIMIT_REACHED_ERROR_TYPE\n | typeof LEGACY_USER_NETWORKING_AUTHENTICATION_FAILED_ERROR_TYPE\n | typeof LEGACY_USER_NETWORKING_SERVER_SHUTDOWN_ERROR_TYPE\n | typeof LEGACY_USER_NETWORKING_UNKNOWN_ERROR;\n\nexport type LegacyUserNetworkingServerError = {\n type: typeof LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE;\n errorType: LegacyUserNetworkingServerErrorType;\n message: string;\n};\n\nexport type LegacyUserNetworkingServerBroadcast = {\n type: typeof LEGACY_USER_NETWORKING_SERVER_BROADCAST_MESSAGE_TYPE;\n broadcastType: string;\n payload: any;\n};\n\nexport type LegacyUserNetworkingServerPingMessage = {\n type: typeof LEGACY_USER_NETWORKING_PING_MESSAGE_TYPE;\n};\n\nexport type LegacyFromUserNetworkingServerMessage =\n | LegacyUserNetworkingIdentityMessage\n | LegacyUserNetworkingProfileMessage\n | LegacyUserNetworkingDisconnectedMessage\n | LegacyUserNetworkingServerPingMessage\n | LegacyUserNetworkingServerBroadcast\n | LegacyUserNetworkingServerError;\n\nexport type LegacyUserNetworkingClientPongMessage = {\n type: typeof LEGACY_USER_NETWORKING_PONG_MESSAGE_TYPE;\n};\n\nexport type LegacyUserIdentity = {\n characterDescription: LegacyCharacterDescription | null;\n username: string | null;\n};\n\nexport type LegacyUserNetworkingAuthenticateMessage = {\n type: typeof LEGACY_USER_NETWORKING_USER_AUTHENTICATE_MESSAGE_TYPE;\n sessionToken: string;\n // The client can send a LegacyUserIdentity to use as the initial user profile and the server can choose to accept it or not\n userIdentity?: LegacyUserIdentity;\n};\n\nexport type LegacyUserNetworkingUserUpdateMessage = {\n type: typeof LEGACY_USER_NETWORKING_USER_UPDATE_MESSAGE_TYPE;\n userIdentity: LegacyUserIdentity;\n};\n\nexport type LegacyFromUserNetworkingClientMessage =\n | LegacyUserNetworkingClientPongMessage\n | LegacyUserNetworkingAuthenticateMessage\n | LegacyUserNetworkingUserUpdateMessage;\n", "import { DeltaNetServer } from \"@mml-io/delta-net-server\";\n\nimport {\n COMPONENT_POSITION_X,\n COMPONENT_ROTATION_W,\n COMPONENT_POSITION_Y,\n COMPONENT_POSITION_Z,\n COMPONENT_ROTATION_Y,\n COMPONENT_STATE,\n rotationMultiplier,\n positionMultiplier,\n} from \"../DeltaNetComponentMapping\";\nimport { UserData } from \"../UserData\";\nimport {\n parseServerBroadcastMessage,\n SERVER_BROADCAST_MESSAGE_TYPE,\n} from \"../UserNetworkingMessages\";\nimport { UserNetworkingServer } from \"../UserNetworkingServer\";\n\nimport {\n LegacyUserNetworkingClientUpdate,\n LegacyUserNetworkingCodec,\n} from \"./LegacyUserNetworkingCodec\";\nimport {\n LEGACY_USER_NETWORKING_AUTHENTICATION_FAILED_ERROR_TYPE,\n LEGACY_USER_NETWORKING_CONNECTION_LIMIT_REACHED_ERROR_TYPE,\n LEGACY_USER_NETWORKING_DISCONNECTED_MESSAGE_TYPE,\n LEGACY_USER_NETWORKING_IDENTITY_MESSAGE_TYPE,\n LEGACY_USER_NETWORKING_PONG_MESSAGE_TYPE,\n LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE,\n LEGACY_USER_NETWORKING_UNKNOWN_ERROR,\n LEGACY_USER_NETWORKING_USER_AUTHENTICATE_MESSAGE_TYPE,\n LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE,\n LEGACY_USER_NETWORKING_USER_UPDATE_MESSAGE_TYPE,\n LegacyFromUserNetworkingClientMessage,\n LegacyFromUserNetworkingServerMessage,\n LegacyUserData,\n LegacyUserNetworkingAuthenticateMessage,\n LegacyUserNetworkingServerBroadcast,\n LegacyUserNetworkingServerError,\n LegacyUserNetworkingUserUpdateMessage,\n} from \"./LegacyUserNetworkingMessages\";\n\nexport type LegacyUserNetworkingServerClient = {\n socket: WebSocket;\n id: number;\n lastPong: number;\n update: LegacyUserNetworkingClientUpdate;\n authenticatedUser: LegacyUserData | null;\n};\n\nfunction toArrayBuffer(buffer: Buffer) {\n const arrayBuffer = new ArrayBuffer(buffer.length);\n const view = new Uint8Array(arrayBuffer);\n for (let i = 0; i < buffer.length; ++i) {\n view[i] = buffer[i];\n }\n return arrayBuffer;\n}\n\nconst WebSocketOpenStatus = 1;\n\nexport class LegacyAdapter {\n private allClientsById: Map<number, LegacyUserNetworkingServerClient> = new Map();\n private legacyAuthenticatedClientsById: Map<number, LegacyUserNetworkingServerClient> = new Map();\n\n constructor(\n private readonly userNetworkingServer: UserNetworkingServer,\n private readonly deltaNetServer: DeltaNetServer,\n ) {}\n\n public broadcastMessage(broadcastType: number, broadcastPayload: string) {\n // The new broadcast type is a number and then the payload is a string\n // \"Broadcast\" messages intended for legacy clients are only the SERVER_BROADCAST_MESSAGE_TYPE\n if (broadcastType !== SERVER_BROADCAST_MESSAGE_TYPE) {\n return;\n }\n\n const parsedPayload = parseServerBroadcastMessage(broadcastPayload);\n if (parsedPayload instanceof Error) {\n console.error(\"Error parsing server broadcast message\", parsedPayload);\n return;\n }\n\n const { broadcastType: broadcastTypeString, payload } = parsedPayload;\n\n const message: LegacyUserNetworkingServerBroadcast = {\n type: \"broadcast\",\n broadcastType: broadcastTypeString,\n payload: payload,\n };\n const messageString = JSON.stringify(message);\n for (const [, client] of this.legacyAuthenticatedClientsById) {\n if (client.socket.readyState === WebSocketOpenStatus) {\n client.socket.send(messageString);\n }\n }\n }\n\n public addWebSocket(socket: WebSocket) {\n const id = this.userNetworkingServer.getLegacyClientId();\n\n // Create a client but without user information\n const client: LegacyUserNetworkingServerClient = {\n id,\n lastPong: Date.now(),\n socket: socket as WebSocket,\n authenticatedUser: null,\n update: {\n id,\n position: { x: 0, y: 0, z: 0 },\n rotation: { quaternionY: 0, quaternionW: 1 },\n state: 0,\n },\n };\n this.allClientsById.set(id, client);\n\n socket.addEventListener(\"message\", (message: MessageEvent) => {\n try {\n if (message.data instanceof ArrayBuffer || message.data instanceof Buffer) {\n if (client.authenticatedUser) {\n const arrayBuffer =\n message.data instanceof ArrayBuffer ? message.data : toArrayBuffer(message.data);\n const update = LegacyUserNetworkingCodec.decodeUpdate(arrayBuffer);\n update.id = id;\n const index = this.deltaNetServer.dangerouslyGetConnectionsToComponentIndex().get(id);\n client.update = update;\n if (index !== undefined) {\n this.deltaNetServer.setComponentValue(\n COMPONENT_POSITION_X,\n index,\n BigInt(Math.round(update.position.x * positionMultiplier)),\n );\n this.deltaNetServer.setComponentValue(\n COMPONENT_POSITION_Y,\n index,\n BigInt(Math.round(update.position.y * positionMultiplier)),\n );\n this.deltaNetServer.setComponentValue(\n COMPONENT_POSITION_Z,\n index,\n BigInt(Math.round(update.position.z * positionMultiplier)),\n );\n this.deltaNetServer.setComponentValue(\n COMPONENT_ROTATION_Y,\n index,\n BigInt(Math.round(update.rotation.quaternionY * rotationMultiplier)),\n );\n this.deltaNetServer.setComponentValue(\n COMPONENT_ROTATION_W,\n index,\n BigInt(Math.round(update.rotation.quaternionW * rotationMultiplier)),\n );\n this.deltaNetServer.setComponentValue(\n COMPONENT_STATE,\n index,\n BigInt(Math.round(update.state)),\n );\n }\n }\n } else {\n let parsed;\n try {\n parsed = JSON.parse(message.data as string) as LegacyFromUserNetworkingClientMessage;\n } catch (e) {\n console.error(\"Error parsing JSON message\", message, e);\n return;\n }\n if (!client.authenticatedUser) {\n if (parsed.type === LEGACY_USER_NETWORKING_USER_AUTHENTICATE_MESSAGE_TYPE) {\n this.handleUserAuth(client, parsed).then((authResult) => {\n if (client.socket.readyState !== WebSocketOpenStatus) {\n // The client disconnected before the authentication was completed\n return;\n }\n if (!authResult) {\n console.error(`Client-id ${client.id} user_auth failed`, authResult);\n // If the user is not authorized, disconnect the client\n const serverError = JSON.stringify({\n type: LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE,\n errorType: LEGACY_USER_NETWORKING_AUTHENTICATION_FAILED_ERROR_TYPE,\n message: \"Authentication failed\",\n } as LegacyFromUserNetworkingServerMessage);\n socket.send(serverError);\n socket.close();\n } else {\n if (!this.userNetworkingServer.hasCapacityForLegacyClient()) {\n // There is a connection limit and it has been met - disconnect the user\n const serverError = JSON.stringify({\n type: LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE,\n errorType: LEGACY_USER_NETWORKING_CONNECTION_LIMIT_REACHED_ERROR_TYPE,\n message: \"Connection limit reached\",\n } as LegacyFromUserNetworkingServerMessage);\n socket.send(serverError);\n socket.close();\n return;\n }\n\n const userData = authResult;\n\n this.deltaNetServer.dangerouslyAddNewJoinerCallback((index) => {\n if (client.socket.readyState !== WebSocketOpenStatus) {\n return null;\n }\n client.authenticatedUser = userData;\n this.deltaNetServer.setComponentValue(COMPONENT_POSITION_X, index, BigInt(0));\n this.deltaNetServer.setComponentValue(COMPONENT_POSITION_Y, index, BigInt(0));\n this.deltaNetServer.setComponentValue(COMPONENT_POSITION_Z, index, BigInt(0));\n this.deltaNetServer.setComponentValue(COMPONENT_ROTATION_Y, index, BigInt(0));\n this.deltaNetServer.setComponentValue(COMPONENT_ROTATION_W, index, BigInt(0));\n this.deltaNetServer.setComponentValue(COMPONENT_STATE, index, BigInt(0));\n\n const asUserData: UserData = {\n ...userData,\n colors: [],\n };\n return {\n id: client.id,\n afterAddCallback: () => {\n this.userNetworkingServer.setAuthenticatedLegacyClientConnection(\n client.id,\n client.socket,\n asUserData,\n );\n this.userNetworkingServer.updateUserCharacter(client.id, asUserData);\n },\n };\n });\n\n // Give the client its own profile\n const userProfileMessage = JSON.stringify({\n id: client.id,\n type: LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE,\n username: userData.username,\n characterDescription: userData.characterDescription,\n } as LegacyFromUserNetworkingServerMessage);\n client.socket.send(userProfileMessage);\n\n // Give the client its own identity\n const identityMessage = JSON.stringify({\n id: client.id,\n type: LEGACY_USER_NETWORKING_IDENTITY_MESSAGE_TYPE,\n } as LegacyFromUserNetworkingServerMessage);\n client.socket.send(identityMessage);\n\n const allUsers: Map<number, number> =\n this.deltaNetServer.dangerouslyGetConnectionsToComponentIndex();\n for (const [connectionId, componentIndex] of allUsers) {\n if (connectionId === client.id) {\n continue;\n }\n const x =\n this.deltaNetServer.getComponentValue(COMPONENT_POSITION_X, componentIndex) /\n positionMultiplier;\n const y =\n this.deltaNetServer.getComponentValue(COMPONENT_POSITION_Y, componentIndex) /\n positionMultiplier;\n const z =\n this.deltaNetServer.getComponentValue(COMPONENT_POSITION_Z, componentIndex) /\n positionMultiplier;\n const quaternionY =\n this.deltaNetServer.getComponentValue(COMPONENT_ROTATION_Y, componentIndex) /\n rotationMultiplier;\n const quaternionW =\n this.deltaNetServer.getComponentValue(COMPONENT_ROTATION_W, componentIndex) /\n rotationMultiplier;\n const state = this.deltaNetServer.getComponentValue(\n COMPONENT_STATE,\n componentIndex,\n );\n const update = LegacyUserNetworkingCodec.encodeUpdate({\n id: connectionId,\n position: { x, y, z },\n rotation: { quaternionY, quaternionW },\n state,\n });\n // Send the update about the other user to the newly connected client\n client.socket.send(\n JSON.stringify({\n id: connectionId,\n type: LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE,\n username: this.userNetworkingServer.getUsername(connectionId),\n characterDescription:\n this.userNetworkingServer.getCharacterDescription(connectionId),\n } satisfies LegacyFromUserNetworkingServerMessage),\n );\n client.socket.send(update);\n }\n\n this.legacyAuthenticatedClientsById.set(id, client);\n }\n });\n } else {\n console.error(`Unhandled message pre-auth: ${JSON.stringify(parsed)}`);\n socket.close();\n }\n } else {\n switch (parsed.type) {\n case LEGACY_USER_NETWORKING_PONG_MESSAGE_TYPE:\n client.lastPong = Date.now();\n break;\n\n case LEGACY_USER_NETWORKING_USER_UPDATE_MESSAGE_TYPE:\n this.handleUserUpdate(id, parsed as LegacyUserNetworkingUserUpdateMessage);\n break;\n\n default:\n console.error(`Unhandled message: ${JSON.stringify(parsed)}`);\n }\n }\n }\n } catch (e) {\n console.error(\"Error handling message\", message, e);\n socket.send(\n JSON.stringify({\n type: LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE,\n errorType: LEGACY_USER_NETWORKING_UNKNOWN_ERROR,\n message: \"Error handling message\",\n } satisfies LegacyFromUserNetworkingServerMessage),\n );\n socket.close();\n }\n });\n\n socket.addEventListener(\"close\", () => {\n this.handleDisconnectedClient(client);\n });\n }\n\n private handleDisconnectedClient(client: LegacyUserNetworkingServerClient) {\n if (!this.allClientsById.has(client.id)) {\n return;\n }\n this.allClientsById.delete(client.id);\n if (client.authenticatedUser !== null) {\n // Only report disconnections of clients that were authenticated\n this.userNetworkingServer.onLegacyClientDisconnect(client.id);\n this.legacyAuthenticatedClientsById.delete(client.id);\n this.deltaNetServer.clearInternalConnectionId(client.id);\n }\n }\n\n private async handleUserAuth(\n client: LegacyUserNetworkingServerClient,\n credentials: LegacyUserNetworkingAuthenticateMessage,\n ): Promise<false | LegacyUserData> {\n const userData = this.userNetworkingServer.onLegacyClientConnect(\n client.id,\n credentials.sessionToken,\n credentials.userIdentity,\n );\n let resolvedUserData;\n if (userData instanceof Promise) {\n resolvedUserData = await userData;\n } else {\n resolvedUserData = userData;\n }\n\n if (resolvedUserData instanceof Error) {\n console.error(`Client-id ${client.id} user_auth failed`, resolvedUserData);\n return false;\n } else if (resolvedUserData === true) {\n console.error(`Client-id ${client.id} user_auth failed`, resolvedUserData);\n resolvedUserData = credentials.userIdentity as LegacyUserData;\n } else {\n resolvedUserData = resolvedUserData as LegacyUserData;\n }\n if (resolvedUserData === null) {\n console.error(`Client-id ${client.id} user_auth unauthorized and ignored`);\n return false;\n }\n\n return resolvedUserData;\n }\n\n public updateUserCharacter(clientId: number, userData: LegacyUserData) {\n this.internalUpdateUser(clientId, userData);\n }\n\n private internalUpdateUser(clientId: number, userData: LegacyUserData) {\n // This function assumes authorization has already been done\n const client = this.legacyAuthenticatedClientsById.get(clientId)!;\n\n client.authenticatedUser = userData;\n this.legacyAuthenticatedClientsById.set(clientId, client);\n\n this.userNetworkingServer.updateUserCharacter(client.id, { ...userData, colors: [] });\n }\n\n private async handleUserUpdate(\n clientId: number,\n message: LegacyUserNetworkingUserUpdateMessage,\n ): Promise<void> {\n const client = this.legacyAuthenticatedClientsById.get(clientId);\n if (!client) {\n console.error(`Client-id ${clientId} user_update ignored, client not found`);\n return;\n }\n\n // TODO - call the UserNetworkingServer to check if the update is allowed\n // Verify using the user authenticator what the allowed version of this update is\n const authorizedUserData = message.userIdentity;\n\n let resolvedAuthorizedUserData;\n if (authorizedUserData instanceof Promise) {\n resolvedAuthorizedUserData = await authorizedUserData;\n } else {\n resolvedAuthorizedUserData = authorizedUserData;\n }\n if (!resolvedAuthorizedUserData) {\n // TODO - inform the client about the unauthorized update\n console.warn(`Client-id ${clientId} user_update unauthorized and ignored`);\n return;\n }\n\n this.internalUpdateUser(clientId, resolvedAuthorizedUserData);\n }\n\n public sendUpdates(\n removedIds: Set<number>,\n addedIds: Set<number>,\n updateUserProfilesInTick: Set<number>,\n ): void {\n for (const id of removedIds) {\n const disconnectMessage = JSON.stringify({\n id,\n type: LEGACY_USER_NETWORKING_DISCONNECTED_MESSAGE_TYPE,\n } as LegacyFromUserNetworkingServerMessage);\n for (const [, otherClient] of this.legacyAuthenticatedClientsById) {\n if (otherClient.socket.readyState === WebSocketOpenStatus) {\n otherClient.socket.send(disconnectMessage);\n }\n }\n }\n\n for (const id of addedIds) {\n const identityMessage = JSON.stringify({\n id: id,\n type: LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE,\n username: this.userNetworkingServer.getUsername(id),\n characterDescription: this.userNetworkingServer.getCharacterDescription(id),\n } satisfies LegacyFromUserNetworkingServerMessage);\n for (const [, otherClient] of this.legacyAuthenticatedClientsById) {\n if (otherClient.socket.readyState === WebSocketOpenStatus) {\n otherClient.socket.send(identityMessage);\n }\n }\n }\n\n for (const id of updateUserProfilesInTick) {\n const identityMessage = JSON.stringify({\n id: id,\n type: LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE,\n username: this.userNetworkingServer.getUsername(id),\n characterDescription: this.userNetworkingServer.getCharacterDescription(id),\n } satisfies LegacyFromUserNetworkingServerMessage);\n for (const [, otherClient] of this.legacyAuthenticatedClientsById) {\n if (otherClient.socket.readyState === WebSocketOpenStatus) {\n otherClient.socket.send(identityMessage);\n }\n }\n }\n\n for (const [clientId, client] of this.legacyAuthenticatedClientsById) {\n const encodedUpdate = LegacyUserNetworkingCodec.encodeUpdate(client.update);\n\n for (const [otherClientId, otherClient] of this.legacyAuthenticatedClientsById) {\n if (otherClientId !== clientId && otherClient.socket.readyState === WebSocketOpenStatus) {\n otherClient.socket.send(encodedUpdate);\n }\n }\n }\n\n const allUsers: Map<number, number> =\n this.deltaNetServer.dangerouslyGetConnectionsToComponentIndex();\n for (const [connectionId, componentIndex] of allUsers) {\n const x =\n this.deltaNetServer.getComponentValue(COMPONENT_POSITION_X, componentIndex) /\n positionMultiplier;\n const y =\n this.deltaNetServer.getComponentValue(COMPONENT_POSITION_Y, componentIndex) /\n positionMultiplier;\n const z =\n this.deltaNetServer.getComponentValue(COMPONENT_POSITION_Z, componentIndex) /\n positionMultiplier;\n const quaternionY =\n this.deltaNetServer.getComponentValue(COMPONENT_ROTATION_Y, componentIndex) /\n rotationMultiplier;\n const quaternionW =\n this.deltaNetServer.getComponentValue(COMPONENT_ROTATION_W, componentIndex) /\n rotationMultiplier;\n const state = this.deltaNetServer.getComponentValue(COMPONENT_STATE, componentIndex);\n const encodedUpdate = LegacyUserNetworkingCodec.encodeUpdate({\n id: connectionId,\n position: { x, y, z },\n rotation: { quaternionY, quaternionW },\n state,\n });\n\n for (const [otherClientId, otherClient] of this.legacyAuthenticatedClientsById) {\n if (\n otherClientId !== connectionId &&\n otherClient.socket.readyState === WebSocketOpenStatus\n ) {\n otherClient.socket.send(encodedUpdate);\n }\n }\n }\n }\n\n public dispose(clientCloseError?: LegacyUserNetworkingServerError) {\n const stringifiedError = clientCloseError ? JSON.stringify(clientCloseError) : undefined;\n\n for (const [, client] of this.legacyAuthenticatedClientsById) {\n if (stringifiedError) {\n client.socket.send(stringifiedError);\n }\n client.socket.close();\n }\n }\n}\n", "import {\n DeltaNetClientState,\n DeltaNetClientWebsocket,\n DeltaNetClientWebsocketInitialCheckout,\n DeltaNetClientWebsocketStatus,\n DeltaNetClientWebsocketTick,\n DeltaNetClientWebsocketUserIndex,\n} from \"@mml-io/delta-net-web\";\n\nimport {\n DeltaNetComponentMapping,\n STATE_CHARACTER_DESCRIPTION,\n STATE_COLORS,\n STATE_INTERNAL_CONNECTION_ID,\n STATE_USERNAME,\n} from \"./DeltaNetComponentMapping\";\nimport { UserNetworkingClientUpdate, WebsocketFactory, WebsocketStatus } from \"./types\";\nimport { UserData } from \"./UserData\";\nimport { CharacterDescription } from \"./UserNetworkingMessages\";\n\nexport type UserNetworkingClientConfig = {\n url: string;\n sessionToken: string;\n websocketFactory: WebsocketFactory;\n statusUpdateCallback: (status: WebsocketStatus) => void;\n assignedIdentity: (clientId: number) => void;\n onServerError: (error: { message: string; errorType: string }) => void;\n onCustomMessage?: (customType: number, contents: string) => void;\n onUpdate(update: NetworkUpdate): void;\n};\n\nexport type AddedUser = {\n userState: UserData;\n components: UserNetworkingClientUpdate;\n};\n\nexport type UpdatedUser = {\n userState?: Partial<UserData>;\n components: UserNetworkingClientUpdate;\n};\n\nexport type NetworkUpdate = {\n removedUserIds: Set<number>;\n addedUserIds: Map<number, AddedUser>;\n updatedUsers: Map<number, UpdatedUser>;\n};\n\nexport class UserNetworkingClient {\n private deltaNetClient: DeltaNetClientWebsocket;\n private deltaNetState: DeltaNetClientState;\n\n private userId: number | null = null;\n private userIndex: number | null = null;\n private userState: UserData = {\n username: null,\n characterDescription: null,\n colors: null,\n };\n\n private stableIdToUserId: Map<number, number> = new Map();\n private userProfiles: Map<number, UserData> = new Map();\n private isAuthenticated = false;\n private pendingUpdate: UserNetworkingClientUpdate;\n\n constructor(\n private config: UserNetworkingClientConfig,\n initialUserState?: UserData,\n initialUpdate?: UserNetworkingClientUpdate,\n ) {\n this.pendingUpdate = initialUpdate ?? {\n position: { x: 0, y: 0, z: 0 },\n rotation: { quaternionY: 0, quaternionW: 1 },\n state: 0,\n };\n this.userState = initialUserState ?? {\n username: null,\n characterDescription: null,\n colors: null,\n };\n this.deltaNetState = new DeltaNetClientState();\n\n // Create deltanet client\n this.deltaNetClient = new DeltaNetClientWebsocket(\n config.url,\n (url: string) => {\n const ws = config.websocketFactory(url);\n return ws;\n },\n config.sessionToken,\n {\n ignoreData: false,\n onInitialCheckout: (initialCheckout: DeltaNetClientWebsocketInitialCheckout) => {\n const { addedStableIds } = this.deltaNetState.handleInitialCheckout(initialCheckout);\n\n // Process any state updates\n const networkUpdate = this.processNetworkUpdate([], addedStableIds, []);\n this.config.onUpdate(networkUpdate);\n\n // Now that we have the user IDs, resolve our stable user ID from the userIndex\n if (this.userIndex !== null) {\n const userIds = this.deltaNetState.getStableIds();\n if (this.userIndex < userIds.length) {\n const stableId = userIds[this.userIndex];\n const userId = this.stableIdToUserId.get(stableId);\n if (!userId) {\n throw new Error(`No userId found for stableId ${stableId}`);\n }\n this.userId = userId;\n this.isAuthenticated = true;\n this.config.assignedIdentity(this.userId);\n } else {\n console.error(\n `Invalid userIndex ${this.userIndex}, userIds length: ${userIds.length}`,\n );\n }\n }\n },\n onTick: (tick: DeltaNetClientWebsocketTick) => {\n const { stateUpdates, removedStableIds, addedStableIds } =\n this.deltaNetState.handleTick(tick);\n // Process state updates\n const networkUpdate = this.processNetworkUpdate(\n removedStableIds,\n addedStableIds,\n stateUpdates,\n );\n this.config.onUpdate(networkUpdate);\n },\n onUserIndex: (userIndex: DeltaNetClientWebsocketUserIndex) => {\n // Store the userIndex and set it on deltanet state\n this.userIndex = userIndex.userIndex;\n this.deltaNetState.setLocalIndex(userIndex.userIndex);\n },\n onError: (errorType: string, errorMessage: string, retryable: boolean) => {\n console.error(\n \"DeltaNet error:\",\n errorType,\n \"errorMessage:\",\n errorMessage,\n \"retryable:\",\n retryable,\n );\n this.config.onServerError({\n message: errorMessage,\n errorType: errorType,\n });\n },\n onWarning: (warning: string) => {\n console.warn(\"DeltaNet warning:\", warning);\n },\n onServerCustom: (customType: number, contents: string) => {\n // Handle server custom messages\n this.config.onCustomMessage?.(customType, contents);\n },\n },\n undefined, // timeCallback is optional\n (status: DeltaNetClientWebsocketStatus) => {\n // Map deltanet status to websocket status\n let mappedStatus: WebsocketStatus;\n switch (status) {\n case DeltaNetClientWebsocketStatus.Connected:\n mappedStatus = WebsocketStatus.Connected;\n break;\n case DeltaNetClientWebsocketStatus.ConnectionOpen:\n this.sendInitialAuthentication();\n mappedStatus = WebsocketStatus.Connected;\n // Send initial authentication data immediately upon connection\n break;\n case DeltaNetClientWebsocketStatus.Disconnected:\n mappedStatus = WebsocketStatus.Disconnected;\n this.reset();\n break;\n case DeltaNetClientWebsocketStatus.Reconnecting:\n mappedStatus = WebsocketStatus.Reconnecting;\n this.reset();\n break;\n default:\n mappedStatus = WebsocketStatus.Disconnected;\n }\n this.config.statusUpdateCallback(mappedStatus);\n },\n );\n }\n\n private reset(): void {\n this.deltaNetState.reset();\n this.userProfiles.clear();\n this.stableIdToUserId.clear();\n this.isAuthenticated = false;\n this.userId = null;\n this.userIndex = null;\n }\n\n private sendInitialAuthentication(): void {\n // Send initial components and states to become \"ready\"\n const components = DeltaNetComponentMapping.toComponents(this.pendingUpdate);\n\n // Create initial states for user data\n const states = DeltaNetComponentMapping.toStates(this.userState);\n\n // Send to deltanet - this makes the client \"ready\" and triggers authentication\n this.deltaNetClient.setUserComponents(components, states);\n }\n\n private processNetworkUpdate(\n removedStableIds: number[],\n addedStableIdsArray: number[],\n stateUpdates: Array<{ stableId: number; stateId: number; state: Uint8Array }>,\n ): NetworkUpdate {\n const addedUserIds = new Map<number, AddedUser>();\n const removedUserIds = new Set<number>();\n\n for (const stableId of removedStableIds) {\n const userId = this.stableIdToUserId.get(stableId);\n if (userId) {\n removedUserIds.add(userId);\n\n // Remove from user profiles\n this.userProfiles.delete(userId);\n\n // Remove from stableIdToUserId\n this.stableIdToUserId.delete(stableId);\n } else {\n throw new Error(`No userId found for stableId ${stableId}`);\n }\n }\n\n for (const stableId of addedStableIdsArray) {\n const stableUserData = this.deltaNetState.byStableId.get(stableId);\n if (!stableUserData) {\n throw new Error(`No stableUserData found for stableId ${stableId}`);\n }\n const userIdState = stableUserData.states.get(STATE_INTERNAL_CONNECTION_ID);\n if (!userIdState) {\n throw new Error(`No userIdState found for stableId ${stableId}`);\n }\n const userId = DeltaNetComponentMapping.userIdFromBytes(userIdState);\n if (!userId) {\n throw new Error(`Failed to extract userId from bytes for stableId ${stableId}`);\n }\n this.stableIdToUserId.set(stableId, userId);\n const newProfile = DeltaNetComponentMapping.fromStates(stableUserData.states);\n this.userProfiles.set(userId, newProfile);\n const clientUpdate = DeltaNetComponentMapping.fromComponents(stableUserData.components);\n addedUserIds.set(userId, {\n userState: newProfile,\n components: clientUpdate,\n });\n }\n\n const updatedUsers = new Map<number, UpdatedUser>();\n\n for (const [stableUserId, userInfo] of this.deltaNetState.byStableId) {\n const userId = this.stableIdToUserId.get(stableUserId);\n if (!userId) {\n throw new Error(`No userId found for stableUserId ${stableUserId}`);\n }\n if (!addedUserIds.has(userId)) {\n if (userInfo.components.size > 0) {\n const clientUpdate = DeltaNetComponentMapping.fromComponents(userInfo.components);\n updatedUsers.set(userId, {\n components: clientUpdate,\n });\n }\n }\n }\n\n for (const update of stateUpdates) {\n // update.stableId is actually a stable user ID maintained by deltanet, not an index\n const stableUserId = update.stableId;\n\n const userId = this.stableIdToUserId.get(stableUserId);\n if (!userId) {\n throw new Error(`No userId found for stableUserId ${stableUserId}`);\n }\n\n if (addedUserIds.has(userId)) {\n continue;\n }\n\n const profile = this.userProfiles.get(userId);\n if (!profile) {\n console.warn(`No profile found for user ${userId}, skipping update`);\n continue;\n }\n const existingUpdate = updatedUsers.get(userId)!;\n let existingUserStateUpdate: Partial<UserData> | undefined = existingUpdate.userState;\n if (!existingUserStateUpdate) {\n existingUserStateUpdate = {};\n existingUpdate.userState = existingUserStateUpdate;\n }\n\n switch (update.stateId) {\n case STATE_INTERNAL_CONNECTION_ID:\n console.error(\"STATE_INTERNAL_CONNECTION_ID is not expected to change in state updates\");\n break;\n case STATE_USERNAME:\n const username = DeltaNetComponentMapping.usernameFromBytes(update.state);\n if (username) {\n profile.username = username;\n existingUserStateUpdate.username = username;\n }\n break;\n case STATE_CHARACTER_DESCRIPTION:\n const characterDescription = DeltaNetComponentMapping.characterDescriptionFromBytes(\n update.state,\n );\n profile.characterDescription = characterDescription;\n existingUserStateUpdate.characterDescription = characterDescription;\n break;\n case STATE_COLORS:\n const colors = DeltaNetComponentMapping.decodeColors(update.state);\n profile.colors = colors;\n existingUserStateUpdate.colors = colors;\n break;\n default:\n console.warn(`Unknown state ID: ${update.stateId}`);\n }\n }\n\n return {\n removedUserIds,\n addedUserIds,\n updatedUsers,\n };\n }\n\n public sendUpdate(update: UserNetworkingClientUpdate): void {\n if (!this.isAuthenticated || this.userId === null) {\n // Store the update to send after authentication\n this.pendingUpdate = update;\n return;\n }\n\n // Convert to deltanet components and send\n const components = DeltaNetComponentMapping.toComponents(update);\n this.deltaNetClient.setUserComponents(components, new Map());\n }\n\n public sendCustomMessage(customType: number, contents: string): void {\n if (!this.isAuthenticated || this.userId === null) {\n console.warn(\"Cannot send custom message before authentication\");\n return;\n }\n\n this.deltaNetClient.sendCustomMessage(customType, contents);\n }\n\n public updateUsername(username: string): void {\n if (!this.isAuthenticated || this.userId === null) {\n return;\n }\n\n // Update local state\n this.userState.username = username;\n\n // Send state update\n const states = DeltaNetComponentMapping.toUsernameState(username);\n this.deltaNetClient.setUserComponents(new Map(), states);\n }\n\n public updateCharacterDescription(characterDescription: CharacterDescription): void {\n if (!this.isAuthenticated || this.userId === null) {\n return;\n }\n\n // Update local state\n this.userState.characterDescription = characterDescription;\n\n // Send state update\n const states = DeltaNetComponentMapping.toCharacterDescriptionState(characterDescription);\n this.deltaNetClient.setUserComponents(new Map(), states);\n }\n\n public updateColors(colors: Array<[number, number, number]>): void {\n if (!this.isAuthenticated || this.userId === null) {\n return;\n }\n\n // Update local state\n this.userState.colors = colors;\n\n // Send state update\n const states = DeltaNetComponentMapping.toColorsState(colors);\n this.deltaNetClient.setUserComponents(new Map(), states);\n }\n\n public stop(): void {\n this.deltaNetClient.stop();\n this.reset();\n }\n}\n", "export type WebsocketFactory = (url: string) => WebSocket;\n\nexport enum WebsocketStatus {\n Connecting,\n Connected,\n Reconnecting,\n Disconnected,\n}\n\nexport type UserNetworkingClientUpdate = {\n position: { x: number; y: number; z: number };\n rotation: { quaternionY: number; quaternionW: number };\n state: number;\n};\n", "export * from \"./UserNetworkingServer\";\nexport * from \"./UserNetworkingClient\";\nexport * from \"./UserData\";\nexport * from \"./types\";\nexport * from \"./UserNetworkingMessages\";\nexport * from \"./legacy/LegacyUserNetworkingMessages\";\nexport * from \"./DeltaNetComponentMapping\";\nexport {\n DeltaNetV01ServerErrors,\n deltaNetProtocolSubProtocol_v0_1,\n} from \"@mml-io/delta-net-protocol\";\n"],
5
- "mappings": "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",
3
+ "sources": ["../src/UserNetworkingServer.ts", "../src/DeltaNetComponentMapping.ts", "../src/UserNetworkingMessages.ts", "../src/legacy/LegacyUserNetworkingCodec.ts", "../src/legacy/LegacyUserNetworkingMessages.ts", "../src/legacy/LegacyAdapter.ts", "../src/UserNetworkingLogger.ts", "../src/UserNetworkingClient.ts", "../src/types.ts", "../src/index.ts"],
4
+ "sourcesContent": ["import { encodeError, DeltaNetV01ServerErrors } from \"@mml-io/delta-net-protocol\";\nimport {\n DeltaNetServer,\n DeltaNetServerError,\n DeltaNetV01Connection,\n onComponentsUpdateOptions,\n onCustomMessageOptions,\n onJoinerOptions,\n onLeaveOptions,\n onStatesUpdateOptions,\n} from \"@mml-io/delta-net-server\";\n\nimport { DeltaNetComponentMapping } from \"./DeltaNetComponentMapping\";\nimport { LegacyAdapter } from \"./legacy/LegacyAdapter\";\nimport {\n LegacyUserIdentity,\n LegacyCharacterDescription,\n} from \"./legacy/LegacyUserNetworkingMessages\";\nimport { UserData } from \"./UserData\";\nimport { UserNetworkingConsoleLogger, UserNetworkingLogger } from \"./UserNetworkingLogger\";\nimport {\n FROM_CLIENT_CHAT_MESSAGE_TYPE,\n FROM_SERVER_CHAT_MESSAGE_TYPE,\n parseClientChatMessage,\n ServerChatMessage,\n UserNetworkingServerError,\n CharacterDescription,\n} from \"./UserNetworkingMessages\";\n\nexport type UserNetworkingServerClient = {\n socket: WebSocket;\n id: number;\n lastPong: number;\n authenticatedUser: UserData | null;\n // May be null for legacy clients\n deltaNetConnection: DeltaNetV01Connection | null;\n};\n\nexport type UserNetworkingServerOptions = {\n legacyAdapterEnabled?: boolean;\n onClientConnect: (\n clientId: number,\n sessionToken: string,\n userIdentity?: UserData,\n ) => Promise<UserData | true | Error> | UserData | true | Error;\n onClientUserIdentityUpdate: (\n clientId: number,\n userIdentity: UserData,\n ) => Promise<UserData | null | false | true | Error> | UserData | null | false | true | Error;\n onClientDisconnect: (clientId: number) => void;\n};\n\nexport class UserNetworkingServer {\n private deltaNetServer: DeltaNetServer;\n private authenticatedClientsById: Map<number, UserNetworkingServerClient> = new Map();\n private tickInterval: NodeJS.Timeout;\n private legacyAdapter: LegacyAdapter | null = null;\n private updatedUserProfilesInTick: Set<number> = new Set();\n\n constructor(\n private options: UserNetworkingServerOptions,\n private logger: UserNetworkingLogger = new UserNetworkingConsoleLogger(),\n ) {\n this.deltaNetServer = new DeltaNetServer({\n serverConnectionIdStateId: 0,\n onJoiner: (joiner: onJoinerOptions) => {\n return this.handleJoiner(joiner);\n },\n onLeave: (leave: onLeaveOptions) => {\n this.handleLeave(leave);\n },\n onComponentsUpdate: (update: onComponentsUpdateOptions) => {\n // TODO - potentially check that components are valid (e.g. rotation is 0 to 2pi)\n return; // No error\n },\n onStatesUpdate: (update: onStatesUpdateOptions) => {\n return this.handleStatesUpdate(update);\n },\n onCustomMessage: (customMessage: onCustomMessageOptions) => {\n this.handleCustomMessage(customMessage);\n },\n });\n if (this.options.legacyAdapterEnabled) {\n this.legacyAdapter = new LegacyAdapter(this, this.deltaNetServer, this.logger);\n }\n\n // Start the deltanet server tick\n this.tickInterval = setInterval(() => {\n const { removedIds, addedIds } = this.deltaNetServer.tick();\n if (this.legacyAdapter) {\n this.legacyAdapter.sendUpdates(removedIds, addedIds, this.updatedUserProfilesInTick);\n this.updatedUserProfilesInTick.clear();\n }\n }, 50);\n }\n\n getCharacterDescription(connectionId: number): LegacyCharacterDescription {\n const client = this.authenticatedClientsById.get(connectionId);\n return client?.authenticatedUser?.characterDescription ?? { mmlCharacterUrl: \"\" };\n }\n getUsername(connectionId: number): string {\n const client = this.authenticatedClientsById.get(connectionId);\n this.logger.info(\"getUsername\", connectionId, client?.authenticatedUser?.username);\n return client?.authenticatedUser?.username ?? \"\";\n }\n\n public getLegacyClientId() {\n return this.deltaNetServer.getNextConnectionId();\n }\n\n public hasCapacityForLegacyClient() {\n return true;\n }\n\n public onLegacyClientConnect(\n id: number,\n sessionToken: string,\n userIdentity: LegacyUserIdentity | undefined,\n ): Promise<UserData | true | Error> | UserData | true | Error {\n return this.options.onClientConnect(id, sessionToken, {\n username: userIdentity?.username ?? null,\n characterDescription: userIdentity?.characterDescription ?? null,\n colors: null,\n });\n }\n\n public setAuthenticatedLegacyClientConnection(\n clientId: number,\n webSocket: WebSocket,\n userData: UserData,\n ) {\n this.logger.info(\"setAuthenticatedLegacyClientConnection\", clientId, userData);\n const authenticatedClient: UserNetworkingServerClient = {\n id: clientId,\n socket: webSocket,\n lastPong: Date.now(),\n authenticatedUser: userData,\n deltaNetConnection: null,\n };\n this.authenticatedClientsById.set(clientId, authenticatedClient);\n }\n\n public onLegacyClientDisconnect(id: number) {\n this.options.onClientDisconnect(id);\n }\n\n private handleStatesUpdate(\n update: onStatesUpdateOptions,\n ):\n | DeltaNetServerError\n | void\n | { success: true; stateOverrides?: Array<[number, Uint8Array]> }\n | Promise<\n DeltaNetServerError | void | { success: true; stateOverrides?: Array<[number, Uint8Array]> }\n > {\n const deltaNetConnection = update.deltaNetV01Connection;\n const clientId = deltaNetConnection.internalConnectionId;\n const updatedStates = update.states;\n const updatedStatesMap = new Map<number, Uint8Array>(updatedStates);\n const updatedUserData: UserData = DeltaNetComponentMapping.fromUserStates(\n updatedStatesMap,\n this.logger,\n );\n\n const existingClient = this.authenticatedClientsById.get(clientId);\n if (!existingClient) {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User not authenticated - no client found\",\n false,\n );\n }\n const existingUserData = existingClient.authenticatedUser ?? {};\n const userData = {\n ...existingUserData,\n ...updatedUserData,\n };\n\n const res = this.options.onClientUserIdentityUpdate(clientId, userData);\n if (res instanceof Promise) {\n return res.then((res) => {\n if (!this.authenticatedClientsById.get(clientId)) {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User not authenticated - client disconnected\",\n false,\n );\n }\n\n if (res instanceof DeltaNetServerError) {\n return res;\n }\n if (res instanceof Error) {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User identity update failed\",\n false,\n );\n }\n if (res === null) {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User identity update failed\",\n false,\n );\n }\n if (res === false) {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User identity update failed\",\n false,\n );\n }\n if (!res || typeof res !== \"object\") {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User identity update failed\",\n false,\n );\n }\n\n this.updatedUserProfilesInTick.add(clientId);\n\n existingClient.authenticatedUser = {\n ...existingClient.authenticatedUser,\n ...res,\n };\n\n return {\n success: true,\n stateOverrides: Array.from(DeltaNetComponentMapping.toStates(res).entries()),\n };\n });\n }\n if (res instanceof DeltaNetServerError) {\n return res;\n }\n if (res instanceof Error) {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User identity update failed\",\n false,\n );\n }\n if (res === null) {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User identity update failed\",\n false,\n );\n }\n if (res === false) {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User identity update failed\",\n false,\n );\n }\n if (!res || typeof res !== \"object\") {\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"User identity update failed\",\n false,\n );\n }\n\n this.updatedUserProfilesInTick.add(clientId);\n\n existingClient.authenticatedUser = {\n ...existingClient.authenticatedUser,\n ...res,\n };\n\n return {\n success: true,\n stateOverrides: Array.from(DeltaNetComponentMapping.toStates(res).entries()),\n };\n }\n\n private handleJoiner(\n joiner: onJoinerOptions,\n ):\n | DeltaNetServerError\n | void\n | { success: true; stateOverrides?: Array<[number, Uint8Array]> }\n | Promise<\n DeltaNetServerError | void | { success: true; stateOverrides?: Array<[number, Uint8Array]> }\n > {\n const deltaNetConnection = joiner.deltaNetV01Connection as DeltaNetV01Connection;\n const webSocket = deltaNetConnection.webSocket as unknown as WebSocket;\n const states = joiner.states as Array<[number, Uint8Array]>;\n const clientId = joiner.internalConnectionId;\n\n const statesMap = new Map<number, Uint8Array>(states);\n const userData: UserData = DeltaNetComponentMapping.fromUserStates(statesMap, this.logger);\n\n // Handle authentication and return the result with state overrides\n return this.handleDeltaNetAuthentication(\n clientId,\n webSocket,\n deltaNetConnection,\n joiner.token,\n userData,\n )\n .then((authResult) => {\n if (!authResult.success) {\n // Authentication failed - return error to reject connection\n this.logger.warn(`Authentication failed for client ID: ${clientId}`, authResult.error);\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n authResult.error?.message || \"Authentication failed\",\n false,\n );\n } else {\n // Return success with state overrides\n return {\n success: true as const,\n stateOverrides: authResult.stateOverrides,\n };\n }\n })\n .catch((error) => {\n this.logger.error(`Authentication error for client ID: ${clientId}:`, error);\n return new DeltaNetServerError(\n DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,\n \"Authentication error\",\n false,\n );\n });\n }\n\n private handleLeave(leave: onLeaveOptions): void {\n const deltaNetConnection = leave.deltaNetV01Connection as DeltaNetV01Connection;\n const clientId = deltaNetConnection.internalConnectionId;\n\n if (clientId !== undefined) {\n const client = this.authenticatedClientsById.get(clientId);\n if (client) {\n this.options.onClientDisconnect(clientId);\n this.authenticatedClientsById.delete(clientId);\n }\n }\n }\n\n private handleCustomMessage(customMessage: onCustomMessageOptions): void {\n const deltaNetConnection = customMessage.deltaNetV01Connection;\n const clientId = deltaNetConnection.internalConnectionId;\n\n const client = this.authenticatedClientsById.get(clientId);\n if (client && client.authenticatedUser) {\n // Handle chat messages\n if (customMessage.customType === FROM_CLIENT_CHAT_MESSAGE_TYPE) {\n const chatMessage = parseClientChatMessage(customMessage.contents);\n if (chatMessage instanceof Error) {\n this.logger.error(`Invalid chat message from client ${clientId}:`, chatMessage);\n } else {\n const serverChatMessage: ServerChatMessage = {\n fromUserId: clientId,\n message: chatMessage.message,\n };\n // Broadcast the chat message to all other clients\n this.deltaNetServer.broadcastCustomMessage(\n FROM_SERVER_CHAT_MESSAGE_TYPE,\n JSON.stringify(serverChatMessage),\n );\n }\n }\n } else {\n this.logger.warn(`Custom message from unauthenticated client ${clientId} - ignoring`);\n }\n }\n\n private async handleDeltaNetAuthentication(\n clientId: number,\n webSocket: WebSocket,\n deltaNetConnection: DeltaNetV01Connection,\n sessionToken: string,\n userIdentity: UserData,\n ): Promise<\n | { success: true; stateOverrides?: Array<[number, Uint8Array]> }\n | { success: false; error?: Error }\n > {\n try {\n // For observers, we might want to allow anonymous access or use a different authentication flow\n let onClientConnectReturn = deltaNetConnection.isObserver\n ? null // Observers don't need user data\n : await this.options.onClientConnect(clientId, sessionToken, userIdentity);\n\n if (!deltaNetConnection.isObserver && !onClientConnectReturn) {\n this.logger.warn(`Authentication failed for client ${clientId} - no user data returned`);\n return { success: false };\n }\n\n if (onClientConnectReturn instanceof Error) {\n return { success: false, error: onClientConnectReturn };\n }\n\n if (onClientConnectReturn === true) {\n onClientConnectReturn = userIdentity;\n }\n\n const authenticatedUser: UserData | null = onClientConnectReturn;\n\n // Create authenticated client\n const authenticatedClient: UserNetworkingServerClient = {\n id: clientId,\n socket: webSocket,\n lastPong: Date.now(),\n authenticatedUser,\n deltaNetConnection: deltaNetConnection,\n };\n this.authenticatedClientsById.set(clientId, authenticatedClient);\n\n // Create state overrides with the user data from the authenticator\n // Observers don't have user data, so no state overrides\n let stateOverrides: Array<[number, Uint8Array]> = [];\n if (onClientConnectReturn) {\n const officialStates = DeltaNetComponentMapping.toStates(onClientConnectReturn);\n stateOverrides = Array.from(officialStates.entries());\n }\n\n return {\n success: true,\n stateOverrides: stateOverrides,\n };\n } catch (error) {\n this.logger.error(\"Authentication error:\", error);\n return { success: false };\n }\n }\n\n public connectClient(socket: WebSocket): void {\n if (socket.protocol === \"\") {\n // This is likely a legacy client that does not support deltanet - use legacy adapter if enabled\n if (this.legacyAdapter) {\n this.legacyAdapter.addWebSocket(socket as unknown as globalThis.WebSocket);\n return;\n } else {\n socket.close(1000, \"Legacy client detected (no subprotocol) - not supported\");\n return;\n }\n }\n\n // Add websocket to deltanet server\n this.deltaNetServer.addWebSocket(socket as unknown as globalThis.WebSocket);\n\n socket.addEventListener(\"close\", () => {\n this.deltaNetServer.removeWebSocket(socket as unknown as globalThis.WebSocket);\n });\n }\n\n public broadcastMessage(broadcastType: number, broadcastPayload: string): void {\n this.deltaNetServer.broadcastCustomMessage(broadcastType, broadcastPayload);\n if (this.legacyAdapter) {\n this.legacyAdapter.broadcastMessage(broadcastType, broadcastPayload);\n }\n }\n\n public updateUserCharacter(clientId: number, userData: UserData): void {\n this.logger.info(\"updateUserCharacter\", clientId, userData);\n this.internalUpdateUser(clientId, userData);\n }\n\n public updateUserUsername(clientId: number, username: string): void {\n const client = this.authenticatedClientsById.get(clientId);\n if (!client || !client.authenticatedUser) return;\n\n // Update local user data by creating a new UserData object\n client.authenticatedUser = {\n ...client.authenticatedUser,\n username: username,\n };\n\n this.updatedUserProfilesInTick.add(clientId);\n\n // Update deltanet states with just the username\n const states = DeltaNetComponentMapping.toUsernameState(username);\n const asArray = Array.from(states.entries());\n this.deltaNetServer.overrideUserStates(client.deltaNetConnection, clientId, asArray);\n }\n\n public updateUserCharacterDescription(\n clientId: number,\n characterDescription: CharacterDescription,\n ): void {\n const client = this.authenticatedClientsById.get(clientId);\n if (!client || !client.authenticatedUser) return;\n\n // Update local user data by creating a new UserData object\n client.authenticatedUser = {\n ...client.authenticatedUser,\n characterDescription: characterDescription,\n };\n\n this.updatedUserProfilesInTick.add(clientId);\n\n // Update deltanet states with just the character description\n const states = DeltaNetComponentMapping.toCharacterDescriptionState(characterDescription);\n const asArray = Array.from(states.entries());\n this.deltaNetServer.overrideUserStates(client.deltaNetConnection, clientId, asArray);\n }\n\n public updateUserColors(clientId: number, colors: Array<[number, number, number]>): void {\n const client = this.authenticatedClientsById.get(clientId);\n if (!client || !client.authenticatedUser) return;\n\n // Update local user data by creating a new UserData object\n client.authenticatedUser = {\n ...client.authenticatedUser,\n colors: colors,\n };\n\n this.updatedUserProfilesInTick.add(clientId);\n\n // Update deltanet states with just the colors\n const states = DeltaNetComponentMapping.toColorsState(colors);\n const asArray = Array.from(states.entries());\n this.deltaNetServer.overrideUserStates(client.deltaNetConnection, clientId, asArray);\n }\n\n public updateUserStates(clientId: number, updates: UserData): void {\n const client = this.authenticatedClientsById.get(clientId);\n if (!client || !client.authenticatedUser) return;\n\n const states = new Map<number, Uint8Array>();\n let hasUpdates = false;\n let updatedUserData = client.authenticatedUser;\n\n this.updatedUserProfilesInTick.add(clientId);\n\n // Update username if provided\n if (updates.username !== null) {\n updatedUserData = {\n ...updatedUserData,\n username: updates.username,\n };\n const usernameStates = DeltaNetComponentMapping.toUsernameState(updates.username);\n for (const [stateId, stateValue] of usernameStates) {\n states.set(stateId, stateValue);\n }\n hasUpdates = true;\n }\n\n // Update character description if provided\n if (updates.characterDescription !== null) {\n updatedUserData = {\n ...updatedUserData,\n characterDescription: updates.characterDescription,\n };\n const characterDescStates = DeltaNetComponentMapping.toCharacterDescriptionState(\n updates.characterDescription,\n );\n for (const [stateId, stateValue] of characterDescStates) {\n states.set(stateId, stateValue);\n }\n hasUpdates = true;\n }\n\n // Update colors if provided\n if (updates.colors !== null) {\n updatedUserData = {\n ...updatedUserData,\n colors: updates.colors,\n };\n const colorsStates = DeltaNetComponentMapping.toColorsState(updates.colors);\n for (const [stateId, stateValue] of colorsStates) {\n states.set(stateId, stateValue);\n }\n hasUpdates = true;\n }\n\n // Only send update if there are changes\n if (hasUpdates) {\n client.authenticatedUser = updatedUserData;\n const asArray = Array.from(states.entries());\n this.deltaNetServer.overrideUserStates(client.deltaNetConnection, clientId, asArray);\n }\n }\n\n private internalUpdateUser(clientId: number, userData: UserData): void {\n const client = this.authenticatedClientsById.get(clientId);\n if (!client) {\n throw new Error(`internalUpdateUser - client not found for clientId ${clientId}`);\n }\n this.logger.info(\"internalUpdateUser\", clientId, userData);\n\n this.updatedUserProfilesInTick.add(clientId);\n\n client.authenticatedUser = {\n ...client.authenticatedUser,\n ...userData,\n };\n\n // Update deltanet states\n const states = DeltaNetComponentMapping.toStates(userData);\n\n const asArray = Array.from(states.entries());\n this.deltaNetServer.overrideUserStates(client.deltaNetConnection, clientId, asArray);\n }\n\n public dispose(clientCloseError?: UserNetworkingServerError): void {\n if (this.tickInterval) {\n clearInterval(this.tickInterval);\n }\n\n let errorMessage: Uint8Array | null = null;\n if (clientCloseError) {\n errorMessage = encodeError({\n type: \"error\",\n errorType: clientCloseError.errorType,\n message: clientCloseError.message,\n retryable: clientCloseError.retryable,\n }).getBuffer();\n }\n\n // Close all client connections\n for (const [, client] of this.authenticatedClientsById) {\n if (errorMessage) {\n client.socket.send(errorMessage);\n }\n client.socket.close();\n }\n\n this.authenticatedClientsById.clear();\n }\n}\n", "import { BufferReader, BufferWriter } from \"@mml-io/delta-net-protocol\";\n\nimport { UserNetworkingClientUpdate } from \"./types\";\nimport { UserData } from \"./UserData\";\nimport { UserNetworkingLogger } from \"./UserNetworkingLogger\";\nimport { CharacterDescription } from \"./UserNetworkingMessages\";\n\n// Component IDs used in the deltanet implementation\nexport const COMPONENT_POSITION_X = 1;\nexport const COMPONENT_POSITION_Y = 2;\nexport const COMPONENT_POSITION_Z = 3;\nexport const COMPONENT_ROTATION_Y = 4;\nexport const COMPONENT_ROTATION_W = 5;\nexport const COMPONENT_STATE = 6;\n\n// State IDs for binary data\nexport const STATE_INTERNAL_CONNECTION_ID = 0;\nexport const STATE_CHARACTER_DESCRIPTION = 1;\nexport const STATE_USERNAME = 2;\nexport const STATE_COLORS = 3;\n\nexport const rotationMultiplier = 360;\nexport const positionMultiplier = 100;\nconst textDecoder = new TextDecoder();\n\nexport class DeltaNetComponentMapping {\n /**\n * Convert UserNetworkingClientUpdate to deltanet components\n */\n static toComponents(update: UserNetworkingClientUpdate): Map<number, bigint> {\n const components = new Map<number, bigint>();\n\n // Convert position values to fixed-point representation\n components.set(\n COMPONENT_POSITION_X,\n BigInt(Math.round(update.position.x * positionMultiplier)),\n );\n components.set(\n COMPONENT_POSITION_Y,\n BigInt(Math.round(update.position.y * positionMultiplier)),\n );\n components.set(\n COMPONENT_POSITION_Z,\n BigInt(Math.round(update.position.z * positionMultiplier)),\n );\n\n // Convert quaternion values to fixed-point representation\n // Using 32767 scale to match original codec precision\n components.set(\n COMPONENT_ROTATION_Y,\n BigInt(Math.round(update.rotation.quaternionY * rotationMultiplier)),\n );\n components.set(\n COMPONENT_ROTATION_W,\n BigInt(Math.round(update.rotation.quaternionW * rotationMultiplier)),\n );\n\n // State is already an integer\n components.set(COMPONENT_STATE, BigInt(update.state));\n\n return components;\n }\n\n /**\n * Convert deltanet components back to UserNetworkingClientUpdate\n */\n static fromComponents(components: Map<number, bigint>): UserNetworkingClientUpdate {\n const positionX =\n Number(components.get(COMPONENT_POSITION_X) || BigInt(0)) / positionMultiplier;\n const positionY =\n Number(components.get(COMPONENT_POSITION_Y) || BigInt(0)) / positionMultiplier;\n const positionZ =\n Number(components.get(COMPONENT_POSITION_Z) || BigInt(0)) / positionMultiplier;\n const rotationY =\n Number(components.get(COMPONENT_ROTATION_Y) || BigInt(0)) / rotationMultiplier;\n const rotationW =\n Number(components.get(COMPONENT_ROTATION_W) || BigInt(0)) / rotationMultiplier;\n\n const state = Number(components.get(COMPONENT_STATE) || BigInt(0));\n\n return {\n position: { x: positionX, y: positionY, z: positionZ },\n rotation: { quaternionY: rotationY, quaternionW: rotationW },\n state,\n };\n }\n\n /**\n * Encode character description and username to binary states\n */\n static toStates(userIdentity: UserData): Map<number, Uint8Array> {\n const states = new Map<number, Uint8Array>();\n const textEncoder = new TextEncoder();\n\n if (userIdentity.username) {\n // Encode username\n states.set(STATE_USERNAME, textEncoder.encode(userIdentity.username));\n }\n\n // Encode character description as JSON\n if (userIdentity.characterDescription) {\n states.set(\n STATE_CHARACTER_DESCRIPTION,\n textEncoder.encode(JSON.stringify(userIdentity.characterDescription)),\n );\n }\n\n if (userIdentity.colors) {\n states.set(STATE_COLORS, DeltaNetComponentMapping.encodeColors(userIdentity.colors));\n }\n\n return states;\n }\n\n /**\n * Encode username to binary state\n */\n static toUsernameState(username: string): Map<number, Uint8Array> {\n const states = new Map<number, Uint8Array>();\n const textEncoder = new TextEncoder();\n states.set(STATE_USERNAME, textEncoder.encode(username));\n return states;\n }\n\n /**\n * Encode character description to binary state\n */\n static toCharacterDescriptionState(\n characterDescription: CharacterDescription,\n ): Map<number, Uint8Array> {\n const states = new Map<number, Uint8Array>();\n const textEncoder = new TextEncoder();\n states.set(\n STATE_CHARACTER_DESCRIPTION,\n textEncoder.encode(JSON.stringify(characterDescription)),\n );\n return states;\n }\n\n /**\n * Encode colors to binary state\n */\n static toColorsState(colors: Array<[number, number, number]>): Map<number, Uint8Array> {\n const states = new Map<number, Uint8Array>();\n states.set(STATE_COLORS, DeltaNetComponentMapping.encodeColors(colors));\n return states;\n }\n\n /**\n * Encode single state value\n */\n static toSingleState(stateId: number, value: any): Map<number, Uint8Array> {\n const states = new Map<number, Uint8Array>();\n const textEncoder = new TextEncoder();\n\n switch (stateId) {\n case STATE_USERNAME:\n if (typeof value === \"string\") {\n states.set(stateId, textEncoder.encode(value));\n }\n break;\n case STATE_CHARACTER_DESCRIPTION:\n if (typeof value === \"object\" && value !== null) {\n states.set(stateId, textEncoder.encode(JSON.stringify(value)));\n }\n break;\n case STATE_COLORS:\n if (Array.isArray(value)) {\n states.set(stateId, DeltaNetComponentMapping.encodeColors(value));\n }\n break;\n }\n\n return states;\n }\n\n static encodeColors(colors: Array<[number, number, number]>): Uint8Array {\n const bufferWriter = new BufferWriter(3 * colors.length + 1);\n bufferWriter.writeUVarint(colors.length);\n for (const color of colors) {\n bufferWriter.writeUVarint(color[0]);\n bufferWriter.writeUVarint(color[1]);\n bufferWriter.writeUVarint(color[2]);\n }\n return bufferWriter.getBuffer();\n }\n\n static decodeColors(\n colors: Uint8Array,\n logger: UserNetworkingLogger,\n ): Array<[number, number, number]> {\n if (colors.byteLength === 0) {\n return [];\n }\n try {\n const bufferReader = new BufferReader(colors);\n const colorsArray: Array<[number, number, number]> = [];\n const count = bufferReader.readUVarint();\n for (let i = 0; i < count; i++) {\n colorsArray.push([\n bufferReader.readUVarint(),\n bufferReader.readUVarint(),\n bufferReader.readUVarint(),\n ]);\n }\n return colorsArray;\n } catch (e) {\n logger.error(\"Error decoding colors\", colors, e);\n return [];\n }\n }\n\n static fromUserStates(states: Map<number, Uint8Array>, logger: UserNetworkingLogger): UserData {\n const usernameBytes = states.get(STATE_USERNAME);\n const username = usernameBytes\n ? DeltaNetComponentMapping.usernameFromBytes(usernameBytes)\n : null;\n\n const characterDescBytes = states.get(STATE_CHARACTER_DESCRIPTION);\n const characterDescription = characterDescBytes\n ? DeltaNetComponentMapping.characterDescriptionFromBytes(characterDescBytes)\n : null;\n\n const colorsBytes = states.get(STATE_COLORS);\n const colorsArray = colorsBytes\n ? DeltaNetComponentMapping.decodeColors(colorsBytes, logger)\n : [];\n\n return { username, characterDescription, colors: colorsArray };\n }\n\n static userIdFromBytes(bytes: Uint8Array): number | null {\n if (bytes.length === 0) {\n return null;\n }\n const reader = new BufferReader(bytes);\n return reader.readUVarint(false);\n }\n\n static usernameFromBytes(bytes: Uint8Array): string | null {\n if (bytes.length === 0) {\n return null;\n }\n return textDecoder.decode(bytes);\n }\n static characterDescriptionFromBytes(bytes: Uint8Array): CharacterDescription | null {\n if (bytes.length === 0) {\n return null;\n }\n return JSON.parse(textDecoder.decode(bytes));\n }\n\n /**\n * Decode binary states back to username and character description\n */\n static fromStates(\n states: Map<number, Uint8Array>,\n logger: UserNetworkingLogger,\n ): {\n userId: number | null;\n } & UserData {\n const userIdBytes = states.get(STATE_INTERNAL_CONNECTION_ID);\n let userId: number | null = null;\n if (userIdBytes) {\n const reader = new BufferReader(userIdBytes);\n userId = reader.readUVarint(false);\n }\n\n const userStates = DeltaNetComponentMapping.fromUserStates(states, logger);\n\n return { userId, ...userStates };\n }\n}\n", "import { DeltaNetServerError } from \"@mml-io/delta-net-server\";\n\nexport type CharacterDescription =\n | {\n meshFileUrl: string;\n mmlCharacterString?: null;\n mmlCharacterUrl?: null;\n }\n | {\n meshFileUrl?: null;\n mmlCharacterString: string;\n mmlCharacterUrl?: null;\n }\n | {\n meshFileUrl?: null;\n mmlCharacterString?: null;\n mmlCharacterUrl: string;\n };\n\nexport class UserNetworkingServerError extends DeltaNetServerError {}\n\nexport type ClientChatMessage = {\n message: string;\n};\n\nexport type ServerChatMessage = {\n fromUserId: number;\n message: string;\n};\n\nexport type ServerBroadcastMessage = {\n broadcastType: string;\n payload: any;\n};\n\n// Custom message types\nexport const SERVER_BROADCAST_MESSAGE_TYPE = 1;\nexport const FROM_CLIENT_CHAT_MESSAGE_TYPE = 2;\nexport const FROM_SERVER_CHAT_MESSAGE_TYPE = 3;\n\nexport function parseClientChatMessage(contents: string): ClientChatMessage | Error {\n try {\n const parsed = JSON.parse(contents) as unknown;\n if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n \"message\" in parsed &&\n typeof parsed.message === \"string\"\n ) {\n return {\n message: parsed.message as string,\n };\n } else {\n throw new Error(\"Invalid chat message\");\n }\n } catch (error) {\n return new Error(`Invalid chat message: ${error}`);\n }\n}\n\nexport function parseServerChatMessage(contents: string): ServerChatMessage | Error {\n try {\n const parsed = JSON.parse(contents) as unknown;\n if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n \"fromUserId\" in parsed &&\n typeof parsed.fromUserId === \"number\" &&\n \"message\" in parsed &&\n typeof parsed.message === \"string\"\n ) {\n return {\n fromUserId: parsed.fromUserId as number,\n message: parsed.message as string,\n };\n } else {\n throw new Error(\"Invalid server chat message\");\n }\n } catch (error) {\n return new Error(`Invalid server chat message: ${error}`);\n }\n}\n\nexport function parseServerBroadcastMessage(contents: string): ServerBroadcastMessage | Error {\n try {\n const parsed = JSON.parse(contents) as unknown;\n if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n \"broadcastType\" in parsed &&\n typeof parsed.broadcastType === \"string\" &&\n \"payload\" in parsed &&\n typeof parsed.payload === \"object\"\n ) {\n return {\n broadcastType: parsed.broadcastType as string,\n payload: parsed.payload as any,\n };\n } else {\n throw new Error(\"Invalid server broadcast message\");\n }\n } catch (error) {\n return new Error(`Invalid server broadcast message: ${error}`);\n }\n}\n", "export type LegacyUserNetworkingClientUpdate = {\n id: number;\n position: { x: number; y: number; z: number };\n rotation: { quaternionY: number; quaternionW: number };\n state: number;\n};\n\nexport class LegacyUserNetworkingCodec {\n static encodeUpdate(update: LegacyUserNetworkingClientUpdate): Uint8Array {\n const buffer = new ArrayBuffer(19);\n const dataView = new DataView(buffer);\n dataView.setUint16(0, update.id); // id\n dataView.setFloat32(2, update.position.x); // position.x\n dataView.setFloat32(6, update.position.y); // position.y\n dataView.setFloat32(10, update.position.z); // position.z\n dataView.setInt16(14, update.rotation.quaternionY * 32767); // quaternion.y\n dataView.setInt16(16, update.rotation.quaternionW * 32767); // quaternion.w\n dataView.setUint8(18, update.state); // animationState\n return new Uint8Array(buffer);\n }\n\n static decodeUpdate(buffer: ArrayBuffer): LegacyUserNetworkingClientUpdate {\n const dataView = new DataView(buffer);\n const id = dataView.getUint16(0); // id\n const x = dataView.getFloat32(2); // position.x\n const y = dataView.getFloat32(6); // position.y\n const z = dataView.getFloat32(10); // position.z\n const quaternionY = dataView.getInt16(14) / 32767; // quaternion.y\n const quaternionW = dataView.getInt16(16) / 32767; // quaternion.w\n const state = dataView.getUint8(18); // animationState\n const position = { x, y, z };\n const rotation = { quaternionY, quaternionW };\n return { id, position, rotation, state };\n }\n}\n", "export const LEGACY_USER_NETWORKING_DISCONNECTED_MESSAGE_TYPE = \"disconnected\";\nexport const LEGACY_USER_NETWORKING_IDENTITY_MESSAGE_TYPE = \"identity\";\nexport const LEGACY_USER_NETWORKING_USER_AUTHENTICATE_MESSAGE_TYPE = \"user_auth\";\nexport const LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE = \"user_profile\";\nexport const LEGACY_USER_NETWORKING_USER_UPDATE_MESSAGE_TYPE = \"user_update\";\nexport const LEGACY_USER_NETWORKING_SERVER_BROADCAST_MESSAGE_TYPE = \"broadcast\";\nexport const LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE = \"error\";\nexport const LEGACY_USER_NETWORKING_PING_MESSAGE_TYPE = \"ping\";\nexport const LEGACY_USER_NETWORKING_PONG_MESSAGE_TYPE = \"pong\";\n\nexport type LegacyUserNetworkingIdentityMessage = {\n type: typeof LEGACY_USER_NETWORKING_IDENTITY_MESSAGE_TYPE;\n id: number;\n};\n\nexport type LegacyCharacterDescription =\n | {\n meshFileUrl: string;\n mmlCharacterString?: null;\n mmlCharacterUrl?: null;\n }\n | {\n meshFileUrl?: null;\n mmlCharacterString: string;\n mmlCharacterUrl?: null;\n }\n | {\n meshFileUrl?: null;\n mmlCharacterString?: null;\n mmlCharacterUrl: string;\n };\n\nexport type LegacyUserData = {\n readonly username: string;\n readonly characterDescription: LegacyCharacterDescription;\n};\n\nexport type LegacyUserNetworkingProfileMessage = {\n type: typeof LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE;\n id: number;\n username: string;\n characterDescription: LegacyCharacterDescription;\n};\n\nexport type LegacyUserNetworkingDisconnectedMessage = {\n type: typeof LEGACY_USER_NETWORKING_DISCONNECTED_MESSAGE_TYPE;\n id: number;\n};\n\nexport const LEGACY_USER_NETWORKING_CONNECTION_LIMIT_REACHED_ERROR_TYPE =\n \"CONNECTION_LIMIT_REACHED\";\nexport const LEGACY_USER_NETWORKING_AUTHENTICATION_FAILED_ERROR_TYPE = \"AUTHENTICATION_FAILED\";\nexport const LEGACY_USER_NETWORKING_SERVER_SHUTDOWN_ERROR_TYPE = \"SERVER_SHUTDOWN\";\nexport const LEGACY_USER_NETWORKING_UNKNOWN_ERROR = \"UNKNOWN_ERROR\";\n\nexport type LegacyUserNetworkingServerErrorType =\n | typeof LEGACY_USER_NETWORKING_CONNECTION_LIMIT_REACHED_ERROR_TYPE\n | typeof LEGACY_USER_NETWORKING_AUTHENTICATION_FAILED_ERROR_TYPE\n | typeof LEGACY_USER_NETWORKING_SERVER_SHUTDOWN_ERROR_TYPE\n | typeof LEGACY_USER_NETWORKING_UNKNOWN_ERROR;\n\nexport type LegacyUserNetworkingServerError = {\n type: typeof LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE;\n errorType: LegacyUserNetworkingServerErrorType;\n message: string;\n};\n\nexport type LegacyUserNetworkingServerBroadcast = {\n type: typeof LEGACY_USER_NETWORKING_SERVER_BROADCAST_MESSAGE_TYPE;\n broadcastType: string;\n payload: any;\n};\n\nexport type LegacyUserNetworkingServerPingMessage = {\n type: typeof LEGACY_USER_NETWORKING_PING_MESSAGE_TYPE;\n};\n\nexport type LegacyFromUserNetworkingServerMessage =\n | LegacyUserNetworkingIdentityMessage\n | LegacyUserNetworkingProfileMessage\n | LegacyUserNetworkingDisconnectedMessage\n | LegacyUserNetworkingServerPingMessage\n | LegacyUserNetworkingServerBroadcast\n | LegacyUserNetworkingServerError;\n\nexport type LegacyUserNetworkingClientPongMessage = {\n type: typeof LEGACY_USER_NETWORKING_PONG_MESSAGE_TYPE;\n};\n\nexport type LegacyUserIdentity = {\n characterDescription: LegacyCharacterDescription | null;\n username: string | null;\n};\n\nexport type LegacyUserNetworkingAuthenticateMessage = {\n type: typeof LEGACY_USER_NETWORKING_USER_AUTHENTICATE_MESSAGE_TYPE;\n sessionToken: string;\n // The client can send a LegacyUserIdentity to use as the initial user profile and the server can choose to accept it or not\n userIdentity?: LegacyUserIdentity;\n};\n\nexport type LegacyUserNetworkingUserUpdateMessage = {\n type: typeof LEGACY_USER_NETWORKING_USER_UPDATE_MESSAGE_TYPE;\n userIdentity: LegacyUserIdentity;\n};\n\nexport type LegacyFromUserNetworkingClientMessage =\n | LegacyUserNetworkingClientPongMessage\n | LegacyUserNetworkingAuthenticateMessage\n | LegacyUserNetworkingUserUpdateMessage;\n", "import { DeltaNetServer } from \"@mml-io/delta-net-server\";\n\nimport {\n COMPONENT_POSITION_X,\n COMPONENT_ROTATION_W,\n COMPONENT_POSITION_Y,\n COMPONENT_POSITION_Z,\n COMPONENT_ROTATION_Y,\n COMPONENT_STATE,\n rotationMultiplier,\n positionMultiplier,\n} from \"../DeltaNetComponentMapping\";\nimport { UserData } from \"../UserData\";\nimport { UserNetworkingLogger } from \"../UserNetworkingLogger\";\nimport {\n parseServerBroadcastMessage,\n SERVER_BROADCAST_MESSAGE_TYPE,\n} from \"../UserNetworkingMessages\";\nimport { UserNetworkingServer } from \"../UserNetworkingServer\";\n\nimport {\n LegacyUserNetworkingClientUpdate,\n LegacyUserNetworkingCodec,\n} from \"./LegacyUserNetworkingCodec\";\nimport {\n LEGACY_USER_NETWORKING_AUTHENTICATION_FAILED_ERROR_TYPE,\n LEGACY_USER_NETWORKING_CONNECTION_LIMIT_REACHED_ERROR_TYPE,\n LEGACY_USER_NETWORKING_DISCONNECTED_MESSAGE_TYPE,\n LEGACY_USER_NETWORKING_IDENTITY_MESSAGE_TYPE,\n LEGACY_USER_NETWORKING_PONG_MESSAGE_TYPE,\n LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE,\n LEGACY_USER_NETWORKING_UNKNOWN_ERROR,\n LEGACY_USER_NETWORKING_USER_AUTHENTICATE_MESSAGE_TYPE,\n LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE,\n LEGACY_USER_NETWORKING_USER_UPDATE_MESSAGE_TYPE,\n LegacyFromUserNetworkingClientMessage,\n LegacyFromUserNetworkingServerMessage,\n LegacyUserData,\n LegacyUserNetworkingAuthenticateMessage,\n LegacyUserNetworkingServerBroadcast,\n LegacyUserNetworkingServerError,\n LegacyUserNetworkingUserUpdateMessage,\n} from \"./LegacyUserNetworkingMessages\";\n\nexport type LegacyUserNetworkingServerClient = {\n socket: WebSocket;\n id: number;\n lastPong: number;\n update: LegacyUserNetworkingClientUpdate;\n authenticatedUser: LegacyUserData | null;\n};\n\nfunction toArrayBuffer(buffer: Buffer) {\n const arrayBuffer = new ArrayBuffer(buffer.length);\n const view = new Uint8Array(arrayBuffer);\n for (let i = 0; i < buffer.length; ++i) {\n view[i] = buffer[i];\n }\n return arrayBuffer;\n}\n\nconst WebSocketOpenStatus = 1;\n\nexport class LegacyAdapter {\n private allClientsById: Map<number, LegacyUserNetworkingServerClient> = new Map();\n private legacyAuthenticatedClientsById: Map<number, LegacyUserNetworkingServerClient> = new Map();\n\n constructor(\n private readonly userNetworkingServer: UserNetworkingServer,\n private readonly deltaNetServer: DeltaNetServer,\n private logger: UserNetworkingLogger,\n ) {}\n\n public broadcastMessage(broadcastType: number, broadcastPayload: string) {\n // The new broadcast type is a number and then the payload is a string\n // \"Broadcast\" messages intended for legacy clients are only the SERVER_BROADCAST_MESSAGE_TYPE\n if (broadcastType !== SERVER_BROADCAST_MESSAGE_TYPE) {\n return;\n }\n\n const parsedPayload = parseServerBroadcastMessage(broadcastPayload);\n if (parsedPayload instanceof Error) {\n this.logger.error(\"Error parsing server broadcast message\", parsedPayload);\n return;\n }\n\n const { broadcastType: broadcastTypeString, payload } = parsedPayload;\n\n const message: LegacyUserNetworkingServerBroadcast = {\n type: \"broadcast\",\n broadcastType: broadcastTypeString,\n payload: payload,\n };\n const messageString = JSON.stringify(message);\n for (const [, client] of this.legacyAuthenticatedClientsById) {\n if (client.socket.readyState === WebSocketOpenStatus) {\n client.socket.send(messageString);\n }\n }\n }\n\n public addWebSocket(socket: WebSocket) {\n const id = this.userNetworkingServer.getLegacyClientId();\n\n // Create a client but without user information\n const client: LegacyUserNetworkingServerClient = {\n id,\n lastPong: Date.now(),\n socket: socket as WebSocket,\n authenticatedUser: null,\n update: {\n id,\n position: { x: 0, y: 0, z: 0 },\n rotation: { quaternionY: 0, quaternionW: 1 },\n state: 0,\n },\n };\n this.allClientsById.set(id, client);\n\n socket.addEventListener(\"message\", (message: MessageEvent) => {\n try {\n if (message.data instanceof ArrayBuffer || message.data instanceof Buffer) {\n if (client.authenticatedUser) {\n const arrayBuffer =\n message.data instanceof ArrayBuffer ? message.data : toArrayBuffer(message.data);\n const update = LegacyUserNetworkingCodec.decodeUpdate(arrayBuffer);\n update.id = id;\n const index = this.deltaNetServer.dangerouslyGetConnectionsToComponentIndex().get(id);\n client.update = update;\n if (index !== undefined) {\n this.deltaNetServer.setComponentValue(\n COMPONENT_POSITION_X,\n index,\n BigInt(Math.round(update.position.x * positionMultiplier)),\n );\n this.deltaNetServer.setComponentValue(\n COMPONENT_POSITION_Y,\n index,\n BigInt(Math.round(update.position.y * positionMultiplier)),\n );\n this.deltaNetServer.setComponentValue(\n COMPONENT_POSITION_Z,\n index,\n BigInt(Math.round(update.position.z * positionMultiplier)),\n );\n this.deltaNetServer.setComponentValue(\n COMPONENT_ROTATION_Y,\n index,\n BigInt(Math.round(update.rotation.quaternionY * rotationMultiplier)),\n );\n this.deltaNetServer.setComponentValue(\n COMPONENT_ROTATION_W,\n index,\n BigInt(Math.round(update.rotation.quaternionW * rotationMultiplier)),\n );\n this.deltaNetServer.setComponentValue(\n COMPONENT_STATE,\n index,\n BigInt(Math.round(update.state)),\n );\n }\n }\n } else {\n let parsed;\n try {\n parsed = JSON.parse(message.data as string) as LegacyFromUserNetworkingClientMessage;\n } catch (e) {\n this.logger.error(\"Error parsing JSON message\", message, e);\n return;\n }\n if (!client.authenticatedUser) {\n if (parsed.type === LEGACY_USER_NETWORKING_USER_AUTHENTICATE_MESSAGE_TYPE) {\n this.handleUserAuth(client, parsed).then((authResult) => {\n if (client.socket.readyState !== WebSocketOpenStatus) {\n // The client disconnected before the authentication was completed\n return;\n }\n if (!authResult) {\n this.logger.error(`Client-id ${client.id} user_auth failed`, authResult);\n // If the user is not authorized, disconnect the client\n const serverError = JSON.stringify({\n type: LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE,\n errorType: LEGACY_USER_NETWORKING_AUTHENTICATION_FAILED_ERROR_TYPE,\n message: \"Authentication failed\",\n } as LegacyFromUserNetworkingServerMessage);\n socket.send(serverError);\n socket.close();\n } else {\n if (!this.userNetworkingServer.hasCapacityForLegacyClient()) {\n // There is a connection limit and it has been met - disconnect the user\n const serverError = JSON.stringify({\n type: LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE,\n errorType: LEGACY_USER_NETWORKING_CONNECTION_LIMIT_REACHED_ERROR_TYPE,\n message: \"Connection limit reached\",\n } as LegacyFromUserNetworkingServerMessage);\n socket.send(serverError);\n socket.close();\n return;\n }\n\n const userData = authResult;\n\n this.deltaNetServer.dangerouslyAddNewJoinerCallback((index) => {\n if (client.socket.readyState !== WebSocketOpenStatus) {\n return null;\n }\n client.authenticatedUser = userData;\n this.deltaNetServer.setComponentValue(COMPONENT_POSITION_X, index, BigInt(0));\n this.deltaNetServer.setComponentValue(COMPONENT_POSITION_Y, index, BigInt(0));\n this.deltaNetServer.setComponentValue(COMPONENT_POSITION_Z, index, BigInt(0));\n this.deltaNetServer.setComponentValue(COMPONENT_ROTATION_Y, index, BigInt(0));\n this.deltaNetServer.setComponentValue(COMPONENT_ROTATION_W, index, BigInt(0));\n this.deltaNetServer.setComponentValue(COMPONENT_STATE, index, BigInt(0));\n\n const asUserData: UserData = {\n ...userData,\n colors: [],\n };\n return {\n id: client.id,\n afterAddCallback: () => {\n this.userNetworkingServer.setAuthenticatedLegacyClientConnection(\n client.id,\n client.socket,\n asUserData,\n );\n this.userNetworkingServer.updateUserCharacter(client.id, asUserData);\n },\n };\n });\n\n // Give the client its own profile\n const userProfileMessage = JSON.stringify({\n id: client.id,\n type: LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE,\n username: userData.username,\n characterDescription: userData.characterDescription,\n } as LegacyFromUserNetworkingServerMessage);\n client.socket.send(userProfileMessage);\n\n // Give the client its own identity\n const identityMessage = JSON.stringify({\n id: client.id,\n type: LEGACY_USER_NETWORKING_IDENTITY_MESSAGE_TYPE,\n } as LegacyFromUserNetworkingServerMessage);\n client.socket.send(identityMessage);\n\n const allUsers: Map<number, number> =\n this.deltaNetServer.dangerouslyGetConnectionsToComponentIndex();\n for (const [connectionId, componentIndex] of allUsers) {\n if (connectionId === client.id) {\n continue;\n }\n const x =\n this.deltaNetServer.getComponentValue(COMPONENT_POSITION_X, componentIndex) /\n positionMultiplier;\n const y =\n this.deltaNetServer.getComponentValue(COMPONENT_POSITION_Y, componentIndex) /\n positionMultiplier;\n const z =\n this.deltaNetServer.getComponentValue(COMPONENT_POSITION_Z, componentIndex) /\n positionMultiplier;\n const quaternionY =\n this.deltaNetServer.getComponentValue(COMPONENT_ROTATION_Y, componentIndex) /\n rotationMultiplier;\n const quaternionW =\n this.deltaNetServer.getComponentValue(COMPONENT_ROTATION_W, componentIndex) /\n rotationMultiplier;\n const state = this.deltaNetServer.getComponentValue(\n COMPONENT_STATE,\n componentIndex,\n );\n const update = LegacyUserNetworkingCodec.encodeUpdate({\n id: connectionId,\n position: { x, y, z },\n rotation: { quaternionY, quaternionW },\n state,\n });\n // Send the update about the other user to the newly connected client\n client.socket.send(\n JSON.stringify({\n id: connectionId,\n type: LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE,\n username: this.userNetworkingServer.getUsername(connectionId),\n characterDescription:\n this.userNetworkingServer.getCharacterDescription(connectionId),\n } satisfies LegacyFromUserNetworkingServerMessage),\n );\n client.socket.send(update);\n }\n\n this.legacyAuthenticatedClientsById.set(id, client);\n }\n });\n } else {\n this.logger.error(`Unhandled message pre-auth: ${JSON.stringify(parsed)}`);\n socket.close();\n }\n } else {\n switch (parsed.type) {\n case LEGACY_USER_NETWORKING_PONG_MESSAGE_TYPE:\n client.lastPong = Date.now();\n break;\n\n case LEGACY_USER_NETWORKING_USER_UPDATE_MESSAGE_TYPE:\n this.handleUserUpdate(id, parsed as LegacyUserNetworkingUserUpdateMessage);\n break;\n\n default:\n this.logger.error(`Unhandled message: ${JSON.stringify(parsed)}`);\n }\n }\n }\n } catch (e) {\n this.logger.error(\"Error handling message\", message, e);\n socket.send(\n JSON.stringify({\n type: LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE,\n errorType: LEGACY_USER_NETWORKING_UNKNOWN_ERROR,\n message: \"Error handling message\",\n } satisfies LegacyFromUserNetworkingServerMessage),\n );\n socket.close();\n }\n });\n\n socket.addEventListener(\"close\", () => {\n this.handleDisconnectedClient(client);\n });\n }\n\n private handleDisconnectedClient(client: LegacyUserNetworkingServerClient) {\n if (!this.allClientsById.has(client.id)) {\n return;\n }\n this.allClientsById.delete(client.id);\n if (client.authenticatedUser !== null) {\n // Only report disconnections of clients that were authenticated\n this.userNetworkingServer.onLegacyClientDisconnect(client.id);\n this.legacyAuthenticatedClientsById.delete(client.id);\n this.deltaNetServer.clearInternalConnectionId(client.id);\n }\n }\n\n private async handleUserAuth(\n client: LegacyUserNetworkingServerClient,\n credentials: LegacyUserNetworkingAuthenticateMessage,\n ): Promise<false | LegacyUserData> {\n const userData = this.userNetworkingServer.onLegacyClientConnect(\n client.id,\n credentials.sessionToken,\n credentials.userIdentity,\n );\n let resolvedUserData;\n if (userData instanceof Promise) {\n resolvedUserData = await userData;\n } else {\n resolvedUserData = userData;\n }\n\n if (resolvedUserData instanceof Error) {\n this.logger.error(`Client-id ${client.id} user_auth failed`, resolvedUserData);\n return false;\n } else if (resolvedUserData === true) {\n this.logger.error(`Client-id ${client.id} user_auth failed`, resolvedUserData);\n resolvedUserData = credentials.userIdentity as LegacyUserData;\n } else {\n resolvedUserData = resolvedUserData as LegacyUserData;\n }\n if (resolvedUserData === null) {\n this.logger.error(`Client-id ${client.id} user_auth unauthorized and ignored`);\n return false;\n }\n\n return resolvedUserData;\n }\n\n public updateUserCharacter(clientId: number, userData: LegacyUserData) {\n this.internalUpdateUser(clientId, userData);\n }\n\n private internalUpdateUser(clientId: number, userData: LegacyUserData) {\n // This function assumes authorization has already been done\n const client = this.legacyAuthenticatedClientsById.get(clientId)!;\n\n client.authenticatedUser = userData;\n this.legacyAuthenticatedClientsById.set(clientId, client);\n\n this.userNetworkingServer.updateUserCharacter(client.id, { ...userData, colors: [] });\n }\n\n private async handleUserUpdate(\n clientId: number,\n message: LegacyUserNetworkingUserUpdateMessage,\n ): Promise<void> {\n const client = this.legacyAuthenticatedClientsById.get(clientId);\n if (!client) {\n this.logger.error(`Client-id ${clientId} user_update ignored, client not found`);\n return;\n }\n\n // TODO - call the UserNetworkingServer to check if the update is allowed\n // Verify using the user authenticator what the allowed version of this update is\n const authorizedUserData = message.userIdentity;\n\n let resolvedAuthorizedUserData;\n if (authorizedUserData instanceof Promise) {\n resolvedAuthorizedUserData = await authorizedUserData;\n } else {\n resolvedAuthorizedUserData = authorizedUserData;\n }\n if (!resolvedAuthorizedUserData) {\n // TODO - inform the client about the unauthorized update\n this.logger.warn(`Client-id ${clientId} user_update unauthorized and ignored`);\n return;\n }\n\n this.internalUpdateUser(clientId, resolvedAuthorizedUserData);\n }\n\n public sendUpdates(\n removedIds: Set<number>,\n addedIds: Set<number>,\n updateUserProfilesInTick: Set<number>,\n ): void {\n for (const id of removedIds) {\n const disconnectMessage = JSON.stringify({\n id,\n type: LEGACY_USER_NETWORKING_DISCONNECTED_MESSAGE_TYPE,\n } as LegacyFromUserNetworkingServerMessage);\n for (const [, otherClient] of this.legacyAuthenticatedClientsById) {\n if (otherClient.socket.readyState === WebSocketOpenStatus) {\n otherClient.socket.send(disconnectMessage);\n }\n }\n }\n\n for (const id of addedIds) {\n const identityMessage = JSON.stringify({\n id: id,\n type: LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE,\n username: this.userNetworkingServer.getUsername(id),\n characterDescription: this.userNetworkingServer.getCharacterDescription(id),\n } satisfies LegacyFromUserNetworkingServerMessage);\n for (const [, otherClient] of this.legacyAuthenticatedClientsById) {\n if (otherClient.socket.readyState === WebSocketOpenStatus) {\n otherClient.socket.send(identityMessage);\n }\n }\n }\n\n for (const id of updateUserProfilesInTick) {\n const identityMessage = JSON.stringify({\n id: id,\n type: LEGACY_USER_NETWORKING_USER_PROFILE_MESSAGE_TYPE,\n username: this.userNetworkingServer.getUsername(id),\n characterDescription: this.userNetworkingServer.getCharacterDescription(id),\n } satisfies LegacyFromUserNetworkingServerMessage);\n for (const [, otherClient] of this.legacyAuthenticatedClientsById) {\n if (otherClient.socket.readyState === WebSocketOpenStatus) {\n otherClient.socket.send(identityMessage);\n }\n }\n }\n\n const allUsers: Map<number, number> =\n this.deltaNetServer.dangerouslyGetConnectionsToComponentIndex();\n for (const [connectionId, componentIndex] of allUsers) {\n const x =\n this.deltaNetServer.getComponentValue(COMPONENT_POSITION_X, componentIndex) /\n positionMultiplier;\n const y =\n this.deltaNetServer.getComponentValue(COMPONENT_POSITION_Y, componentIndex) /\n positionMultiplier;\n const z =\n this.deltaNetServer.getComponentValue(COMPONENT_POSITION_Z, componentIndex) /\n positionMultiplier;\n const quaternionY =\n this.deltaNetServer.getComponentValue(COMPONENT_ROTATION_Y, componentIndex) /\n rotationMultiplier;\n const quaternionW =\n this.deltaNetServer.getComponentValue(COMPONENT_ROTATION_W, componentIndex) /\n rotationMultiplier;\n const state = this.deltaNetServer.getComponentValue(COMPONENT_STATE, componentIndex);\n const encodedUpdate = LegacyUserNetworkingCodec.encodeUpdate({\n id: connectionId,\n position: { x, y, z },\n rotation: { quaternionY, quaternionW },\n state,\n });\n\n for (const [otherClientId, otherClient] of this.legacyAuthenticatedClientsById) {\n if (\n otherClientId !== connectionId &&\n otherClient.socket.readyState === WebSocketOpenStatus\n ) {\n otherClient.socket.send(encodedUpdate);\n }\n }\n }\n }\n\n public dispose(clientCloseError?: LegacyUserNetworkingServerError) {\n const stringifiedError = clientCloseError ? JSON.stringify(clientCloseError) : undefined;\n\n for (const [, client] of this.legacyAuthenticatedClientsById) {\n if (stringifiedError) {\n client.socket.send(stringifiedError);\n }\n client.socket.close();\n }\n }\n}\n", "export type UserNetworkingServerLogFunction = (...args: Array<any>) => void;\n\nexport type UserNetworkingLogger = {\n trace: UserNetworkingServerLogFunction;\n debug: UserNetworkingServerLogFunction;\n info: UserNetworkingServerLogFunction;\n warn: UserNetworkingServerLogFunction;\n error: UserNetworkingServerLogFunction;\n};\n\nexport class UserNetworkingConsoleLogger implements UserNetworkingLogger {\n trace(...args: Array<any>) {\n console.trace(...args);\n }\n\n debug(...args: Array<any>) {\n console.debug(...args);\n }\n\n info(...args: Array<any>) {\n console.info(...args);\n }\n\n warn(...args: Array<any>) {\n console.warn(...args);\n }\n\n error(...args: Array<any>) {\n console.error(...args);\n }\n}\n", "import {\n DeltaNetClientState,\n DeltaNetClientWebsocket,\n DeltaNetClientWebsocketInitialCheckout,\n DeltaNetClientWebsocketStatus,\n DeltaNetClientWebsocketTick,\n DeltaNetClientWebsocketUserIndex,\n} from \"@mml-io/delta-net-web\";\n\nimport {\n DeltaNetComponentMapping,\n STATE_CHARACTER_DESCRIPTION,\n STATE_COLORS,\n STATE_INTERNAL_CONNECTION_ID,\n STATE_USERNAME,\n} from \"./DeltaNetComponentMapping\";\nimport { UserNetworkingClientUpdate, WebsocketFactory, WebsocketStatus } from \"./types\";\nimport { UserData } from \"./UserData\";\nimport { UserNetworkingConsoleLogger, UserNetworkingLogger } from \"./UserNetworkingLogger\";\nimport { CharacterDescription } from \"./UserNetworkingMessages\";\n\nexport type UserNetworkingClientConfig = {\n url: string;\n sessionToken: string;\n websocketFactory: WebsocketFactory;\n statusUpdateCallback: (status: WebsocketStatus) => void;\n assignedIdentity: (clientId: number) => void;\n onServerError: (error: { message: string; errorType: string }) => void;\n onCustomMessage?: (customType: number, contents: string) => void;\n onUpdate(update: NetworkUpdate): void;\n};\n\nexport type AddedUser = {\n userState: UserData;\n components: UserNetworkingClientUpdate;\n};\n\nexport type UpdatedUser = {\n userState?: Partial<UserData>;\n components: UserNetworkingClientUpdate;\n};\n\nexport type NetworkUpdate = {\n removedUserIds: Set<number>;\n addedUserIds: Map<number, AddedUser>;\n updatedUsers: Map<number, UpdatedUser>;\n};\n\nexport class UserNetworkingClient {\n private deltaNetClient: DeltaNetClientWebsocket;\n private deltaNetState: DeltaNetClientState;\n\n private userId: number | null = null;\n private userIndex: number | null = null;\n private userState: UserData = {\n username: null,\n characterDescription: null,\n colors: null,\n };\n\n private stableIdToUserId: Map<number, number> = new Map();\n private userProfiles: Map<number, UserData> = new Map();\n private isAuthenticated = false;\n private pendingUpdate: UserNetworkingClientUpdate;\n\n constructor(\n private config: UserNetworkingClientConfig,\n initialUserState?: UserData,\n initialUpdate?: UserNetworkingClientUpdate,\n private logger: UserNetworkingLogger = new UserNetworkingConsoleLogger(),\n ) {\n this.pendingUpdate = initialUpdate ?? {\n position: { x: 0, y: 0, z: 0 },\n rotation: { quaternionY: 0, quaternionW: 1 },\n state: 0,\n };\n this.userState = initialUserState ?? {\n username: null,\n characterDescription: null,\n colors: null,\n };\n this.deltaNetState = new DeltaNetClientState();\n\n // Create deltanet client\n this.deltaNetClient = new DeltaNetClientWebsocket(\n config.url,\n (url: string) => {\n const ws = config.websocketFactory(url);\n return ws;\n },\n config.sessionToken,\n {\n ignoreData: false,\n onInitialCheckout: (initialCheckout: DeltaNetClientWebsocketInitialCheckout) => {\n const { addedStableIds } = this.deltaNetState.handleInitialCheckout(initialCheckout);\n\n // Process any state updates\n const networkUpdate = this.processNetworkUpdate([], addedStableIds, []);\n this.config.onUpdate(networkUpdate);\n\n // Now that we have the user IDs, resolve our stable user ID from the userIndex\n if (this.userIndex !== null) {\n const userIds = this.deltaNetState.getStableIds();\n if (this.userIndex < userIds.length) {\n const stableId = userIds[this.userIndex];\n const userId = this.stableIdToUserId.get(stableId);\n if (!userId) {\n throw new Error(`No userId found for stableId ${stableId}`);\n }\n this.userId = userId;\n this.isAuthenticated = true;\n this.config.assignedIdentity(this.userId);\n } else {\n this.logger.error(\n `Invalid userIndex ${this.userIndex}, userIds length: ${userIds.length}`,\n );\n }\n }\n },\n onTick: (tick: DeltaNetClientWebsocketTick) => {\n const { stateUpdates, removedStableIds, addedStableIds } =\n this.deltaNetState.handleTick(tick);\n // Process state updates\n const networkUpdate = this.processNetworkUpdate(\n removedStableIds,\n addedStableIds,\n stateUpdates,\n );\n this.config.onUpdate(networkUpdate);\n },\n onUserIndex: (userIndex: DeltaNetClientWebsocketUserIndex) => {\n // Store the userIndex and set it on deltanet state\n this.userIndex = userIndex.userIndex;\n this.deltaNetState.setLocalIndex(userIndex.userIndex);\n },\n onError: (errorType: string, errorMessage: string, retryable: boolean) => {\n this.logger.error(\n \"DeltaNet error:\",\n errorType,\n \"errorMessage:\",\n errorMessage,\n \"retryable:\",\n retryable,\n );\n this.config.onServerError({\n message: errorMessage,\n errorType: errorType,\n });\n },\n onWarning: (warning: string) => {\n this.logger.warn(\"DeltaNet warning:\", warning);\n },\n onServerCustom: (customType: number, contents: string) => {\n // Handle server custom messages\n this.config.onCustomMessage?.(customType, contents);\n },\n },\n undefined, // timeCallback is optional\n (status: DeltaNetClientWebsocketStatus) => {\n // Map deltanet status to websocket status\n let mappedStatus: WebsocketStatus;\n switch (status) {\n case DeltaNetClientWebsocketStatus.Connected:\n mappedStatus = WebsocketStatus.Connected;\n break;\n case DeltaNetClientWebsocketStatus.ConnectionOpen:\n this.sendInitialAuthentication();\n mappedStatus = WebsocketStatus.Connected;\n // Send initial authentication data immediately upon connection\n break;\n case DeltaNetClientWebsocketStatus.Disconnected:\n mappedStatus = WebsocketStatus.Disconnected;\n this.reset();\n break;\n case DeltaNetClientWebsocketStatus.Reconnecting:\n mappedStatus = WebsocketStatus.Reconnecting;\n this.reset();\n break;\n default:\n mappedStatus = WebsocketStatus.Disconnected;\n }\n this.config.statusUpdateCallback(mappedStatus);\n },\n );\n }\n\n private reset(): void {\n this.deltaNetState.reset();\n this.userProfiles.clear();\n this.stableIdToUserId.clear();\n this.isAuthenticated = false;\n this.userId = null;\n this.userIndex = null;\n }\n\n private sendInitialAuthentication(): void {\n // Send initial components and states to become \"ready\"\n const components = DeltaNetComponentMapping.toComponents(this.pendingUpdate);\n\n // Create initial states for user data\n const states = DeltaNetComponentMapping.toStates(this.userState);\n\n // Send to deltanet - this makes the client \"ready\" and triggers authentication\n this.deltaNetClient.setUserComponents(components, states);\n }\n\n private processNetworkUpdate(\n removedStableIds: number[],\n addedStableIdsArray: number[],\n stateUpdates: Array<{ stableId: number; stateId: number; state: Uint8Array }>,\n ): NetworkUpdate {\n const addedUserIds = new Map<number, AddedUser>();\n const removedUserIds = new Set<number>();\n\n for (const stableId of removedStableIds) {\n const userId = this.stableIdToUserId.get(stableId);\n if (userId) {\n removedUserIds.add(userId);\n\n // Remove from user profiles\n this.userProfiles.delete(userId);\n\n // Remove from stableIdToUserId\n this.stableIdToUserId.delete(stableId);\n } else {\n throw new Error(`No userId found for stableId ${stableId}`);\n }\n }\n\n for (const stableId of addedStableIdsArray) {\n const stableUserData = this.deltaNetState.byStableId.get(stableId);\n if (!stableUserData) {\n throw new Error(`No stableUserData found for stableId ${stableId}`);\n }\n const userIdState = stableUserData.states.get(STATE_INTERNAL_CONNECTION_ID);\n if (!userIdState) {\n throw new Error(`No userIdState found for stableId ${stableId}`);\n }\n const userId = DeltaNetComponentMapping.userIdFromBytes(userIdState);\n if (!userId) {\n throw new Error(`Failed to extract userId from bytes for stableId ${stableId}`);\n }\n this.stableIdToUserId.set(stableId, userId);\n const newProfile = DeltaNetComponentMapping.fromStates(stableUserData.states, this.logger);\n this.userProfiles.set(userId, newProfile);\n const clientUpdate = DeltaNetComponentMapping.fromComponents(stableUserData.components);\n addedUserIds.set(userId, {\n userState: newProfile,\n components: clientUpdate,\n });\n }\n\n const updatedUsers = new Map<number, UpdatedUser>();\n\n for (const [stableUserId, userInfo] of this.deltaNetState.byStableId) {\n const userId = this.stableIdToUserId.get(stableUserId);\n if (!userId) {\n throw new Error(`No userId found for stableUserId ${stableUserId}`);\n }\n if (!addedUserIds.has(userId)) {\n if (userInfo.components.size > 0) {\n const clientUpdate = DeltaNetComponentMapping.fromComponents(userInfo.components);\n updatedUsers.set(userId, {\n components: clientUpdate,\n });\n }\n }\n }\n\n for (const update of stateUpdates) {\n // update.stableId is actually a stable user ID maintained by deltanet, not an index\n const stableUserId = update.stableId;\n\n const userId = this.stableIdToUserId.get(stableUserId);\n if (!userId) {\n throw new Error(`No userId found for stableUserId ${stableUserId}`);\n }\n\n if (addedUserIds.has(userId)) {\n continue;\n }\n\n const profile = this.userProfiles.get(userId);\n if (!profile) {\n this.logger.warn(`No profile found for user ${userId}, skipping update`);\n continue;\n }\n const existingUpdate = updatedUsers.get(userId)!;\n let existingUserStateUpdate: Partial<UserData> | undefined = existingUpdate.userState;\n if (!existingUserStateUpdate) {\n existingUserStateUpdate = {};\n existingUpdate.userState = existingUserStateUpdate;\n }\n\n switch (update.stateId) {\n case STATE_INTERNAL_CONNECTION_ID:\n this.logger.error(\n \"STATE_INTERNAL_CONNECTION_ID is not expected to change in state updates\",\n );\n break;\n case STATE_USERNAME:\n const username = DeltaNetComponentMapping.usernameFromBytes(update.state);\n if (username) {\n profile.username = username;\n existingUserStateUpdate.username = username;\n }\n break;\n case STATE_CHARACTER_DESCRIPTION:\n const characterDescription = DeltaNetComponentMapping.characterDescriptionFromBytes(\n update.state,\n );\n profile.characterDescription = characterDescription;\n existingUserStateUpdate.characterDescription = characterDescription;\n break;\n case STATE_COLORS:\n const colors = DeltaNetComponentMapping.decodeColors(update.state, this.logger);\n profile.colors = colors;\n existingUserStateUpdate.colors = colors;\n break;\n default:\n this.logger.warn(`Unknown state ID: ${update.stateId}`);\n }\n }\n\n return {\n removedUserIds,\n addedUserIds,\n updatedUsers,\n };\n }\n\n public sendUpdate(update: UserNetworkingClientUpdate): void {\n if (!this.isAuthenticated || this.userId === null) {\n // Store the update to send after authentication\n this.pendingUpdate = update;\n return;\n }\n\n // Convert to deltanet components and send\n const components = DeltaNetComponentMapping.toComponents(update);\n this.deltaNetClient.setUserComponents(components, new Map());\n }\n\n public sendCustomMessage(customType: number, contents: string): void {\n if (!this.isAuthenticated || this.userId === null) {\n this.logger.warn(\"Cannot send custom message before authentication\");\n return;\n }\n\n this.deltaNetClient.sendCustomMessage(customType, contents);\n }\n\n public updateUsername(username: string): void {\n if (!this.isAuthenticated || this.userId === null) {\n return;\n }\n\n // Update local state\n this.userState.username = username;\n\n // Send state update\n const states = DeltaNetComponentMapping.toUsernameState(username);\n this.deltaNetClient.setUserComponents(new Map(), states);\n }\n\n public updateCharacterDescription(characterDescription: CharacterDescription): void {\n if (!this.isAuthenticated || this.userId === null) {\n return;\n }\n\n // Update local state\n this.userState.characterDescription = characterDescription;\n\n // Send state update\n const states = DeltaNetComponentMapping.toCharacterDescriptionState(characterDescription);\n this.deltaNetClient.setUserComponents(new Map(), states);\n }\n\n public updateColors(colors: Array<[number, number, number]>): void {\n if (!this.isAuthenticated || this.userId === null) {\n return;\n }\n\n // Update local state\n this.userState.colors = colors;\n\n // Send state update\n const states = DeltaNetComponentMapping.toColorsState(colors);\n this.deltaNetClient.setUserComponents(new Map(), states);\n }\n\n public stop(): void {\n this.deltaNetClient.stop();\n this.reset();\n }\n}\n", "export type WebsocketFactory = (url: string) => WebSocket;\n\nexport enum WebsocketStatus {\n Connecting,\n Connected,\n Reconnecting,\n Disconnected,\n}\n\nexport type UserNetworkingClientUpdate = {\n position: { x: number; y: number; z: number };\n rotation: { quaternionY: number; quaternionW: number };\n state: number;\n};\n", "export * from \"./UserNetworkingServer\";\nexport * from \"./UserNetworkingClient\";\nexport * from \"./UserData\";\nexport * from \"./types\";\nexport * from \"./UserNetworkingMessages\";\nexport * from \"./legacy/LegacyUserNetworkingMessages\";\nexport * from \"./DeltaNetComponentMapping\";\nexport * from \"./UserNetworkingLogger\";\nexport {\n DeltaNetV01ServerErrors,\n deltaNetProtocolSubProtocol_v0_1,\n} from \"@mml-io/delta-net-protocol\";\n"],
5
+ "mappings": "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",
6
6
  "names": ["DeltaNetServerError", "DeltaNetServerError", "res", "WebsocketStatus", "DeltaNetV01ServerErrors"]
7
7
  }
@@ -1,4 +1,5 @@
1
1
  import { DeltaNetServer } from "@mml-io/delta-net-server";
2
+ import { UserNetworkingLogger } from "../UserNetworkingLogger";
2
3
  import { UserNetworkingServer } from "../UserNetworkingServer";
3
4
  import { LegacyUserNetworkingClientUpdate } from "./LegacyUserNetworkingCodec";
4
5
  import { LegacyUserData, LegacyUserNetworkingServerError } from "./LegacyUserNetworkingMessages";
@@ -12,9 +13,10 @@ export type LegacyUserNetworkingServerClient = {
12
13
  export declare class LegacyAdapter {
13
14
  private readonly userNetworkingServer;
14
15
  private readonly deltaNetServer;
16
+ private logger;
15
17
  private allClientsById;
16
18
  private legacyAuthenticatedClientsById;
17
- constructor(userNetworkingServer: UserNetworkingServer, deltaNetServer: DeltaNetServer);
19
+ constructor(userNetworkingServer: UserNetworkingServer, deltaNetServer: DeltaNetServer, logger: UserNetworkingLogger);
18
20
  broadcastMessage(broadcastType: number, broadcastPayload: string): void;
19
21
  addWebSocket(socket: WebSocket): void;
20
22
  private handleDisconnectedClient;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mml-io/3d-web-user-networking",
3
- "version": "0.0.0-experimental-4fa4c42-20250715",
3
+ "version": "0.0.0-experimental-d4f4aa0-20250721",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -20,9 +20,9 @@
20
20
  "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest"
21
21
  },
22
22
  "dependencies": {
23
- "@mml-io/delta-net-protocol": "0.0.0-experimental-4fa4c42-20250715",
24
- "@mml-io/delta-net-server": "0.0.0-experimental-4fa4c42-20250715",
25
- "@mml-io/delta-net-web": "0.0.0-experimental-4fa4c42-20250715"
23
+ "@mml-io/delta-net-protocol": "0.0.0-experimental-d4f4aa0-20250721",
24
+ "@mml-io/delta-net-server": "0.0.0-experimental-d4f4aa0-20250721",
25
+ "@mml-io/delta-net-web": "0.0.0-experimental-d4f4aa0-20250721"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@jest/globals": "29.7.0",
@@ -38,5 +38,6 @@
38
38
  "jest-junit": "16.0.0",
39
39
  "ts-jest": "^29.1.2",
40
40
  "ws": "^8.18.0"
41
- }
41
+ },
42
+ "gitHead": "6701877506d918e48ae067c4a20f2a6eac8b1808"
42
43
  }