@mml-io/3d-web-user-networking 0.0.0-experimental-4fa4c42-20250715 → 0.0.0-experimental-1111b42-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 +19 -0
- package/build/DeltaNetComponentMapping.d.ts +4 -3
- package/build/UserNetworkingClient.d.ts +3 -1
- package/build/UserNetworkingLogger.d.ts +15 -0
- package/build/UserNetworkingServer.d.ts +5 -4
- package/build/index.d.ts +1 -0
- package/build/index.js +102 -78
- package/build/index.js.map +3 -3
- package/build/legacy/LegacyAdapter.d.ts +3 -1
- package/package.json +6 -5
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
|
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):
|
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
|
-
|
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.
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
529
|
+
this.logger.error(`Unhandled message: ${JSON.stringify(parsed)}`);
|
529
530
|
}
|
530
531
|
}
|
531
532
|
}
|
532
533
|
} catch (e) {
|
533
|
-
|
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
|
-
|
573
|
+
this.logger.error(`Client-id ${client.id} user_auth failed`, resolvedUserData);
|
573
574
|
return false;
|
574
575
|
} else if (resolvedUserData === true) {
|
575
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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
|
-
|
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
|
-
|
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(
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
952
|
-
if (!deltaNetConnection.isObserver && !
|
953
|
-
|
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 (
|
960
|
-
return { success: false, error:
|
975
|
+
if (onClientConnectReturn instanceof Error) {
|
976
|
+
return { success: false, error: onClientConnectReturn };
|
961
977
|
}
|
962
|
-
if (
|
963
|
-
|
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
|
986
|
+
authenticatedUser,
|
970
987
|
deltaNetConnection
|
971
988
|
};
|
972
989
|
this.authenticatedClientsById.set(clientId, authenticatedClient);
|
973
990
|
let stateOverrides = [];
|
974
|
-
if (
|
975
|
-
const officialStates = DeltaNetComponentMapping.toStates(
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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,
|
package/build/index.js.map
CHANGED
@@ -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-
|
3
|
+
"version": "0.0.0-experimental-1111b42-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-
|
24
|
-
"@mml-io/delta-net-server": "0.0.0-experimental-
|
25
|
-
"@mml-io/delta-net-web": "0.0.0-experimental-
|
23
|
+
"@mml-io/delta-net-protocol": "0.0.0-experimental-1111b42-20250721",
|
24
|
+
"@mml-io/delta-net-server": "0.0.0-experimental-1111b42-20250721",
|
25
|
+
"@mml-io/delta-net-web": "0.0.0-experimental-1111b42-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": "6715c1d4febf4efa299fb472060b1d1855306302"
|
42
43
|
}
|