@mml-io/3d-web-user-networking 0.0.0-experimental-3a2278c-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 +110 -98
- 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
@@ -1,12 +1,12 @@
|
|
1
1
|
// src/UserNetworkingServer.ts
|
2
|
-
import { encodeError, DeltaNetV01ServerErrors } from "
|
2
|
+
import { encodeError, DeltaNetV01ServerErrors } from "@mml-io/delta-net-protocol";
|
3
3
|
import {
|
4
4
|
DeltaNetServer,
|
5
5
|
DeltaNetServerError as DeltaNetServerError2
|
6
|
-
} from "
|
6
|
+
} from "@mml-io/delta-net-server";
|
7
7
|
|
8
8
|
// src/DeltaNetComponentMapping.ts
|
9
|
-
import { BufferReader, BufferWriter } from "
|
9
|
+
import { BufferReader, BufferWriter } from "@mml-io/delta-net-protocol";
|
10
10
|
var COMPONENT_POSITION_X = 1;
|
11
11
|
var COMPONENT_POSITION_Y = 2;
|
12
12
|
var COMPONENT_POSITION_Z = 3;
|
@@ -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,20 +201,20 @@ 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
|
};
|
215
215
|
|
216
216
|
// src/UserNetworkingMessages.ts
|
217
|
-
import { DeltaNetServerError } from "
|
217
|
+
import { DeltaNetServerError } from "@mml-io/delta-net-server";
|
218
218
|
var UserNetworkingServerError = class extends DeltaNetServerError {
|
219
219
|
};
|
220
220
|
var SERVER_BROADCAST_MESSAGE_TYPE = 1;
|
@@ -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;
|
@@ -350,7 +351,6 @@ var LegacyAdapter = class {
|
|
350
351
|
}
|
351
352
|
addWebSocket(socket) {
|
352
353
|
const id = this.userNetworkingServer.getLegacyClientId();
|
353
|
-
console.log(`Client ID: ${id} joined, waiting for user-identification`);
|
354
354
|
const client = {
|
355
355
|
id,
|
356
356
|
lastPong: Date.now(),
|
@@ -411,7 +411,7 @@ var LegacyAdapter = class {
|
|
411
411
|
try {
|
412
412
|
parsed = JSON.parse(message.data);
|
413
413
|
} catch (e) {
|
414
|
-
|
414
|
+
this.logger.error("Error parsing JSON message", message, e);
|
415
415
|
return;
|
416
416
|
}
|
417
417
|
if (!client.authenticatedUser) {
|
@@ -421,7 +421,7 @@ var LegacyAdapter = class {
|
|
421
421
|
return;
|
422
422
|
}
|
423
423
|
if (!authResult) {
|
424
|
-
|
424
|
+
this.logger.error(`Client-id ${client.id} user_auth failed`, authResult);
|
425
425
|
const serverError = JSON.stringify({
|
426
426
|
type: LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE,
|
427
427
|
errorType: LEGACY_USER_NETWORKING_AUTHENTICATION_FAILED_ERROR_TYPE,
|
@@ -514,7 +514,7 @@ var LegacyAdapter = class {
|
|
514
514
|
}
|
515
515
|
});
|
516
516
|
} else {
|
517
|
-
|
517
|
+
this.logger.error(`Unhandled message pre-auth: ${JSON.stringify(parsed)}`);
|
518
518
|
socket.close();
|
519
519
|
}
|
520
520
|
} else {
|
@@ -526,12 +526,12 @@ var LegacyAdapter = class {
|
|
526
526
|
this.handleUserUpdate(id, parsed);
|
527
527
|
break;
|
528
528
|
default:
|
529
|
-
|
529
|
+
this.logger.error(`Unhandled message: ${JSON.stringify(parsed)}`);
|
530
530
|
}
|
531
531
|
}
|
532
532
|
}
|
533
533
|
} catch (e) {
|
534
|
-
|
534
|
+
this.logger.error("Error handling message", message, e);
|
535
535
|
socket.send(
|
536
536
|
JSON.stringify({
|
537
537
|
type: LEGACY_USER_NETWORKING_SERVER_ERROR_MESSAGE_TYPE,
|
@@ -543,7 +543,6 @@ var LegacyAdapter = class {
|
|
543
543
|
}
|
544
544
|
});
|
545
545
|
socket.addEventListener("close", () => {
|
546
|
-
console.log("Client disconnected", id);
|
547
546
|
this.handleDisconnectedClient(client);
|
548
547
|
});
|
549
548
|
}
|
@@ -571,19 +570,18 @@ var LegacyAdapter = class {
|
|
571
570
|
resolvedUserData = userData;
|
572
571
|
}
|
573
572
|
if (resolvedUserData instanceof Error) {
|
574
|
-
|
573
|
+
this.logger.error(`Client-id ${client.id} user_auth failed`, resolvedUserData);
|
575
574
|
return false;
|
576
575
|
} else if (resolvedUserData === true) {
|
577
|
-
|
576
|
+
this.logger.error(`Client-id ${client.id} user_auth failed`, resolvedUserData);
|
578
577
|
resolvedUserData = credentials.userIdentity;
|
579
578
|
} else {
|
580
579
|
resolvedUserData = resolvedUserData;
|
581
580
|
}
|
582
581
|
if (resolvedUserData === null) {
|
583
|
-
|
582
|
+
this.logger.error(`Client-id ${client.id} user_auth unauthorized and ignored`);
|
584
583
|
return false;
|
585
584
|
}
|
586
|
-
console.log("Client authenticated", client.id, resolvedUserData);
|
587
585
|
return resolvedUserData;
|
588
586
|
}
|
589
587
|
updateUserCharacter(clientId, userData) {
|
@@ -598,7 +596,7 @@ var LegacyAdapter = class {
|
|
598
596
|
async handleUserUpdate(clientId, message) {
|
599
597
|
const client = this.legacyAuthenticatedClientsById.get(clientId);
|
600
598
|
if (!client) {
|
601
|
-
|
599
|
+
this.logger.error(`Client-id ${clientId} user_update ignored, client not found`);
|
602
600
|
return;
|
603
601
|
}
|
604
602
|
const authorizedUserData = message.userIdentity;
|
@@ -609,7 +607,7 @@ var LegacyAdapter = class {
|
|
609
607
|
resolvedAuthorizedUserData = authorizedUserData;
|
610
608
|
}
|
611
609
|
if (!resolvedAuthorizedUserData) {
|
612
|
-
|
610
|
+
this.logger.warn(`Client-id ${clientId} user_update unauthorized and ignored`);
|
613
611
|
return;
|
614
612
|
}
|
615
613
|
this.internalUpdateUser(clientId, resolvedAuthorizedUserData);
|
@@ -652,14 +650,6 @@ var LegacyAdapter = class {
|
|
652
650
|
}
|
653
651
|
}
|
654
652
|
}
|
655
|
-
for (const [clientId, client] of this.legacyAuthenticatedClientsById) {
|
656
|
-
const encodedUpdate = LegacyUserNetworkingCodec.encodeUpdate(client.update);
|
657
|
-
for (const [otherClientId, otherClient] of this.legacyAuthenticatedClientsById) {
|
658
|
-
if (otherClientId !== clientId && otherClient.socket.readyState === WebSocketOpenStatus) {
|
659
|
-
otherClient.socket.send(encodedUpdate);
|
660
|
-
}
|
661
|
-
}
|
662
|
-
}
|
663
653
|
const allUsers = this.deltaNetServer.dangerouslyGetConnectionsToComponentIndex();
|
664
654
|
for (const [connectionId, componentIndex] of allUsers) {
|
665
655
|
const x = this.deltaNetServer.getComponentValue(COMPONENT_POSITION_X, componentIndex) / positionMultiplier;
|
@@ -692,13 +682,30 @@ var LegacyAdapter = class {
|
|
692
682
|
}
|
693
683
|
};
|
694
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
|
+
|
695
704
|
// src/UserNetworkingServer.ts
|
696
705
|
var UserNetworkingServer = class {
|
697
|
-
constructor(options) {
|
706
|
+
constructor(options, logger = new UserNetworkingConsoleLogger()) {
|
698
707
|
this.options = options;
|
699
|
-
this.
|
700
|
-
this.legacyAdapter = null;
|
701
|
-
this.updatedUserProfilesInTick = /* @__PURE__ */ new Set();
|
708
|
+
this.logger = logger;
|
702
709
|
this.deltaNetServer = new DeltaNetServer({
|
703
710
|
serverConnectionIdStateId: 0,
|
704
711
|
onJoiner: (joiner) => {
|
@@ -718,7 +725,7 @@ var UserNetworkingServer = class {
|
|
718
725
|
}
|
719
726
|
});
|
720
727
|
if (this.options.legacyAdapterEnabled) {
|
721
|
-
this.legacyAdapter = new LegacyAdapter(this, this.deltaNetServer);
|
728
|
+
this.legacyAdapter = new LegacyAdapter(this, this.deltaNetServer, this.logger);
|
722
729
|
}
|
723
730
|
this.tickInterval = setInterval(() => {
|
724
731
|
const { removedIds, addedIds } = this.deltaNetServer.tick();
|
@@ -728,20 +735,20 @@ var UserNetworkingServer = class {
|
|
728
735
|
}
|
729
736
|
}, 50);
|
730
737
|
}
|
738
|
+
deltaNetServer;
|
739
|
+
authenticatedClientsById = /* @__PURE__ */ new Map();
|
740
|
+
tickInterval;
|
741
|
+
legacyAdapter = null;
|
742
|
+
updatedUserProfilesInTick = /* @__PURE__ */ new Set();
|
731
743
|
getCharacterDescription(connectionId) {
|
732
|
-
var _a
|
744
|
+
var _a;
|
733
745
|
const client = this.authenticatedClientsById.get(connectionId);
|
734
|
-
|
735
|
-
"getCharacterDescription",
|
736
|
-
connectionId,
|
737
|
-
(_a = client == null ? void 0 : client.authenticatedUser) == null ? void 0 : _a.characterDescription
|
738
|
-
);
|
739
|
-
return ((_b = client == null ? void 0 : client.authenticatedUser) == null ? void 0 : _b.characterDescription) ?? { mmlCharacterUrl: "" };
|
746
|
+
return ((_a = client == null ? void 0 : client.authenticatedUser) == null ? void 0 : _a.characterDescription) ?? { mmlCharacterUrl: "" };
|
740
747
|
}
|
741
748
|
getUsername(connectionId) {
|
742
749
|
var _a, _b;
|
743
750
|
const client = this.authenticatedClientsById.get(connectionId);
|
744
|
-
|
751
|
+
this.logger.info("getUsername", connectionId, (_a = client == null ? void 0 : client.authenticatedUser) == null ? void 0 : _a.username);
|
745
752
|
return ((_b = client == null ? void 0 : client.authenticatedUser) == null ? void 0 : _b.username) ?? "";
|
746
753
|
}
|
747
754
|
getLegacyClientId() {
|
@@ -758,7 +765,7 @@ var UserNetworkingServer = class {
|
|
758
765
|
});
|
759
766
|
}
|
760
767
|
setAuthenticatedLegacyClientConnection(clientId, webSocket, userData) {
|
761
|
-
|
768
|
+
this.logger.info("setAuthenticatedLegacyClientConnection", clientId, userData);
|
762
769
|
const authenticatedClient = {
|
763
770
|
id: clientId,
|
764
771
|
socket: webSocket,
|
@@ -776,7 +783,10 @@ var UserNetworkingServer = class {
|
|
776
783
|
const clientId = deltaNetConnection.internalConnectionId;
|
777
784
|
const updatedStates = update.states;
|
778
785
|
const updatedStatesMap = new Map(updatedStates);
|
779
|
-
const updatedUserData = DeltaNetComponentMapping.fromUserStates(
|
786
|
+
const updatedUserData = DeltaNetComponentMapping.fromUserStates(
|
787
|
+
updatedStatesMap,
|
788
|
+
this.logger
|
789
|
+
);
|
780
790
|
const existingClient = this.authenticatedClientsById.get(clientId);
|
781
791
|
if (!existingClient) {
|
782
792
|
return new DeltaNetServerError2(
|
@@ -889,7 +899,7 @@ var UserNetworkingServer = class {
|
|
889
899
|
const states = joiner.states;
|
890
900
|
const clientId = joiner.internalConnectionId;
|
891
901
|
const statesMap = new Map(states);
|
892
|
-
const userData = DeltaNetComponentMapping.fromUserStates(statesMap);
|
902
|
+
const userData = DeltaNetComponentMapping.fromUserStates(statesMap, this.logger);
|
893
903
|
return this.handleDeltaNetAuthentication(
|
894
904
|
clientId,
|
895
905
|
webSocket,
|
@@ -897,11 +907,12 @@ var UserNetworkingServer = class {
|
|
897
907
|
joiner.token,
|
898
908
|
userData
|
899
909
|
).then((authResult) => {
|
910
|
+
var _a;
|
900
911
|
if (!authResult.success) {
|
901
|
-
|
912
|
+
this.logger.warn(`Authentication failed for client ID: ${clientId}`, authResult.error);
|
902
913
|
return new DeltaNetServerError2(
|
903
914
|
DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
|
904
|
-
"Authentication failed",
|
915
|
+
((_a = authResult.error) == null ? void 0 : _a.message) || "Authentication failed",
|
905
916
|
false
|
906
917
|
);
|
907
918
|
} else {
|
@@ -911,7 +922,7 @@ var UserNetworkingServer = class {
|
|
911
922
|
};
|
912
923
|
}
|
913
924
|
}).catch((error) => {
|
914
|
-
|
925
|
+
this.logger.error(`Authentication error for client ID: ${clientId}:`, error);
|
915
926
|
return new DeltaNetServerError2(
|
916
927
|
DeltaNetV01ServerErrors.USER_AUTHENTICATION_FAILED_ERROR_TYPE,
|
917
928
|
"Authentication error",
|
@@ -938,7 +949,7 @@ var UserNetworkingServer = class {
|
|
938
949
|
if (customMessage.customType === FROM_CLIENT_CHAT_MESSAGE_TYPE) {
|
939
950
|
const chatMessage = parseClientChatMessage(customMessage.contents);
|
940
951
|
if (chatMessage instanceof Error) {
|
941
|
-
|
952
|
+
this.logger.error(`Invalid chat message from client ${clientId}:`, chatMessage);
|
942
953
|
} else {
|
943
954
|
const serverChatMessage = {
|
944
955
|
fromUserId: clientId,
|
@@ -951,36 +962,34 @@ var UserNetworkingServer = class {
|
|
951
962
|
}
|
952
963
|
}
|
953
964
|
} else {
|
954
|
-
|
965
|
+
this.logger.warn(`Custom message from unauthenticated client ${clientId} - ignoring`);
|
955
966
|
}
|
956
967
|
}
|
957
968
|
async handleDeltaNetAuthentication(clientId, webSocket, deltaNetConnection, sessionToken, userIdentity) {
|
958
969
|
try {
|
959
|
-
let
|
960
|
-
if (!deltaNetConnection.isObserver && !
|
961
|
-
|
962
|
-
return { success: false };
|
963
|
-
}
|
964
|
-
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`);
|
965
973
|
return { success: false };
|
966
974
|
}
|
967
|
-
if (
|
968
|
-
return { success: false, error:
|
975
|
+
if (onClientConnectReturn instanceof Error) {
|
976
|
+
return { success: false, error: onClientConnectReturn };
|
969
977
|
}
|
970
|
-
if (
|
971
|
-
|
978
|
+
if (onClientConnectReturn === true) {
|
979
|
+
onClientConnectReturn = userIdentity;
|
972
980
|
}
|
981
|
+
const authenticatedUser = onClientConnectReturn;
|
973
982
|
const authenticatedClient = {
|
974
983
|
id: clientId,
|
975
984
|
socket: webSocket,
|
976
985
|
lastPong: Date.now(),
|
977
|
-
authenticatedUser
|
986
|
+
authenticatedUser,
|
978
987
|
deltaNetConnection
|
979
988
|
};
|
980
989
|
this.authenticatedClientsById.set(clientId, authenticatedClient);
|
981
990
|
let stateOverrides = [];
|
982
|
-
if (
|
983
|
-
const officialStates = DeltaNetComponentMapping.toStates(
|
991
|
+
if (onClientConnectReturn) {
|
992
|
+
const officialStates = DeltaNetComponentMapping.toStates(onClientConnectReturn);
|
984
993
|
stateOverrides = Array.from(officialStates.entries());
|
985
994
|
}
|
986
995
|
return {
|
@@ -988,14 +997,13 @@ var UserNetworkingServer = class {
|
|
988
997
|
stateOverrides
|
989
998
|
};
|
990
999
|
} catch (error) {
|
991
|
-
|
1000
|
+
this.logger.error("Authentication error:", error);
|
992
1001
|
return { success: false };
|
993
1002
|
}
|
994
1003
|
}
|
995
1004
|
connectClient(socket) {
|
996
1005
|
if (socket.protocol === "") {
|
997
1006
|
if (this.legacyAdapter) {
|
998
|
-
console.log("Legacy client detected - using legacy adapter");
|
999
1007
|
this.legacyAdapter.addWebSocket(socket);
|
1000
1008
|
return;
|
1001
1009
|
} else {
|
@@ -1015,7 +1023,7 @@ var UserNetworkingServer = class {
|
|
1015
1023
|
}
|
1016
1024
|
}
|
1017
1025
|
updateUserCharacter(clientId, userData) {
|
1018
|
-
|
1026
|
+
this.logger.info("updateUserCharacter", clientId, userData);
|
1019
1027
|
this.internalUpdateUser(clientId, userData);
|
1020
1028
|
}
|
1021
1029
|
updateUserUsername(clientId, username) {
|
@@ -1107,7 +1115,7 @@ var UserNetworkingServer = class {
|
|
1107
1115
|
if (!client) {
|
1108
1116
|
throw new Error(`internalUpdateUser - client not found for clientId ${clientId}`);
|
1109
1117
|
}
|
1110
|
-
|
1118
|
+
this.logger.info("internalUpdateUser", clientId, userData);
|
1111
1119
|
this.updatedUserProfilesInTick.add(clientId);
|
1112
1120
|
client.authenticatedUser = {
|
1113
1121
|
...client.authenticatedUser,
|
@@ -1145,7 +1153,7 @@ import {
|
|
1145
1153
|
DeltaNetClientState,
|
1146
1154
|
DeltaNetClientWebsocket,
|
1147
1155
|
DeltaNetClientWebsocketStatus
|
1148
|
-
} from "
|
1156
|
+
} from "@mml-io/delta-net-web";
|
1149
1157
|
|
1150
1158
|
// src/types.ts
|
1151
1159
|
var WebsocketStatus = /* @__PURE__ */ ((WebsocketStatus2) => {
|
@@ -1158,18 +1166,9 @@ var WebsocketStatus = /* @__PURE__ */ ((WebsocketStatus2) => {
|
|
1158
1166
|
|
1159
1167
|
// src/UserNetworkingClient.ts
|
1160
1168
|
var UserNetworkingClient = class {
|
1161
|
-
constructor(config, initialUserState, initialUpdate) {
|
1169
|
+
constructor(config, initialUserState, initialUpdate, logger = new UserNetworkingConsoleLogger()) {
|
1162
1170
|
this.config = config;
|
1163
|
-
this.
|
1164
|
-
this.userIndex = null;
|
1165
|
-
this.userState = {
|
1166
|
-
username: null,
|
1167
|
-
characterDescription: null,
|
1168
|
-
colors: null
|
1169
|
-
};
|
1170
|
-
this.stableIdToUserId = /* @__PURE__ */ new Map();
|
1171
|
-
this.userProfiles = /* @__PURE__ */ new Map();
|
1172
|
-
this.isAuthenticated = false;
|
1171
|
+
this.logger = logger;
|
1173
1172
|
this.pendingUpdate = initialUpdate ?? {
|
1174
1173
|
position: { x: 0, y: 0, z: 0 },
|
1175
1174
|
rotation: { quaternionY: 0, quaternionW: 1 },
|
@@ -1206,7 +1205,7 @@ var UserNetworkingClient = class {
|
|
1206
1205
|
this.isAuthenticated = true;
|
1207
1206
|
this.config.assignedIdentity(this.userId);
|
1208
1207
|
} else {
|
1209
|
-
|
1208
|
+
this.logger.error(
|
1210
1209
|
`Invalid userIndex ${this.userIndex}, userIds length: ${userIds.length}`
|
1211
1210
|
);
|
1212
1211
|
}
|
@@ -1224,12 +1223,9 @@ var UserNetworkingClient = class {
|
|
1224
1223
|
onUserIndex: (userIndex) => {
|
1225
1224
|
this.userIndex = userIndex.userIndex;
|
1226
1225
|
this.deltaNetState.setLocalIndex(userIndex.userIndex);
|
1227
|
-
console.log(
|
1228
|
-
`Received userIndex: ${userIndex.userIndex}, waiting for initial checkout to resolve stable userId...`
|
1229
|
-
);
|
1230
1226
|
},
|
1231
1227
|
onError: (errorType, errorMessage, retryable) => {
|
1232
|
-
|
1228
|
+
this.logger.error(
|
1233
1229
|
"DeltaNet error:",
|
1234
1230
|
errorType,
|
1235
1231
|
"errorMessage:",
|
@@ -1243,7 +1239,7 @@ var UserNetworkingClient = class {
|
|
1243
1239
|
});
|
1244
1240
|
},
|
1245
1241
|
onWarning: (warning) => {
|
1246
|
-
|
1242
|
+
this.logger.warn("DeltaNet warning:", warning);
|
1247
1243
|
},
|
1248
1244
|
onServerCustom: (customType, contents) => {
|
1249
1245
|
var _a, _b;
|
@@ -1277,6 +1273,19 @@ var UserNetworkingClient = class {
|
|
1277
1273
|
}
|
1278
1274
|
);
|
1279
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;
|
1280
1289
|
reset() {
|
1281
1290
|
this.deltaNetState.reset();
|
1282
1291
|
this.userProfiles.clear();
|
@@ -1317,7 +1326,7 @@ var UserNetworkingClient = class {
|
|
1317
1326
|
throw new Error(`Failed to extract userId from bytes for stableId ${stableId}`);
|
1318
1327
|
}
|
1319
1328
|
this.stableIdToUserId.set(stableId, userId);
|
1320
|
-
const newProfile = DeltaNetComponentMapping.fromStates(stableUserData.states);
|
1329
|
+
const newProfile = DeltaNetComponentMapping.fromStates(stableUserData.states, this.logger);
|
1321
1330
|
this.userProfiles.set(userId, newProfile);
|
1322
1331
|
const clientUpdate = DeltaNetComponentMapping.fromComponents(stableUserData.components);
|
1323
1332
|
addedUserIds.set(userId, {
|
@@ -1351,7 +1360,7 @@ var UserNetworkingClient = class {
|
|
1351
1360
|
}
|
1352
1361
|
const profile = this.userProfiles.get(userId);
|
1353
1362
|
if (!profile) {
|
1354
|
-
|
1363
|
+
this.logger.warn(`No profile found for user ${userId}, skipping update`);
|
1355
1364
|
continue;
|
1356
1365
|
}
|
1357
1366
|
const existingUpdate = updatedUsers.get(userId);
|
@@ -1362,7 +1371,9 @@ var UserNetworkingClient = class {
|
|
1362
1371
|
}
|
1363
1372
|
switch (update.stateId) {
|
1364
1373
|
case STATE_INTERNAL_CONNECTION_ID:
|
1365
|
-
|
1374
|
+
this.logger.error(
|
1375
|
+
"STATE_INTERNAL_CONNECTION_ID is not expected to change in state updates"
|
1376
|
+
);
|
1366
1377
|
break;
|
1367
1378
|
case STATE_USERNAME:
|
1368
1379
|
const username = DeltaNetComponentMapping.usernameFromBytes(update.state);
|
@@ -1379,12 +1390,12 @@ var UserNetworkingClient = class {
|
|
1379
1390
|
existingUserStateUpdate.characterDescription = characterDescription;
|
1380
1391
|
break;
|
1381
1392
|
case STATE_COLORS:
|
1382
|
-
const colors = DeltaNetComponentMapping.decodeColors(update.state);
|
1393
|
+
const colors = DeltaNetComponentMapping.decodeColors(update.state, this.logger);
|
1383
1394
|
profile.colors = colors;
|
1384
1395
|
existingUserStateUpdate.colors = colors;
|
1385
1396
|
break;
|
1386
1397
|
default:
|
1387
|
-
|
1398
|
+
this.logger.warn(`Unknown state ID: ${update.stateId}`);
|
1388
1399
|
}
|
1389
1400
|
}
|
1390
1401
|
return {
|
@@ -1403,7 +1414,7 @@ var UserNetworkingClient = class {
|
|
1403
1414
|
}
|
1404
1415
|
sendCustomMessage(customType, contents) {
|
1405
1416
|
if (!this.isAuthenticated || this.userId === null) {
|
1406
|
-
|
1417
|
+
this.logger.warn("Cannot send custom message before authentication");
|
1407
1418
|
return;
|
1408
1419
|
}
|
1409
1420
|
this.deltaNetClient.sendCustomMessage(customType, contents);
|
@@ -1442,7 +1453,7 @@ var UserNetworkingClient = class {
|
|
1442
1453
|
import {
|
1443
1454
|
DeltaNetV01ServerErrors as DeltaNetV01ServerErrors2,
|
1444
1455
|
deltaNetProtocolSubProtocol_v0_1
|
1445
|
-
} from "
|
1456
|
+
} from "@mml-io/delta-net-protocol";
|
1446
1457
|
export {
|
1447
1458
|
COMPONENT_POSITION_X,
|
1448
1459
|
COMPONENT_POSITION_Y,
|
@@ -1473,6 +1484,7 @@ export {
|
|
1473
1484
|
STATE_INTERNAL_CONNECTION_ID,
|
1474
1485
|
STATE_USERNAME,
|
1475
1486
|
UserNetworkingClient,
|
1487
|
+
UserNetworkingConsoleLogger,
|
1476
1488
|
UserNetworkingServer,
|
1477
1489
|
UserNetworkingServerError,
|
1478
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 console.log(\n \"getCharacterDescription\",\n connectionId,\n client?.authenticatedUser?.characterDescription,\n );\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 console.log(\"Legacy client detected - using legacy adapter\");\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 console.log(`Client ID: ${id} joined, waiting for user-identification`);\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 console.log(\"Client disconnected\", id);\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 console.log(\"Client authenticated\", client.id, resolvedUserData);\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 console.log(\n `Received userIndex: ${userIndex.userIndex}, waiting for initial checkout to resolve stable userId...`,\n );\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": ";AAAA,SAAS,aAAa,+BAA+B;AACrD;AAAA,EACE;AAAA,EACA,uBAAAA;AAAA,OAOK;;;ACVP,SAAS,cAAc,oBAAoB;AAOpC,IAAM,uBAAuB;AAC7B,IAAM,uBAAuB;AAC7B,IAAM,uBAAuB;AAC7B,IAAM,uBAAuB;AAC7B,IAAM,uBAAuB;AAC7B,IAAM,kBAAkB;AAGxB,IAAM,+BAA+B;AACrC,IAAM,8BAA8B;AACpC,IAAM,iBAAiB;AACvB,IAAM,eAAe;AAErB,IAAM,qBAAqB;AAC3B,IAAM,qBAAqB;AAClC,IAAM,cAAc,IAAI,YAAY;AAE7B,IAAM,2BAAN,MAAM,0BAAyB;AAAA;AAAA;AAAA;AAAA,EAIpC,OAAO,aAAa,QAAyD;AAC3E,UAAM,aAAa,oBAAI,IAAoB;AAG3C,eAAW;AAAA,MACT;AAAA,MACA,OAAO,KAAK,MAAM,OAAO,SAAS,IAAI,kBAAkB,CAAC;AAAA,IAC3D;AACA,eAAW;AAAA,MACT;AAAA,MACA,OAAO,KAAK,MAAM,OAAO,SAAS,IAAI,kBAAkB,CAAC;AAAA,IAC3D;AACA,eAAW;AAAA,MACT;AAAA,MACA,OAAO,KAAK,MAAM,OAAO,SAAS,IAAI,kBAAkB,CAAC;AAAA,IAC3D;AAIA,eAAW;AAAA,MACT;AAAA,MACA,OAAO,KAAK,MAAM,OAAO,SAAS,cAAc,kBAAkB,CAAC;AAAA,IACrE;AACA,eAAW;AAAA,MACT;AAAA,MACA,OAAO,KAAK,MAAM,OAAO,SAAS,cAAc,kBAAkB,CAAC;AAAA,IACrE;AAGA,eAAW,IAAI,iBAAiB,OAAO,OAAO,KAAK,CAAC;AAEpD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,eAAe,YAA6D;AACjF,UAAM,YACJ,OAAO,WAAW,IAAI,oBAAoB,KAAK,OAAO,CAAC,CAAC,IAAI;AAC9D,UAAM,YACJ,OAAO,WAAW,IAAI,oBAAoB,KAAK,OAAO,CAAC,CAAC,IAAI;AAC9D,UAAM,YACJ,OAAO,WAAW,IAAI,oBAAoB,KAAK,OAAO,CAAC,CAAC,IAAI;AAC9D,UAAM,YACJ,OAAO,WAAW,IAAI,oBAAoB,KAAK,OAAO,CAAC,CAAC,IAAI;AAC9D,UAAM,YACJ,OAAO,WAAW,IAAI,oBAAoB,KAAK,OAAO,CAAC,CAAC,IAAI;AAE9D,UAAM,QAAQ,OAAO,WAAW,IAAI,eAAe,KAAK,OAAO,CAAC,CAAC;AAEjE,WAAO;AAAA,MACL,UAAU,EAAE,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU;AAAA,MACrD,UAAU,EAAE,aAAa,WAAW,aAAa,UAAU;AAAA,MAC3D;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,SAAS,cAAiD;AAC/D,UAAM,SAAS,oBAAI,IAAwB;AAC3C,UAAM,cAAc,IAAI,YAAY;AAEpC,QAAI,aAAa,UAAU;AAEzB,aAAO,IAAI,gBAAgB,YAAY,OAAO,aAAa,QAAQ,CAAC;AAAA,IACtE;AAGA,QAAI,aAAa,sBAAsB;AACrC,aAAO;AAAA,QACL;AAAA,QACA,YAAY,OAAO,KAAK,UAAU,aAAa,oBAAoB,CAAC;AAAA,MACtE;AAAA,IACF;AAEA,QAAI,aAAa,QAAQ;AACvB,aAAO,IAAI,cAAc,0BAAyB,aAAa,aAAa,MAAM,CAAC;AAAA,IACrF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,gBAAgB,UAA2C;AAChE,UAAM,SAAS,oBAAI,IAAwB;AAC3C,UAAM,cAAc,IAAI,YAAY;AACpC,WAAO,IAAI,gBAAgB,YAAY,OAAO,QAAQ,CAAC;AACvD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,4BACL,sBACyB;AACzB,UAAM,SAAS,oBAAI,IAAwB;AAC3C,UAAM,cAAc,IAAI,YAAY;AACpC,WAAO;AAAA,MACL;AAAA,MACA,YAAY,OAAO,KAAK,UAAU,oBAAoB,CAAC;AAAA,IACzD;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,cAAc,QAAkE;AACrF,UAAM,SAAS,oBAAI,IAAwB;AAC3C,WAAO,IAAI,cAAc,0BAAyB,aAAa,MAAM,CAAC;AACtE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,cAAc,SAAiB,OAAqC;AACzE,UAAM,SAAS,oBAAI,IAAwB;AAC3C,UAAM,cAAc,IAAI,YAAY;AAEpC,YAAQ,SAAS;AAAA,MACf,KAAK;AACH,YAAI,OAAO,UAAU,UAAU;AAC7B,iBAAO,IAAI,SAAS,YAAY,OAAO,KAAK,CAAC;AAAA,QAC/C;AACA;AAAA,MACF,KAAK;AACH,YAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,iBAAO,IAAI,SAAS,YAAY,OAAO,KAAK,UAAU,KAAK,CAAC,CAAC;AAAA,QAC/D;AACA;AAAA,MACF,KAAK;AACH,YAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,iBAAO,IAAI,SAAS,0BAAyB,aAAa,KAAK,CAAC;AAAA,QAClE;AACA;AAAA,IACJ;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,aAAa,QAAqD;AACvE,UAAM,eAAe,IAAI,aAAa,IAAI,OAAO,SAAS,CAAC;AAC3D,iBAAa,aAAa,OAAO,MAAM;AACvC,eAAW,SAAS,QAAQ;AAC1B,mBAAa,aAAa,MAAM,CAAC,CAAC;AAClC,mBAAa,aAAa,MAAM,CAAC,CAAC;AAClC,mBAAa,aAAa,MAAM,CAAC,CAAC;AAAA,IACpC;AACA,WAAO,aAAa,UAAU;AAAA,EAChC;AAAA,EAEA,OAAO,aAAa,QAAqD;AACvE,QAAI,OAAO,eAAe,GAAG;AAC3B,aAAO,CAAC;AAAA,IACV;AACA,QAAI;AACF,YAAM,eAAe,IAAI,aAAa,MAAM;AAC5C,YAAM,cAA+C,CAAC;AACtD,YAAM,QAAQ,aAAa,YAAY;AACvC,eAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,oBAAY,KAAK;AAAA,UACf,aAAa,YAAY;AAAA,UACzB,aAAa,YAAY;AAAA,UACzB,aAAa,YAAY;AAAA,QAC3B,CAAC;AAAA,MACH;AACA,aAAO;AAAA,IACT,SAAS,GAAG;AACV,cAAQ,MAAM,yBAAyB,QAAQ,CAAC;AAChD,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEA,OAAO,eAAe,QAA2C;AAC/D,UAAM,gBAAgB,OAAO,IAAI,cAAc;AAC/C,UAAM,WAAW,gBACb,0BAAyB,kBAAkB,aAAa,IACxD;AAEJ,UAAM,qBAAqB,OAAO,IAAI,2BAA2B;AACjE,UAAM,uBAAuB,qBACzB,0BAAyB,8BAA8B,kBAAkB,IACzE;AAEJ,UAAM,cAAc,OAAO,IAAI,YAAY;AAC3C,UAAM,cAAc,cAAc,0BAAyB,aAAa,WAAW,IAAI,CAAC;AAExF,WAAO,EAAE,UAAU,sBAAsB,QAAQ,YAAY;AAAA,EAC/D;AAAA,EAEA,OAAO,gBAAgB,OAAkC;AACvD,QAAI,MAAM,WAAW,GAAG;AACtB,aAAO;AAAA,IACT;AACA,UAAM,SAAS,IAAI,aAAa,KAAK;AACrC,WAAO,OAAO,YAAY,KAAK;AAAA,EACjC;AAAA,EAEA,OAAO,kBAAkB,OAAkC;AACzD,QAAI,MAAM,WAAW,GAAG;AACtB,aAAO;AAAA,IACT;AACA,WAAO,YAAY,OAAO,KAAK;AAAA,EACjC;AAAA,EACA,OAAO,8BAA8B,OAAgD;AACnF,QAAI,MAAM,WAAW,GAAG;AACtB,aAAO;AAAA,IACT;AACA,WAAO,KAAK,MAAM,YAAY,OAAO,KAAK,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,WAAW,QAEL;AACX,UAAM,cAAc,OAAO,IAAI,4BAA4B;AAC3D,QAAI,SAAwB;AAC5B,QAAI,aAAa;AACf,YAAM,SAAS,IAAI,aAAa,WAAW;AAC3C,eAAS,OAAO,YAAY,KAAK;AAAA,IACnC;AAEA,UAAM,aAAa,0BAAyB,eAAe,MAAM;AAEjE,WAAO,EAAE,QAAQ,GAAG,WAAW;AAAA,EACjC;AACF;;;ACvQA,SAAS,2BAA2B;AAmB7B,IAAM,4BAAN,cAAwC,oBAAoB;AAAC;AAiB7D,IAAM,gCAAgC;AACtC,IAAM,gCAAgC;AACtC,IAAM,gCAAgC;AAEtC,SAAS,uBAAuB,UAA6C;AAClF,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,QAAQ;AAClC,QACE,OAAO,WAAW,YAClB,WAAW,QACX,aAAa,UACb,OAAO,OAAO,YAAY,UAC1B;AACA,aAAO;AAAA,QACL,SAAS,OAAO;AAAA,MAClB;AAAA,IACF,OAAO;AACL,YAAM,IAAI,MAAM,sBAAsB;AAAA,IACxC;AAAA,EACF,SAAS,OAAO;AACd,WAAO,IAAI,MAAM,yBAAyB,KAAK,EAAE;AAAA,EACnD;AACF;AAEO,SAAS,uBAAuB,UAA6C;AAClF,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,QAAQ;AAClC,QACE,OAAO,WAAW,YAClB,WAAW,QACX,gBAAgB,UAChB,OAAO,OAAO,eAAe,YAC7B,aAAa,UACb,OAAO,OAAO,YAAY,UAC1B;AACA,aAAO;AAAA,QACL,YAAY,OAAO;AAAA,QACnB,SAAS,OAAO;AAAA,MAClB;AAAA,IACF,OAAO;AACL,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAAA,EACF,SAAS,OAAO;AACd,WAAO,IAAI,MAAM,gCAAgC,KAAK,EAAE;AAAA,EAC1D;AACF;AAEO,SAAS,4BAA4B,UAAkD;AAC5F,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,QAAQ;AAClC,QACE,OAAO,WAAW,YAClB,WAAW,QACX,mBAAmB,UACnB,OAAO,OAAO,kBAAkB,YAChC,aAAa,UACb,OAAO,OAAO,YAAY,UAC1B;AACA,aAAO;AAAA,QACL,eAAe,OAAO;AAAA,QACtB,SAAS,OAAO;AAAA,MAClB;AAAA,IACF,OAAO;AACL,YAAM,IAAI,MAAM,kCAAkC;AAAA,IACpD;AAAA,EACF,SAAS,OAAO;AACd,WAAO,IAAI,MAAM,qCAAqC,KAAK,EAAE;AAAA,EAC/D;AACF;;;ACjGO,IAAM,4BAAN,MAAgC;AAAA,EACrC,OAAO,aAAa,QAAsD;AACxE,UAAM,SAAS,IAAI,YAAY,EAAE;AACjC,UAAM,WAAW,IAAI,SAAS,MAAM;AACpC,aAAS,UAAU,GAAG,OAAO,EAAE;AAC/B,aAAS,WAAW,GAAG,OAAO,SAAS,CAAC;AACxC,aAAS,WAAW,GAAG,OAAO,SAAS,CAAC;AACxC,aAAS,WAAW,IAAI,OAAO,SAAS,CAAC;AACzC,aAAS,SAAS,IAAI,OAAO,SAAS,cAAc,KAAK;AACzD,aAAS,SAAS,IAAI,OAAO,SAAS,cAAc,KAAK;AACzD,aAAS,SAAS,IAAI,OAAO,KAAK;AAClC,WAAO,IAAI,WAAW,MAAM;AAAA,EAC9B;AAAA,EAEA,OAAO,aAAa,QAAuD;AACzE,UAAM,WAAW,IAAI,SAAS,MAAM;AACpC,UAAM,KAAK,SAAS,UAAU,CAAC;AAC/B,UAAM,IAAI,SAAS,WAAW,CAAC;AAC/B,UAAM,IAAI,SAAS,WAAW,CAAC;AAC/B,UAAM,IAAI,SAAS,WAAW,EAAE;AAChC,UAAM,cAAc,SAAS,SAAS,EAAE,IAAI;AAC5C,UAAM,cAAc,SAAS,SAAS,EAAE,IAAI;AAC5C,UAAM,QAAQ,SAAS,SAAS,EAAE;AAClC,UAAM,WAAW,EAAE,GAAG,GAAG,EAAE;AAC3B,UAAM,WAAW,EAAE,aAAa,YAAY;AAC5C,WAAO,EAAE,IAAI,UAAU,UAAU,MAAM;AAAA,EACzC;AACF;;;AClCO,IAAM,mDAAmD;AACzD,IAAM,+CAA+C;AACrD,IAAM,wDAAwD;AAC9D,IAAM,mDAAmD;AACzD,IAAM,kDAAkD;AACxD,IAAM,uDAAuD;AAC7D,IAAM,mDAAmD;AACzD,IAAM,2CAA2C;AACjD,IAAM,2CAA2C;AAyCjD,IAAM,6DACX;AACK,IAAM,0DAA0D;AAChE,IAAM,oDAAoD;AAC1D,IAAM,uCAAuC;;;ACFpD,SAAS,cAAc,QAAgB;AACrC,QAAM,cAAc,IAAI,YAAY,OAAO,MAAM;AACjD,QAAM,OAAO,IAAI,WAAW,WAAW;AACvC,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,EAAE,GAAG;AACtC,SAAK,CAAC,IAAI,OAAO,CAAC;AAAA,EACpB;AACA,SAAO;AACT;AAEA,IAAM,sBAAsB;AAErB,IAAM,gBAAN,MAAoB;AAAA,EAIzB,YACmB,sBACA,gBACjB;AAFiB;AACA;AALnB,SAAQ,iBAAgE,oBAAI,IAAI;AAChF,SAAQ,iCAAgF,oBAAI,IAAI;AAAA,EAK7F;AAAA,EAEI,iBAAiB,eAAuB,kBAA0B;AAGvE,QAAI,kBAAkB,+BAA+B;AACnD;AAAA,IACF;AAEA,UAAM,gBAAgB,4BAA4B,gBAAgB;AAClE,QAAI,yBAAyB,OAAO;AAClC,cAAQ,MAAM,0CAA0C,aAAa;AACrE;AAAA,IACF;AAEA,UAAM,EAAE,eAAe,qBAAqB,QAAQ,IAAI;AAExD,UAAM,UAA+C;AAAA,MACnD,MAAM;AAAA,MACN,eAAe;AAAA,MACf;AAAA,IACF;AACA,UAAM,gBAAgB,KAAK,UAAU,OAAO;AAC5C,eAAW,CAAC,EAAE,MAAM,KAAK,KAAK,gCAAgC;AAC5D,UAAI,OAAO,OAAO,eAAe,qBAAqB;AACpD,eAAO,OAAO,KAAK,aAAa;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AAAA,EAEO,aAAa,QAAmB;AACrC,UAAM,KAAK,KAAK,qBAAqB,kBAAkB;AACvD,YAAQ,IAAI,cAAc,EAAE,0CAA0C;AAGtE,UAAM,SAA2C;AAAA,MAC/C;AAAA,MACA,UAAU,KAAK,IAAI;AAAA,MACnB;AAAA,MACA,mBAAmB;AAAA,MACnB,QAAQ;AAAA,QACN;AAAA,QACA,UAAU,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE;AAAA,QAC7B,UAAU,EAAE,aAAa,GAAG,aAAa,EAAE;AAAA,QAC3C,OAAO;AAAA,MACT;AAAA,IACF;AACA,SAAK,eAAe,IAAI,IAAI,MAAM;AAElC,WAAO,iBAAiB,WAAW,CAAC,YAA0B;AAC5D,UAAI;AACF,YAAI,QAAQ,gBAAgB,eAAe,QAAQ,gBAAgB,QAAQ;AACzE,cAAI,OAAO,mBAAmB;AAC5B,kBAAM,cACJ,QAAQ,gBAAgB,cAAc,QAAQ,OAAO,cAAc,QAAQ,IAAI;AACjF,kBAAM,SAAS,0BAA0B,aAAa,WAAW;AACjE,mBAAO,KAAK;AACZ,kBAAM,QAAQ,KAAK,eAAe,0CAA0C,EAAE,IAAI,EAAE;AACpF,mBAAO,SAAS;AAChB,gBAAI,UAAU,QAAW;AACvB,mBAAK,eAAe;AAAA,gBAClB;AAAA,gBACA;AAAA,gBACA,OAAO,KAAK,MAAM,OAAO,SAAS,IAAI,kBAAkB,CAAC;AAAA,cAC3D;AACA,mBAAK,eAAe;AAAA,gBAClB;AAAA,gBACA;AAAA,gBACA,OAAO,KAAK,MAAM,OAAO,SAAS,IAAI,kBAAkB,CAAC;AAAA,cAC3D;AACA,mBAAK,eAAe;AAAA,gBAClB;AAAA,gBACA;AAAA,gBACA,OAAO,KAAK,MAAM,OAAO,SAAS,IAAI,kBAAkB,CAAC;AAAA,cAC3D;AACA,mBAAK,eAAe;AAAA,gBAClB;AAAA,gBACA;AAAA,gBACA,OAAO,KAAK,MAAM,OAAO,SAAS,cAAc,kBAAkB,CAAC;AAAA,cACrE;AACA,mBAAK,eAAe;AAAA,gBAClB;AAAA,gBACA;AAAA,gBACA,OAAO,KAAK,MAAM,OAAO,SAAS,cAAc,kBAAkB,CAAC;AAAA,cACrE;AACA,mBAAK,eAAe;AAAA,gBAClB;AAAA,gBACA;AAAA,gBACA,OAAO,KAAK,MAAM,OAAO,KAAK,CAAC;AAAA,cACjC;AAAA,YACF;AAAA,UACF;AAAA,QACF,OAAO;AACL,cAAI;AACJ,cAAI;AACF,qBAAS,KAAK,MAAM,QAAQ,IAAc;AAAA,UAC5C,SAAS,GAAG;AACV,oBAAQ,MAAM,8BAA8B,SAAS,CAAC;AACtD;AAAA,UACF;AACA,cAAI,CAAC,OAAO,mBAAmB;AAC7B,gBAAI,OAAO,SAAS,uDAAuD;AACzE,mBAAK,eAAe,QAAQ,MAAM,EAAE,KAAK,CAAC,eAAe;AACvD,oBAAI,OAAO,OAAO,eAAe,qBAAqB;AAEpD;AAAA,gBACF;AACA,oBAAI,CAAC,YAAY;AACf,0BAAQ,MAAM,aAAa,OAAO,EAAE,qBAAqB,UAAU;AAEnE,wBAAM,cAAc,KAAK,UAAU;AAAA,oBACjC,MAAM;AAAA,oBACN,WAAW;AAAA,oBACX,SAAS;AAAA,kBACX,CAA0C;AAC1C,yBAAO,KAAK,WAAW;AACvB,yBAAO,MAAM;AAAA,gBACf,OAAO;AACL,sBAAI,CAAC,KAAK,qBAAqB,2BAA2B,GAAG;AAE3D,0BAAM,cAAc,KAAK,UAAU;AAAA,sBACjC,MAAM;AAAA,sBACN,WAAW;AAAA,sBACX,SAAS;AAAA,oBACX,CAA0C;AAC1C,2BAAO,KAAK,WAAW;AACvB,2BAAO,MAAM;AACb;AAAA,kBACF;AAEA,wBAAM,WAAW;AAEjB,uBAAK,eAAe,gCAAgC,CAAC,UAAU;AAC7D,wBAAI,OAAO,OAAO,eAAe,qBAAqB;AACpD,6BAAO;AAAA,oBACT;AACA,2BAAO,oBAAoB;AAC3B,yBAAK,eAAe,kBAAkB,sBAAsB,OAAO,OAAO,CAAC,CAAC;AAC5E,yBAAK,eAAe,kBAAkB,sBAAsB,OAAO,OAAO,CAAC,CAAC;AAC5E,yBAAK,eAAe,kBAAkB,sBAAsB,OAAO,OAAO,CAAC,CAAC;AAC5E,yBAAK,eAAe,kBAAkB,sBAAsB,OAAO,OAAO,CAAC,CAAC;AAC5E,yBAAK,eAAe,kBAAkB,sBAAsB,OAAO,OAAO,CAAC,CAAC;AAC5E,yBAAK,eAAe,kBAAkB,iBAAiB,OAAO,OAAO,CAAC,CAAC;AAEvE,0BAAM,aAAuB;AAAA,sBAC3B,GAAG;AAAA,sBACH,QAAQ,CAAC;AAAA,oBACX;AACA,2BAAO;AAAA,sBACL,IAAI,OAAO;AAAA,sBACX,kBAAkB,MAAM;AACtB,6BAAK,qBAAqB;AAAA,0BACxB,OAAO;AAAA,0BACP,OAAO;AAAA,0BACP;AAAA,wBACF;AACA,6BAAK,qBAAqB,oBAAoB,OAAO,IAAI,UAAU;AAAA,sBACrE;AAAA,oBACF;AAAA,kBACF,CAAC;AAGD,wBAAM,qBAAqB,KAAK,UAAU;AAAA,oBACxC,IAAI,OAAO;AAAA,oBACX,MAAM;AAAA,oBACN,UAAU,SAAS;AAAA,oBACnB,sBAAsB,SAAS;AAAA,kBACjC,CAA0C;AAC1C,yBAAO,OAAO,KAAK,kBAAkB;AAGrC,wBAAM,kBAAkB,KAAK,UAAU;AAAA,oBACrC,IAAI,OAAO;AAAA,oBACX,MAAM;AAAA,kBACR,CAA0C;AAC1C,yBAAO,OAAO,KAAK,eAAe;AAElC,wBAAM,WACJ,KAAK,eAAe,0CAA0C;AAChE,6BAAW,CAAC,cAAc,cAAc,KAAK,UAAU;AACrD,wBAAI,iBAAiB,OAAO,IAAI;AAC9B;AAAA,oBACF;AACA,0BAAM,IACJ,KAAK,eAAe,kBAAkB,sBAAsB,cAAc,IAC1E;AACF,0BAAM,IACJ,KAAK,eAAe,kBAAkB,sBAAsB,cAAc,IAC1E;AACF,0BAAM,IACJ,KAAK,eAAe,kBAAkB,sBAAsB,cAAc,IAC1E;AACF,0BAAM,cACJ,KAAK,eAAe,kBAAkB,sBAAsB,cAAc,IAC1E;AACF,0BAAM,cACJ,KAAK,eAAe,kBAAkB,sBAAsB,cAAc,IAC1E;AACF,0BAAM,QAAQ,KAAK,eAAe;AAAA,sBAChC;AAAA,sBACA;AAAA,oBACF;AACA,0BAAM,SAAS,0BAA0B,aAAa;AAAA,sBACpD,IAAI;AAAA,sBACJ,UAAU,EAAE,GAAG,GAAG,EAAE;AAAA,sBACpB,UAAU,EAAE,aAAa,YAAY;AAAA,sBACrC;AAAA,oBACF,CAAC;AAED,2BAAO,OAAO;AAAA,sBACZ,KAAK,UAAU;AAAA,wBACb,IAAI;AAAA,wBACJ,MAAM;AAAA,wBACN,UAAU,KAAK,qBAAqB,YAAY,YAAY;AAAA,wBAC5D,sBACE,KAAK,qBAAqB,wBAAwB,YAAY;AAAA,sBAClE,CAAiD;AAAA,oBACnD;AACA,2BAAO,OAAO,KAAK,MAAM;AAAA,kBAC3B;AAEA,uBAAK,+BAA+B,IAAI,IAAI,MAAM;AAAA,gBACpD;AAAA,cACF,CAAC;AAAA,YACH,OAAO;AACL,sBAAQ,MAAM,+BAA+B,KAAK,UAAU,MAAM,CAAC,EAAE;AACrE,qBAAO,MAAM;AAAA,YACf;AAAA,UACF,OAAO;AACL,oBAAQ,OAAO,MAAM;AAAA,cACnB,KAAK;AACH,uBAAO,WAAW,KAAK,IAAI;AAC3B;AAAA,cAEF,KAAK;AACH,qBAAK,iBAAiB,IAAI,MAA+C;AACzE;AAAA,cAEF;AACE,wBAAQ,MAAM,sBAAsB,KAAK,UAAU,MAAM,CAAC,EAAE;AAAA,YAChE;AAAA,UACF;AAAA,QACF;AAAA,MACF,SAAS,GAAG;AACV,gBAAQ,MAAM,0BAA0B,SAAS,CAAC;AAClD,eAAO;AAAA,UACL,KAAK,UAAU;AAAA,YACb,MAAM;AAAA,YACN,WAAW;AAAA,YACX,SAAS;AAAA,UACX,CAAiD;AAAA,QACnD;AACA,eAAO,MAAM;AAAA,MACf;AAAA,IACF,CAAC;AAED,WAAO,iBAAiB,SAAS,MAAM;AACrC,cAAQ,IAAI,uBAAuB,EAAE;AACrC,WAAK,yBAAyB,MAAM;AAAA,IACtC,CAAC;AAAA,EACH;AAAA,EAEQ,yBAAyB,QAA0C;AACzE,QAAI,CAAC,KAAK,eAAe,IAAI,OAAO,EAAE,GAAG;AACvC;AAAA,IACF;AACA,SAAK,eAAe,OAAO,OAAO,EAAE;AACpC,QAAI,OAAO,sBAAsB,MAAM;AAErC,WAAK,qBAAqB,yBAAyB,OAAO,EAAE;AAC5D,WAAK,+BAA+B,OAAO,OAAO,EAAE;AACpD,WAAK,eAAe,0BAA0B,OAAO,EAAE;AAAA,IACzD;AAAA,EACF;AAAA,EAEA,MAAc,eACZ,QACA,aACiC;AACjC,UAAM,WAAW,KAAK,qBAAqB;AAAA,MACzC,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,YAAY;AAAA,IACd;AACA,QAAI;AACJ,QAAI,oBAAoB,SAAS;AAC/B,yBAAmB,MAAM;AAAA,IAC3B,OAAO;AACL,yBAAmB;AAAA,IACrB;AAEA,QAAI,4BAA4B,OAAO;AACrC,cAAQ,MAAM,aAAa,OAAO,EAAE,qBAAqB,gBAAgB;AACzE,aAAO;AAAA,IACT,WAAW,qBAAqB,MAAM;AACpC,cAAQ,MAAM,aAAa,OAAO,EAAE,qBAAqB,gBAAgB;AACzE,yBAAmB,YAAY;AAAA,IACjC,OAAO;AACL,yBAAmB;AAAA,IACrB;AACA,QAAI,qBAAqB,MAAM;AAC7B,cAAQ,MAAM,aAAa,OAAO,EAAE,qCAAqC;AACzE,aAAO;AAAA,IACT;AAEA,YAAQ,IAAI,wBAAwB,OAAO,IAAI,gBAAgB;AAE/D,WAAO;AAAA,EACT;AAAA,EAEO,oBAAoB,UAAkB,UAA0B;AACrE,SAAK,mBAAmB,UAAU,QAAQ;AAAA,EAC5C;AAAA,EAEQ,mBAAmB,UAAkB,UAA0B;AAErE,UAAM,SAAS,KAAK,+BAA+B,IAAI,QAAQ;AAE/D,WAAO,oBAAoB;AAC3B,SAAK,+BAA+B,IAAI,UAAU,MAAM;AAExD,SAAK,qBAAqB,oBAAoB,OAAO,IAAI,EAAE,GAAG,UAAU,QAAQ,CAAC,EAAE,CAAC;AAAA,EACtF;AAAA,EAEA,MAAc,iBACZ,UACA,SACe;AACf,UAAM,SAAS,KAAK,+BAA+B,IAAI,QAAQ;AAC/D,QAAI,CAAC,QAAQ;AACX,cAAQ,MAAM,aAAa,QAAQ,wCAAwC;AAC3E;AAAA,IACF;AAIA,UAAM,qBAAqB,QAAQ;AAEnC,QAAI;AACJ,QAAI,8BAA8B,SAAS;AACzC,mCAA6B,MAAM;AAAA,IACrC,OAAO;AACL,mCAA6B;AAAA,IAC/B;AACA,QAAI,CAAC,4BAA4B;AAE/B,cAAQ,KAAK,aAAa,QAAQ,uCAAuC;AACzE;AAAA,IACF;AAEA,SAAK,mBAAmB,UAAU,0BAA0B;AAAA,EAC9D;AAAA,EAEO,YACL,YACA,UACA,0BACM;AACN,eAAW,MAAM,YAAY;AAC3B,YAAM,oBAAoB,KAAK,UAAU;AAAA,QACvC;AAAA,QACA,MAAM;AAAA,MACR,CAA0C;AAC1C,iBAAW,CAAC,EAAE,WAAW,KAAK,KAAK,gCAAgC;AACjE,YAAI,YAAY,OAAO,eAAe,qBAAqB;AACzD,sBAAY,OAAO,KAAK,iBAAiB;AAAA,QAC3C;AAAA,MACF;AAAA,IACF;AAEA,eAAW,MAAM,UAAU;AACzB,YAAM,kBAAkB,KAAK,UAAU;AAAA,QACrC;AAAA,QACA,MAAM;AAAA,QACN,UAAU,KAAK,qBAAqB,YAAY,EAAE;AAAA,QAClD,sBAAsB,KAAK,qBAAqB,wBAAwB,EAAE;AAAA,MAC5E,CAAiD;AACjD,iBAAW,CAAC,EAAE,WAAW,KAAK,KAAK,gCAAgC;AACjE,YAAI,YAAY,OAAO,eAAe,qBAAqB;AACzD,sBAAY,OAAO,KAAK,eAAe;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AAEA,eAAW,MAAM,0BAA0B;AACzC,YAAM,kBAAkB,KAAK,UAAU;AAAA,QACrC;AAAA,QACA,MAAM;AAAA,QACN,UAAU,KAAK,qBAAqB,YAAY,EAAE;AAAA,QAClD,sBAAsB,KAAK,qBAAqB,wBAAwB,EAAE;AAAA,MAC5E,CAAiD;AACjD,iBAAW,CAAC,EAAE,WAAW,KAAK,KAAK,gCAAgC;AACjE,YAAI,YAAY,OAAO,eAAe,qBAAqB;AACzD,sBAAY,OAAO,KAAK,eAAe;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AAEA,eAAW,CAAC,UAAU,MAAM,KAAK,KAAK,gCAAgC;AACpE,YAAM,gBAAgB,0BAA0B,aAAa,OAAO,MAAM;AAE1E,iBAAW,CAAC,eAAe,WAAW,KAAK,KAAK,gCAAgC;AAC9E,YAAI,kBAAkB,YAAY,YAAY,OAAO,eAAe,qBAAqB;AACvF,sBAAY,OAAO,KAAK,aAAa;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AAEA,UAAM,WACJ,KAAK,eAAe,0CAA0C;AAChE,eAAW,CAAC,cAAc,cAAc,KAAK,UAAU;AACrD,YAAM,IACJ,KAAK,eAAe,kBAAkB,sBAAsB,cAAc,IAC1E;AACF,YAAM,IACJ,KAAK,eAAe,kBAAkB,sBAAsB,cAAc,IAC1E;AACF,YAAM,IACJ,KAAK,eAAe,kBAAkB,sBAAsB,cAAc,IAC1E;AACF,YAAM,cACJ,KAAK,eAAe,kBAAkB,sBAAsB,cAAc,IAC1E;AACF,YAAM,cACJ,KAAK,eAAe,kBAAkB,sBAAsB,cAAc,IAC1E;AACF,YAAM,QAAQ,KAAK,eAAe,kBAAkB,iBAAiB,cAAc;AACnF,YAAM,gBAAgB,0BAA0B,aAAa;AAAA,QAC3D,IAAI;AAAA,QACJ,UAAU,EAAE,GAAG,GAAG,EAAE;AAAA,QACpB,UAAU,EAAE,aAAa,YAAY;AAAA,QACrC;AAAA,MACF,CAAC;AAED,iBAAW,CAAC,eAAe,WAAW,KAAK,KAAK,gCAAgC;AAC9E,YACE,kBAAkB,gBAClB,YAAY,OAAO,eAAe,qBAClC;AACA,sBAAY,OAAO,KAAK,aAAa;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEO,QAAQ,kBAAoD;AACjE,UAAM,mBAAmB,mBAAmB,KAAK,UAAU,gBAAgB,IAAI;AAE/E,eAAW,CAAC,EAAE,MAAM,KAAK,KAAK,gCAAgC;AAC5D,UAAI,kBAAkB;AACpB,eAAO,OAAO,KAAK,gBAAgB;AAAA,MACrC;AACA,aAAO,OAAO,MAAM;AAAA,IACtB;AAAA,EACF;AACF;;;AL3dO,IAAM,uBAAN,MAA2B;AAAA,EAOhC,YAAoB,SAAsC;AAAtC;AALpB,SAAQ,2BAAoE,oBAAI,IAAI;AAEpF,SAAQ,gBAAsC;AAC9C,SAAQ,4BAAyC,oBAAI,IAAI;AAGvD,SAAK,iBAAiB,IAAI,eAAe;AAAA,MACvC,2BAA2B;AAAA,MAC3B,UAAU,CAAC,WAA4B;AACrC,eAAO,KAAK,aAAa,MAAM;AAAA,MACjC;AAAA,MACA,SAAS,CAAC,UAA0B;AAClC,aAAK,YAAY,KAAK;AAAA,MACxB;AAAA,MACA,oBAAoB,CAAC,WAAsC;AAEzD;AAAA,MACF;AAAA,MACA,gBAAgB,CAAC,WAAkC;AACjD,eAAO,KAAK,mBAAmB,MAAM;AAAA,MACvC;AAAA,MACA,iBAAiB,CAAC,kBAA0C;AAC1D,aAAK,oBAAoB,aAAa;AAAA,MACxC;AAAA,IACF,CAAC;AACD,QAAI,KAAK,QAAQ,sBAAsB;AACrC,WAAK,gBAAgB,IAAI,cAAc,MAAM,KAAK,cAAc;AAAA,IAClE;AAGA,SAAK,eAAe,YAAY,MAAM;AACpC,YAAM,EAAE,YAAY,SAAS,IAAI,KAAK,eAAe,KAAK;AAC1D,UAAI,KAAK,eAAe;AACtB,aAAK,cAAc,YAAY,YAAY,UAAU,KAAK,yBAAyB;AACnF,aAAK,0BAA0B,MAAM;AAAA,MACvC;AAAA,IACF,GAAG,EAAE;AAAA,EACP;AAAA,EAEA,wBACE,cAC4E;AA5FhF;AA6FI,UAAM,SAAS,KAAK,yBAAyB,IAAI,YAAY;AAC7D,YAAQ;AAAA,MACN;AAAA,MACA;AAAA,OACA,sCAAQ,sBAAR,mBAA2B;AAAA,IAC7B;AACA,aAAO,sCAAQ,sBAAR,mBAA2B,yBAAwB,EAAE,iBAAiB,GAAG;AAAA,EAClF;AAAA,EACA,YAAY,cAA8B;AArG5C;AAsGI,UAAM,SAAS,KAAK,yBAAyB,IAAI,YAAY;AAC7D,YAAQ,IAAI,eAAe,eAAc,sCAAQ,sBAAR,mBAA2B,QAAQ;AAC5E,aAAO,sCAAQ,sBAAR,mBAA2B,aAAY;AAAA,EAChD;AAAA,EAEO,oBAAoB;AACzB,WAAO,KAAK,eAAe,oBAAoB;AAAA,EACjD;AAAA,EAEO,6BAA6B;AAClC,WAAO;AAAA,EACT;AAAA,EAEO,sBACL,IACA,cACA,cAC4D;AAC5D,WAAO,KAAK,QAAQ,gBAAgB,IAAI,cAAc;AAAA,MACpD,WAAU,6CAAc,aAAY;AAAA,MACpC,uBAAsB,6CAAc,yBAAwB;AAAA,MAC5D,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAAA,EAEO,uCACL,UACA,WACA,UACA;AACA,YAAQ,IAAI,0CAA0C,UAAU,QAAQ;AACxE,UAAM,sBAAkD;AAAA,MACtD,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,UAAU,KAAK,IAAI;AAAA,MACnB,mBAAmB;AAAA,MACnB,oBAAoB;AAAA,IACtB;AACA,SAAK,yBAAyB,IAAI,UAAU,mBAAmB;AAAA,EACjE;AAAA,EAEO,yBAAyB,IAAY;AAC1C,SAAK,QAAQ,mBAAmB,EAAE;AAAA,EACpC;AAAA,EAEQ,mBACN,QAOI;AACJ,UAAM,qBAAqB,OAAO;AAClC,UAAM,WAAW,mBAAmB;AACpC,UAAM,gBAAgB,OAAO;AAC7B,UAAM,mBAAmB,IAAI,IAAwB,aAAa;AAClE,UAAM,kBAA4B,yBAAyB,eAAe,gBAAgB;AAE1F,UAAM,iBAAiB,KAAK,yBAAyB,IAAI,QAAQ;AACjE,QAAI,CAAC,gBAAgB;AACnB,aAAO,IAAIC;AAAA,QACT,wBAAwB;AAAA,QACxB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,UAAM,mBAAmB,eAAe,qBAAqB,CAAC;AAC9D,UAAM,WAAW;AAAA,MACf,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AAEA,UAAM,MAAM,KAAK,QAAQ,2BAA2B,UAAU,QAAQ;AACtE,QAAI,eAAe,SAAS;AAC1B,aAAO,IAAI,KAAK,CAACC,SAAQ;AACvB,YAAI,CAAC,KAAK,yBAAyB,IAAI,QAAQ,GAAG;AAChD,iBAAO,IAAID;AAAA,YACT,wBAAwB;AAAA,YACxB;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAEA,YAAIC,gBAAeD,sBAAqB;AACtC,iBAAOC;AAAA,QACT;AACA,YAAIA,gBAAe,OAAO;AACxB,iBAAO,IAAID;AAAA,YACT,wBAAwB;AAAA,YACxB;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,YAAIC,SAAQ,MAAM;AAChB,iBAAO,IAAID;AAAA,YACT,wBAAwB;AAAA,YACxB;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,YAAIC,SAAQ,OAAO;AACjB,iBAAO,IAAID;AAAA,YACT,wBAAwB;AAAA,YACxB;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,YAAI,CAACC,QAAO,OAAOA,SAAQ,UAAU;AACnC,iBAAO,IAAID;AAAA,YACT,wBAAwB;AAAA,YACxB;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAEA,aAAK,0BAA0B,IAAI,QAAQ;AAE3C,uBAAe,oBAAoB;AAAA,UACjC,GAAG,eAAe;AAAA,UAClB,GAAGC;AAAA,QACL;AAEA,eAAO;AAAA,UACL,SAAS;AAAA,UACT,gBAAgB,MAAM,KAAK,yBAAyB,SAASA,IAAG,EAAE,QAAQ,CAAC;AAAA,QAC7E;AAAA,MACF,CAAC;AAAA,IACH;AACA,QAAI,eAAeD,sBAAqB;AACtC,aAAO;AAAA,IACT;AACA,QAAI,eAAe,OAAO;AACxB,aAAO,IAAIA;AAAA,QACT,wBAAwB;AAAA,QACxB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,QAAI,QAAQ,MAAM;AAChB,aAAO,IAAIA;AAAA,QACT,wBAAwB;AAAA,QACxB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,QAAI,QAAQ,OAAO;AACjB,aAAO,IAAIA;AAAA,QACT,wBAAwB;AAAA,QACxB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACnC,aAAO,IAAIA;AAAA,QACT,wBAAwB;AAAA,QACxB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,SAAK,0BAA0B,IAAI,QAAQ;AAE3C,mBAAe,oBAAoB;AAAA,MACjC,GAAG,eAAe;AAAA,MAClB,GAAG;AAAA,IACL;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,gBAAgB,MAAM,KAAK,yBAAyB,SAAS,GAAG,EAAE,QAAQ,CAAC;AAAA,IAC7E;AAAA,EACF;AAAA,EAEQ,aACN,QAOI;AACJ,UAAM,qBAAqB,OAAO;AAClC,UAAM,YAAY,mBAAmB;AACrC,UAAM,SAAS,OAAO;AACtB,UAAM,WAAW,OAAO;AAExB,UAAM,YAAY,IAAI,IAAwB,MAAM;AACpD,UAAM,WAAqB,yBAAyB,eAAe,SAAS;AAG5E,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,MACP;AAAA,IACF,EACG,KAAK,CAAC,eAAe;AACpB,UAAI,CAAC,WAAW,SAAS;AAEvB,gBAAQ,KAAK,wCAAwC,QAAQ,EAAE;AAC/D,eAAO,IAAIA;AAAA,UACT,wBAAwB;AAAA,UACxB;AAAA,UACA;AAAA,QACF;AAAA,MACF,OAAO;AAEL,eAAO;AAAA,UACL,SAAS;AAAA,UACT,gBAAgB,WAAW;AAAA,QAC7B;AAAA,MACF;AAAA,IACF,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,cAAQ,MAAM,uCAAuC,QAAQ,KAAK,KAAK;AACvE,aAAO,IAAIA;AAAA,QACT,wBAAwB;AAAA,QACxB;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACL;AAAA,EAEQ,YAAY,OAA6B;AAC/C,UAAM,qBAAqB,MAAM;AACjC,UAAM,WAAW,mBAAmB;AAEpC,QAAI,aAAa,QAAW;AAC1B,YAAM,SAAS,KAAK,yBAAyB,IAAI,QAAQ;AACzD,UAAI,QAAQ;AACV,aAAK,QAAQ,mBAAmB,QAAQ;AACxC,aAAK,yBAAyB,OAAO,QAAQ;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,oBAAoB,eAA6C;AACvE,UAAM,qBAAqB,cAAc;AACzC,UAAM,WAAW,mBAAmB;AAEpC,UAAM,SAAS,KAAK,yBAAyB,IAAI,QAAQ;AACzD,QAAI,UAAU,OAAO,mBAAmB;AAEtC,UAAI,cAAc,eAAe,+BAA+B;AAC9D,cAAM,cAAc,uBAAuB,cAAc,QAAQ;AACjE,YAAI,uBAAuB,OAAO;AAChC,kBAAQ,MAAM,oCAAoC,QAAQ,KAAK,WAAW;AAAA,QAC5E,OAAO;AACL,gBAAM,oBAAuC;AAAA,YAC3C,YAAY;AAAA,YACZ,SAAS,YAAY;AAAA,UACvB;AAEA,eAAK,eAAe;AAAA,YAClB;AAAA,YACA,KAAK,UAAU,iBAAiB;AAAA,UAClC;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,cAAQ,KAAK,8CAA8C,QAAQ,aAAa;AAAA,IAClF;AAAA,EACF;AAAA,EAEA,MAAc,6BACZ,UACA,WACA,oBACA,cACA,cAIA;AACA,QAAI;AAEF,UAAI,WAAW,mBAAmB,aAC9B,OACA,MAAM,KAAK,QAAQ,gBAAgB,UAAU,cAAc,YAAY;AAE3E,UAAI,CAAC,mBAAmB,cAAc,CAAC,UAAU;AAC/C,gBAAQ,KAAK,oCAAoC,QAAQ,0BAA0B;AACnF,eAAO,EAAE,SAAS,MAAM;AAAA,MAC1B;AAGA,UACE,KAAK,QAAQ,oBAAoB,UACjC,KAAK,yBAAyB,QAAQ,KAAK,QAAQ,iBACnD;AACA,eAAO,EAAE,SAAS,MAAM;AAAA,MAC1B;AAEA,UAAI,oBAAoB,OAAO;AAC7B,eAAO,EAAE,SAAS,OAAO,OAAO,SAAS;AAAA,MAC3C;AAEA,UAAI,aAAa,MAAM;AACrB,mBAAW;AAAA,MACb;AAGA,YAAM,sBAAkD;AAAA,QACtD,IAAI;AAAA,QACJ,QAAQ;AAAA,QACR,UAAU,KAAK,IAAI;AAAA,QACnB,mBAAmB;AAAA,QACnB;AAAA,MACF;AACA,WAAK,yBAAyB,IAAI,UAAU,mBAAmB;AAI/D,UAAI,iBAA8C,CAAC;AACnD,UAAI,UAAU;AACZ,cAAM,iBAAiB,yBAAyB,SAAS,QAAQ;AACjE,yBAAiB,MAAM,KAAK,eAAe,QAAQ,CAAC;AAAA,MACtD;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,yBAAyB,KAAK;AAC5C,aAAO,EAAE,SAAS,MAAM;AAAA,IAC1B;AAAA,EACF;AAAA,EAEO,cAAc,QAAyB;AAC5C,QAAI,OAAO,aAAa,IAAI;AAE1B,UAAI,KAAK,eAAe;AACtB,gBAAQ,IAAI,+CAA+C;AAC3D,aAAK,cAAc,aAAa,MAAyC;AACzE;AAAA,MACF,OAAO;AACL,eAAO,MAAM,KAAM,yDAAyD;AAC5E;AAAA,MACF;AAAA,IACF;AAGA,SAAK,eAAe,aAAa,MAAyC;AAE1E,WAAO,iBAAiB,SAAS,MAAM;AACrC,WAAK,eAAe,gBAAgB,MAAyC;AAAA,IAC/E,CAAC;AAAA,EACH;AAAA,EAEO,iBAAiB,eAAuB,kBAAgC;AAC7E,SAAK,eAAe,uBAAuB,eAAe,gBAAgB;AAC1E,QAAI,KAAK,eAAe;AACtB,WAAK,cAAc,iBAAiB,eAAe,gBAAgB;AAAA,IACrE;AAAA,EACF;AAAA,EAEO,oBAAoB,UAAkB,UAA0B;AACrE,YAAQ,IAAI,uBAAuB,UAAU,QAAQ;AACrD,SAAK,mBAAmB,UAAU,QAAQ;AAAA,EAC5C;AAAA,EAEO,mBAAmB,UAAkB,UAAwB;AAClE,UAAM,SAAS,KAAK,yBAAyB,IAAI,QAAQ;AACzD,QAAI,CAAC,UAAU,CAAC,OAAO,kBAAmB;AAG1C,WAAO,oBAAoB;AAAA,MACzB,GAAG,OAAO;AAAA,MACV;AAAA,IACF;AAEA,SAAK,0BAA0B,IAAI,QAAQ;AAG3C,UAAM,SAAS,yBAAyB,gBAAgB,QAAQ;AAChE,UAAM,UAAU,MAAM,KAAK,OAAO,QAAQ,CAAC;AAC3C,SAAK,eAAe,mBAAmB,OAAO,oBAAoB,UAAU,OAAO;AAAA,EACrF;AAAA,EAEO,+BACL,UACA,sBACM;AACN,UAAM,SAAS,KAAK,yBAAyB,IAAI,QAAQ;AACzD,QAAI,CAAC,UAAU,CAAC,OAAO,kBAAmB;AAG1C,WAAO,oBAAoB;AAAA,MACzB,GAAG,OAAO;AAAA,MACV;AAAA,IACF;AAEA,SAAK,0BAA0B,IAAI,QAAQ;AAG3C,UAAM,SAAS,yBAAyB,4BAA4B,oBAAoB;AACxF,UAAM,UAAU,MAAM,KAAK,OAAO,QAAQ,CAAC;AAC3C,SAAK,eAAe,mBAAmB,OAAO,oBAAoB,UAAU,OAAO;AAAA,EACrF;AAAA,EAEO,iBAAiB,UAAkB,QAA+C;AACvF,UAAM,SAAS,KAAK,yBAAyB,IAAI,QAAQ;AACzD,QAAI,CAAC,UAAU,CAAC,OAAO,kBAAmB;AAG1C,WAAO,oBAAoB;AAAA,MACzB,GAAG,OAAO;AAAA,MACV;AAAA,IACF;AAEA,SAAK,0BAA0B,IAAI,QAAQ;AAG3C,UAAM,SAAS,yBAAyB,cAAc,MAAM;AAC5D,UAAM,UAAU,MAAM,KAAK,OAAO,QAAQ,CAAC;AAC3C,SAAK,eAAe,mBAAmB,OAAO,oBAAoB,UAAU,OAAO;AAAA,EACrF;AAAA,EAEO,iBAAiB,UAAkB,SAAyB;AACjE,UAAM,SAAS,KAAK,yBAAyB,IAAI,QAAQ;AACzD,QAAI,CAAC,UAAU,CAAC,OAAO,kBAAmB;AAE1C,UAAM,SAAS,oBAAI,IAAwB;AAC3C,QAAI,aAAa;AACjB,QAAI,kBAAkB,OAAO;AAE7B,SAAK,0BAA0B,IAAI,QAAQ;AAG3C,QAAI,QAAQ,aAAa,MAAM;AAC7B,wBAAkB;AAAA,QAChB,GAAG;AAAA,QACH,UAAU,QAAQ;AAAA,MACpB;AACA,YAAM,iBAAiB,yBAAyB,gBAAgB,QAAQ,QAAQ;AAChF,iBAAW,CAAC,SAAS,UAAU,KAAK,gBAAgB;AAClD,eAAO,IAAI,SAAS,UAAU;AAAA,MAChC;AACA,mBAAa;AAAA,IACf;AAGA,QAAI,QAAQ,yBAAyB,MAAM;AACzC,wBAAkB;AAAA,QAChB,GAAG;AAAA,QACH,sBAAsB,QAAQ;AAAA,MAChC;AACA,YAAM,sBAAsB,yBAAyB;AAAA,QACnD,QAAQ;AAAA,MACV;AACA,iBAAW,CAAC,SAAS,UAAU,KAAK,qBAAqB;AACvD,eAAO,IAAI,SAAS,UAAU;AAAA,MAChC;AACA,mBAAa;AAAA,IACf;AAGA,QAAI,QAAQ,WAAW,MAAM;AAC3B,wBAAkB;AAAA,QAChB,GAAG;AAAA,QACH,QAAQ,QAAQ;AAAA,MAClB;AACA,YAAM,eAAe,yBAAyB,cAAc,QAAQ,MAAM;AAC1E,iBAAW,CAAC,SAAS,UAAU,KAAK,cAAc;AAChD,eAAO,IAAI,SAAS,UAAU;AAAA,MAChC;AACA,mBAAa;AAAA,IACf;AAGA,QAAI,YAAY;AACd,aAAO,oBAAoB;AAC3B,YAAM,UAAU,MAAM,KAAK,OAAO,QAAQ,CAAC;AAC3C,WAAK,eAAe,mBAAmB,OAAO,oBAAoB,UAAU,OAAO;AAAA,IACrF;AAAA,EACF;AAAA,EAEQ,mBAAmB,UAAkB,UAA0B;AACrE,UAAM,SAAS,KAAK,yBAAyB,IAAI,QAAQ;AACzD,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,sDAAsD,QAAQ,EAAE;AAAA,IAClF;AACA,YAAQ,IAAI,sBAAsB,UAAU,QAAQ;AAEpD,SAAK,0BAA0B,IAAI,QAAQ;AAE3C,WAAO,oBAAoB;AAAA,MACzB,GAAG,OAAO;AAAA,MACV,GAAG;AAAA,IACL;AAGA,UAAM,SAAS,yBAAyB,SAAS,QAAQ;AAEzD,UAAM,UAAU,MAAM,KAAK,OAAO,QAAQ,CAAC;AAC3C,SAAK,eAAe,mBAAmB,OAAO,oBAAoB,UAAU,OAAO;AAAA,EACrF;AAAA,EAEO,QAAQ,kBAAoD;AACjE,QAAI,KAAK,cAAc;AACrB,oBAAc,KAAK,YAAY;AAAA,IACjC;AAEA,QAAI,eAAkC;AACtC,QAAI,kBAAkB;AACpB,qBAAe,YAAY;AAAA,QACzB,MAAM;AAAA,QACN,WAAW,iBAAiB;AAAA,QAC5B,SAAS,iBAAiB;AAAA,QAC1B,WAAW,iBAAiB;AAAA,MAC9B,CAAC,EAAE,UAAU;AAAA,IACf;AAGA,eAAW,CAAC,EAAE,MAAM,KAAK,KAAK,0BAA0B;AACtD,UAAI,cAAc;AAChB,eAAO,OAAO,KAAK,YAAY;AAAA,MACjC;AACA,aAAO,OAAO,MAAM;AAAA,IACtB;AAEA,SAAK,yBAAyB,MAAM;AAAA,EACtC;AACF;;;AMtnBA;AAAA,EACE;AAAA,EACA;AAAA,EAEA;AAAA,OAGK;;;ACLA,IAAK,kBAAL,kBAAKE,qBAAL;AACL,EAAAA,kCAAA;AACA,EAAAA,kCAAA;AACA,EAAAA,kCAAA;AACA,EAAAA,kCAAA;AAJU,SAAAA;AAAA,GAAA;;;AD6CL,IAAM,uBAAN,MAA2B;AAAA,EAiBhC,YACU,QACR,kBACA,eACA;AAHQ;AAdV,SAAQ,SAAwB;AAChC,SAAQ,YAA2B;AACnC,SAAQ,YAAsB;AAAA,MAC5B,UAAU;AAAA,MACV,sBAAsB;AAAA,MACtB,QAAQ;AAAA,IACV;AAEA,SAAQ,mBAAwC,oBAAI,IAAI;AACxD,SAAQ,eAAsC,oBAAI,IAAI;AACtD,SAAQ,kBAAkB;AAQxB,SAAK,gBAAgB,iBAAiB;AAAA,MACpC,UAAU,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE;AAAA,MAC7B,UAAU,EAAE,aAAa,GAAG,aAAa,EAAE;AAAA,MAC3C,OAAO;AAAA,IACT;AACA,SAAK,YAAY,oBAAoB;AAAA,MACnC,UAAU;AAAA,MACV,sBAAsB;AAAA,MACtB,QAAQ;AAAA,IACV;AACA,SAAK,gBAAgB,IAAI,oBAAoB;AAG7C,SAAK,iBAAiB,IAAI;AAAA,MACxB,OAAO;AAAA,MACP,CAAC,QAAgB;AACf,cAAM,KAAK,OAAO,iBAAiB,GAAG;AACtC,eAAO;AAAA,MACT;AAAA,MACA,OAAO;AAAA,MACP;AAAA,QACE,YAAY;AAAA,QACZ,mBAAmB,CAAC,oBAA4D;AAC9E,gBAAM,EAAE,eAAe,IAAI,KAAK,cAAc,sBAAsB,eAAe;AAGnF,gBAAM,gBAAgB,KAAK,qBAAqB,CAAC,GAAG,gBAAgB,CAAC,CAAC;AACtE,eAAK,OAAO,SAAS,aAAa;AAGlC,cAAI,KAAK,cAAc,MAAM;AAC3B,kBAAM,UAAU,KAAK,cAAc,aAAa;AAChD,gBAAI,KAAK,YAAY,QAAQ,QAAQ;AACnC,oBAAM,WAAW,QAAQ,KAAK,SAAS;AACvC,oBAAM,SAAS,KAAK,iBAAiB,IAAI,QAAQ;AACjD,kBAAI,CAAC,QAAQ;AACX,sBAAM,IAAI,MAAM,gCAAgC,QAAQ,EAAE;AAAA,cAC5D;AACA,mBAAK,SAAS;AACd,mBAAK,kBAAkB;AACvB,mBAAK,OAAO,iBAAiB,KAAK,MAAM;AAAA,YAC1C,OAAO;AACL,sBAAQ;AAAA,gBACN,qBAAqB,KAAK,SAAS,qBAAqB,QAAQ,MAAM;AAAA,cACxE;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,QAAQ,CAAC,SAAsC;AAC7C,gBAAM,EAAE,cAAc,kBAAkB,eAAe,IACrD,KAAK,cAAc,WAAW,IAAI;AAEpC,gBAAM,gBAAgB,KAAK;AAAA,YACzB;AAAA,YACA;AAAA,YACA;AAAA,UACF;AACA,eAAK,OAAO,SAAS,aAAa;AAAA,QACpC;AAAA,QACA,aAAa,CAAC,cAAgD;AAE5D,eAAK,YAAY,UAAU;AAC3B,eAAK,cAAc,cAAc,UAAU,SAAS;AAEpD,kBAAQ;AAAA,YACN,uBAAuB,UAAU,SAAS;AAAA,UAC5C;AAAA,QACF;AAAA,QACA,SAAS,CAAC,WAAmB,cAAsB,cAAuB;AACxE,kBAAQ;AAAA,YACN;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AACA,eAAK,OAAO,cAAc;AAAA,YACxB,SAAS;AAAA,YACT;AAAA,UACF,CAAC;AAAA,QACH;AAAA,QACA,WAAW,CAAC,YAAoB;AAC9B,kBAAQ,KAAK,qBAAqB,OAAO;AAAA,QAC3C;AAAA,QACA,gBAAgB,CAAC,YAAoB,aAAqB;AA1JlE;AA4JU,2BAAK,QAAO,oBAAZ,4BAA8B,YAAY;AAAA,QAC5C;AAAA,MACF;AAAA,MACA;AAAA;AAAA,MACA,CAAC,WAA0C;AAEzC,YAAI;AACJ,gBAAQ,QAAQ;AAAA,UACd,KAAK,8BAA8B;AACjC;AACA;AAAA,UACF,KAAK,8BAA8B;AACjC,iBAAK,0BAA0B;AAC/B;AAEA;AAAA,UACF,KAAK,8BAA8B;AACjC;AACA,iBAAK,MAAM;AACX;AAAA,UACF,KAAK,8BAA8B;AACjC;AACA,iBAAK,MAAM;AACX;AAAA,UACF;AACE;AAAA,QACJ;AACA,aAAK,OAAO,qBAAqB,YAAY;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,QAAc;AACpB,SAAK,cAAc,MAAM;AACzB,SAAK,aAAa,MAAM;AACxB,SAAK,iBAAiB,MAAM;AAC5B,SAAK,kBAAkB;AACvB,SAAK,SAAS;AACd,SAAK,YAAY;AAAA,EACnB;AAAA,EAEQ,4BAAkC;AAExC,UAAM,aAAa,yBAAyB,aAAa,KAAK,aAAa;AAG3E,UAAM,SAAS,yBAAyB,SAAS,KAAK,SAAS;AAG/D,SAAK,eAAe,kBAAkB,YAAY,MAAM;AAAA,EAC1D;AAAA,EAEQ,qBACN,kBACA,qBACA,cACe;AACf,UAAM,eAAe,oBAAI,IAAuB;AAChD,UAAM,iBAAiB,oBAAI,IAAY;AAEvC,eAAW,YAAY,kBAAkB;AACvC,YAAM,SAAS,KAAK,iBAAiB,IAAI,QAAQ;AACjD,UAAI,QAAQ;AACV,uBAAe,IAAI,MAAM;AAGzB,aAAK,aAAa,OAAO,MAAM;AAG/B,aAAK,iBAAiB,OAAO,QAAQ;AAAA,MACvC,OAAO;AACL,cAAM,IAAI,MAAM,gCAAgC,QAAQ,EAAE;AAAA,MAC5D;AAAA,IACF;AAEA,eAAW,YAAY,qBAAqB;AAC1C,YAAM,iBAAiB,KAAK,cAAc,WAAW,IAAI,QAAQ;AACjE,UAAI,CAAC,gBAAgB;AACnB,cAAM,IAAI,MAAM,wCAAwC,QAAQ,EAAE;AAAA,MACpE;AACA,YAAM,cAAc,eAAe,OAAO,IAAI,4BAA4B;AAC1E,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI,MAAM,qCAAqC,QAAQ,EAAE;AAAA,MACjE;AACA,YAAM,SAAS,yBAAyB,gBAAgB,WAAW;AACnE,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI,MAAM,oDAAoD,QAAQ,EAAE;AAAA,MAChF;AACA,WAAK,iBAAiB,IAAI,UAAU,MAAM;AAC1C,YAAM,aAAa,yBAAyB,WAAW,eAAe,MAAM;AAC5E,WAAK,aAAa,IAAI,QAAQ,UAAU;AACxC,YAAM,eAAe,yBAAyB,eAAe,eAAe,UAAU;AACtF,mBAAa,IAAI,QAAQ;AAAA,QACvB,WAAW;AAAA,QACX,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAEA,UAAM,eAAe,oBAAI,IAAyB;AAElD,eAAW,CAAC,cAAc,QAAQ,KAAK,KAAK,cAAc,YAAY;AACpE,YAAM,SAAS,KAAK,iBAAiB,IAAI,YAAY;AACrD,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI,MAAM,oCAAoC,YAAY,EAAE;AAAA,MACpE;AACA,UAAI,CAAC,aAAa,IAAI,MAAM,GAAG;AAC7B,YAAI,SAAS,WAAW,OAAO,GAAG;AAChC,gBAAM,eAAe,yBAAyB,eAAe,SAAS,UAAU;AAChF,uBAAa,IAAI,QAAQ;AAAA,YACvB,YAAY;AAAA,UACd,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,eAAW,UAAU,cAAc;AAEjC,YAAM,eAAe,OAAO;AAE5B,YAAM,SAAS,KAAK,iBAAiB,IAAI,YAAY;AACrD,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI,MAAM,oCAAoC,YAAY,EAAE;AAAA,MACpE;AAEA,UAAI,aAAa,IAAI,MAAM,GAAG;AAC5B;AAAA,MACF;AAEA,YAAM,UAAU,KAAK,aAAa,IAAI,MAAM;AAC5C,UAAI,CAAC,SAAS;AACZ,gBAAQ,KAAK,6BAA6B,MAAM,mBAAmB;AACnE;AAAA,MACF;AACA,YAAM,iBAAiB,aAAa,IAAI,MAAM;AAC9C,UAAI,0BAAyD,eAAe;AAC5E,UAAI,CAAC,yBAAyB;AAC5B,kCAA0B,CAAC;AAC3B,uBAAe,YAAY;AAAA,MAC7B;AAEA,cAAQ,OAAO,SAAS;AAAA,QACtB,KAAK;AACH,kBAAQ,MAAM,yEAAyE;AACvF;AAAA,QACF,KAAK;AACH,gBAAM,WAAW,yBAAyB,kBAAkB,OAAO,KAAK;AACxE,cAAI,UAAU;AACZ,oBAAQ,WAAW;AACnB,oCAAwB,WAAW;AAAA,UACrC;AACA;AAAA,QACF,KAAK;AACH,gBAAM,uBAAuB,yBAAyB;AAAA,YACpD,OAAO;AAAA,UACT;AACA,kBAAQ,uBAAuB;AAC/B,kCAAwB,uBAAuB;AAC/C;AAAA,QACF,KAAK;AACH,gBAAM,SAAS,yBAAyB,aAAa,OAAO,KAAK;AACjE,kBAAQ,SAAS;AACjB,kCAAwB,SAAS;AACjC;AAAA,QACF;AACE,kBAAQ,KAAK,qBAAqB,OAAO,OAAO,EAAE;AAAA,MACtD;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEO,WAAW,QAA0C;AAC1D,QAAI,CAAC,KAAK,mBAAmB,KAAK,WAAW,MAAM;AAEjD,WAAK,gBAAgB;AACrB;AAAA,IACF;AAGA,UAAM,aAAa,yBAAyB,aAAa,MAAM;AAC/D,SAAK,eAAe,kBAAkB,YAAY,oBAAI,IAAI,CAAC;AAAA,EAC7D;AAAA,EAEO,kBAAkB,YAAoB,UAAwB;AACnE,QAAI,CAAC,KAAK,mBAAmB,KAAK,WAAW,MAAM;AACjD,cAAQ,KAAK,kDAAkD;AAC/D;AAAA,IACF;AAEA,SAAK,eAAe,kBAAkB,YAAY,QAAQ;AAAA,EAC5D;AAAA,EAEO,eAAe,UAAwB;AAC5C,QAAI,CAAC,KAAK,mBAAmB,KAAK,WAAW,MAAM;AACjD;AAAA,IACF;AAGA,SAAK,UAAU,WAAW;AAG1B,UAAM,SAAS,yBAAyB,gBAAgB,QAAQ;AAChE,SAAK,eAAe,kBAAkB,oBAAI,IAAI,GAAG,MAAM;AAAA,EACzD;AAAA,EAEO,2BAA2B,sBAAkD;AAClF,QAAI,CAAC,KAAK,mBAAmB,KAAK,WAAW,MAAM;AACjD;AAAA,IACF;AAGA,SAAK,UAAU,uBAAuB;AAGtC,UAAM,SAAS,yBAAyB,4BAA4B,oBAAoB;AACxF,SAAK,eAAe,kBAAkB,oBAAI,IAAI,GAAG,MAAM;AAAA,EACzD;AAAA,EAEO,aAAa,QAA+C;AACjE,QAAI,CAAC,KAAK,mBAAmB,KAAK,WAAW,MAAM;AACjD;AAAA,IACF;AAGA,SAAK,UAAU,SAAS;AAGxB,UAAM,SAAS,yBAAyB,cAAc,MAAM;AAC5D,SAAK,eAAe,kBAAkB,oBAAI,IAAI,GAAG,MAAM;AAAA,EACzD;AAAA,EAEO,OAAa;AAClB,SAAK,eAAe,KAAK;AACzB,SAAK,MAAM;AAAA,EACb;AACF;;;AEpYA;AAAA,EACE,2BAAAC;AAAA,EACA;AAAA,OACK;",
|
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
|
}
|