@mml-io/3d-web-experience-client 0.17.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,6 @@
1
+ import { AvatarConfiguration } from "@mml-io/3d-web-avatar-selection-ui";
1
2
  import { AnimationConfig, EnvironmentConfiguration } from "@mml-io/3d-web-client-core";
3
+ import { StringToHslOptions } from "@mml-io/3d-web-text-chat";
2
4
  type MMLDocumentConfiguration = {
3
5
  url: string;
4
6
  position?: {
@@ -18,24 +20,35 @@ type MMLDocumentConfiguration = {
18
20
  };
19
21
  };
20
22
  export type Networked3dWebExperienceClientConfig = {
21
- sessionToken: string;
22
- chatNetworkAddress?: string;
23
- voiceChatAddress?: string;
24
23
  userNetworkAddress: string;
25
- mmlDocuments?: Array<MMLDocumentConfiguration>;
24
+ sessionToken: string;
25
+ chatVisibleByDefault?: boolean;
26
+ userNameToColorOptions?: StringToHslOptions;
26
27
  animationConfig: AnimationConfig;
28
+ voiceChatAddress?: string;
29
+ updateURLLocation?: boolean;
30
+ onServerBroadcast?: (broadcast: {
31
+ broadcastType: string;
32
+ payload: any;
33
+ }) => void;
34
+ } & UpdatableConfig;
35
+ export type UpdatableConfig = {
36
+ chatNetworkAddress?: string | null;
37
+ mmlDocuments?: {
38
+ [key: string]: MMLDocumentConfiguration;
39
+ };
27
40
  environmentConfiguration?: EnvironmentConfiguration;
28
- skyboxHdrJpgUrl: string;
41
+ avatarConfiguration?: AvatarConfiguration;
29
42
  enableTweakPane?: boolean;
30
- updateURLLocation?: boolean;
31
43
  };
32
44
  export declare class Networked3dWebExperienceClient {
33
45
  private holderElement;
34
46
  private config;
35
47
  private element;
48
+ private canvasHolder;
36
49
  private scene;
37
50
  private composer;
38
- private tweakPane?;
51
+ private tweakPane;
39
52
  private audioListener;
40
53
  private cameraManager;
41
54
  private collisionsManager;
@@ -45,27 +58,43 @@ export declare class Networked3dWebExperienceClient {
45
58
  private keyInputManager;
46
59
  private virtualJoystick;
47
60
  private mmlCompositionScene;
61
+ private mmlFrames;
48
62
  private clientId;
49
63
  private networkClient;
50
64
  private remoteUserStates;
51
65
  private userProfiles;
52
66
  private networkChat;
53
67
  private textChatUI;
68
+ private avatarSelectionUI;
54
69
  private voiceChatManager;
55
70
  private readonly latestCharacterObject;
56
71
  private characterControllerPaneSet;
57
72
  private initialLoadCompleted;
58
73
  private loadingProgressManager;
59
74
  private loadingScreen;
75
+ private errorScreen?;
76
+ private currentRequestAnimationFrame;
77
+ private groundPlane;
60
78
  constructor(holderElement: HTMLElement, config: Networked3dWebExperienceClientConfig);
79
+ private setGroundPlaneEnabled;
80
+ updateConfig(config: Partial<UpdatableConfig>): void;
61
81
  static createFullscreenHolder(): HTMLDivElement;
62
82
  private resolveCharacterData;
63
83
  private updateUserProfile;
84
+ private updateUserAvatar;
64
85
  private sendChatMessageToServer;
86
+ private sendIdentityUpdateToServer;
65
87
  private connectToVoiceChat;
88
+ private setupTweakPane;
66
89
  private connectToTextChat;
90
+ private mountAvatarSelectionUI;
67
91
  update(): void;
68
92
  private spawnCharacter;
93
+ private disposeWithError;
94
+ dispose(): void;
69
95
  private setupMMLScene;
96
+ private createFrame;
97
+ private updateFrameAttributes;
98
+ private setMMLDocuments;
70
99
  }
71
100
  export {};
package/build/index.js CHANGED
@@ -1,4 +1,7 @@
1
1
  // src/Networked3dWebExperienceClient.ts
2
+ import {
3
+ AvatarSelectionUI
4
+ } from "@mml-io/3d-web-avatar-selection-ui";
2
5
  import {
3
6
  CameraManager,
4
7
  CharacterManager,
@@ -6,6 +9,7 @@ import {
6
9
  CollisionsManager,
7
10
  Composer,
8
11
  decodeCharacterAndCamera,
12
+ ErrorScreen,
9
13
  getSpawnPositionInsideCircle,
10
14
  GroundPlane,
11
15
  KeyInputManager,
@@ -15,8 +19,15 @@ import {
15
19
  TweakPane,
16
20
  VirtualJoystick
17
21
  } from "@mml-io/3d-web-client-core";
18
- import { ChatNetworkingClient, TextChatUI } from "@mml-io/3d-web-text-chat";
19
22
  import {
23
+ ChatNetworkingClient,
24
+ TextChatUI
25
+ } from "@mml-io/3d-web-text-chat";
26
+ import {
27
+ USER_NETWORKING_AUTHENTICATION_FAILED_ERROR_TYPE,
28
+ USER_NETWORKING_CONNECTION_LIMIT_REACHED_ERROR_TYPE,
29
+ USER_NETWORKING_SERVER_SHUTDOWN_ERROR_TYPE,
30
+ USER_NETWORKING_USER_UPDATE_MESSAGE_TYPE,
20
31
  UserNetworkingClient,
21
32
  WebsocketStatus
22
33
  } from "@mml-io/3d-web-user-networking";
@@ -24,6 +35,7 @@ import { VoiceChatManager } from "@mml-io/3d-web-voice-chat";
24
35
  import {
25
36
  LoadingProgressManager,
26
37
  registerCustomElementsToWindow,
38
+ setGlobalDocumentTimeManager,
27
39
  setGlobalMMLScene
28
40
  } from "mml-web";
29
41
  import { AudioListener, Euler, Scene, Vector3 } from "three";
@@ -32,16 +44,19 @@ var Networked3dWebExperienceClient = class {
32
44
  this.holderElement = holderElement;
33
45
  this.config = config;
34
46
  this.scene = new Scene();
47
+ this.tweakPane = null;
35
48
  this.audioListener = new AudioListener();
36
49
  this.collisionsManager = new CollisionsManager(this.scene);
37
50
  this.characterModelLoader = new CharacterModelLoader();
38
51
  this.timeManager = new TimeManager();
39
52
  this.keyInputManager = new KeyInputManager();
53
+ this.mmlFrames = {};
40
54
  this.clientId = null;
41
55
  this.remoteUserStates = /* @__PURE__ */ new Map();
42
56
  this.userProfiles = /* @__PURE__ */ new Map();
43
57
  this.networkChat = null;
44
58
  this.textChatUI = null;
59
+ this.avatarSelectionUI = null;
45
60
  this.voiceChatManager = null;
46
61
  this.latestCharacterObject = {
47
62
  characterState: null
@@ -49,6 +64,8 @@ var Networked3dWebExperienceClient = class {
49
64
  this.characterControllerPaneSet = false;
50
65
  this.initialLoadCompleted = false;
51
66
  this.loadingProgressManager = new LoadingProgressManager();
67
+ this.currentRequestAnimationFrame = null;
68
+ this.groundPlane = null;
52
69
  var _a;
53
70
  this.element = document.createElement("div");
54
71
  this.element.style.position = "absolute";
@@ -60,14 +77,17 @@ var Networked3dWebExperienceClient = class {
60
77
  this.audioListener.context.resume();
61
78
  }
62
79
  });
63
- this.cameraManager = new CameraManager(this.element, this.collisionsManager);
80
+ this.canvasHolder = document.createElement("div");
81
+ this.canvasHolder.style.position = "absolute";
82
+ this.canvasHolder.style.width = "100%";
83
+ this.canvasHolder.style.height = "100%";
84
+ this.element.appendChild(this.canvasHolder);
85
+ this.cameraManager = new CameraManager(this.canvasHolder, this.collisionsManager);
64
86
  this.cameraManager.camera.add(this.audioListener);
65
87
  this.virtualJoystick = new VirtualJoystick(this.element, {
66
88
  radius: 70,
67
- inner_radius: 20,
68
- x: 70,
69
- y: 0,
70
- mouse_support: false
89
+ innerRadius: 20,
90
+ mouseSupport: false
71
91
  });
72
92
  this.composer = new Composer({
73
93
  scene: this.scene,
@@ -75,17 +95,9 @@ var Networked3dWebExperienceClient = class {
75
95
  spawnSun: true,
76
96
  environmentConfiguration: this.config.environmentConfiguration
77
97
  });
78
- this.composer.useHDRJPG(this.config.skyboxHdrJpgUrl);
79
- this.element.appendChild(this.composer.renderer.domElement);
98
+ this.canvasHolder.appendChild(this.composer.renderer.domElement);
80
99
  if (this.config.enableTweakPane !== false) {
81
- this.tweakPane = new TweakPane(
82
- this.element,
83
- this.composer.renderer,
84
- this.scene,
85
- this.composer.effectComposer
86
- );
87
- this.cameraManager.setupTweakPane(this.tweakPane);
88
- this.composer.setupTweakPane(this.tweakPane);
100
+ this.setupTweakPane();
89
101
  }
90
102
  const resizeObserver = new ResizeObserver(() => {
91
103
  this.composer.fitContainer();
@@ -125,6 +137,26 @@ var Networked3dWebExperienceClient = class {
125
137
  username,
126
138
  characterDescription
127
139
  });
140
+ },
141
+ onServerError: (error) => {
142
+ switch (error.errorType) {
143
+ case USER_NETWORKING_AUTHENTICATION_FAILED_ERROR_TYPE:
144
+ this.disposeWithError(error.message);
145
+ break;
146
+ case USER_NETWORKING_CONNECTION_LIMIT_REACHED_ERROR_TYPE:
147
+ this.disposeWithError(error.message);
148
+ break;
149
+ case USER_NETWORKING_SERVER_SHUTDOWN_ERROR_TYPE:
150
+ this.disposeWithError(error.message || "Server shutdown");
151
+ break;
152
+ default:
153
+ console.error(`Unhandled server error: ${error.message}`);
154
+ this.disposeWithError(error.message);
155
+ }
156
+ },
157
+ onServerBroadcast: (broadcast) => {
158
+ var _a2, _b;
159
+ (_b = (_a2 = this.config).onServerBroadcast) == null ? void 0 : _b.call(_a2, broadcast);
128
160
  }
129
161
  });
130
162
  this.characterManager = new CharacterManager({
@@ -147,25 +179,68 @@ var Networked3dWebExperienceClient = class {
147
179
  updateURLLocation: this.config.updateURLLocation !== false
148
180
  });
149
181
  this.scene.add(this.characterManager.group);
150
- if (((_a = this.config.environmentConfiguration) == null ? void 0 : _a.groundPlane) !== false) {
151
- const groundPlane = new GroundPlane();
152
- this.collisionsManager.addMeshesGroup(groundPlane);
153
- this.scene.add(groundPlane);
154
- }
182
+ this.setGroundPlaneEnabled(((_a = this.config.environmentConfiguration) == null ? void 0 : _a.groundPlane) ?? true);
155
183
  this.setupMMLScene();
156
184
  this.loadingScreen = new LoadingScreen(this.loadingProgressManager);
157
- document.body.append(this.loadingScreen.element);
185
+ this.element.append(this.loadingScreen.element);
158
186
  this.loadingProgressManager.addProgressCallback(() => {
159
187
  const [, completed] = this.loadingProgressManager.toRatio();
160
188
  if (completed && !this.initialLoadCompleted) {
161
189
  this.initialLoadCompleted = true;
162
190
  this.connectToVoiceChat();
163
191
  this.connectToTextChat();
192
+ this.mountAvatarSelectionUI();
164
193
  this.spawnCharacter();
165
194
  }
166
195
  });
167
196
  this.loadingProgressManager.setInitialLoad(true);
168
197
  }
198
+ setGroundPlaneEnabled(enabled) {
199
+ if (enabled && this.groundPlane === null) {
200
+ this.groundPlane = new GroundPlane();
201
+ this.collisionsManager.addMeshesGroup(this.groundPlane);
202
+ this.scene.add(this.groundPlane);
203
+ } else if (!enabled && this.groundPlane !== null) {
204
+ this.collisionsManager.removeMeshesGroup(this.groundPlane);
205
+ this.scene.remove(this.groundPlane);
206
+ this.groundPlane = null;
207
+ }
208
+ }
209
+ updateConfig(config) {
210
+ var _a, _b;
211
+ this.config = {
212
+ ...this.config,
213
+ ...config
214
+ };
215
+ if (config.environmentConfiguration) {
216
+ this.composer.updateEnvironmentConfiguration(config.environmentConfiguration);
217
+ this.setGroundPlaneEnabled(config.environmentConfiguration.groundPlane ?? true);
218
+ }
219
+ if (config.avatarConfiguration && this.avatarSelectionUI) {
220
+ (_a = this.avatarSelectionUI) == null ? void 0 : _a.updateAvatarConfig(config.avatarConfiguration);
221
+ }
222
+ if (config.enableTweakPane !== void 0) {
223
+ if (config.enableTweakPane === false && this.tweakPane !== null) {
224
+ this.tweakPane.dispose();
225
+ this.tweakPane = null;
226
+ } else if (config.enableTweakPane === true && this.tweakPane === null) {
227
+ this.setupTweakPane();
228
+ }
229
+ }
230
+ if (config.chatNetworkAddress !== void 0) {
231
+ if (config.chatNetworkAddress === null && this.networkChat !== null) {
232
+ this.networkChat.stop();
233
+ this.networkChat = null;
234
+ (_b = this.textChatUI) == null ? void 0 : _b.dispose();
235
+ this.textChatUI = null;
236
+ } else {
237
+ this.connectToTextChat();
238
+ }
239
+ }
240
+ if (config.mmlDocuments) {
241
+ this.setMMLDocuments(config.mmlDocuments);
242
+ }
243
+ }
169
244
  static createFullscreenHolder() {
170
245
  document.body.style.margin = "0";
171
246
  document.body.style.overflow = "hidden";
@@ -192,12 +267,51 @@ var Networked3dWebExperienceClient = class {
192
267
  this.userProfiles.set(id, userData);
193
268
  this.characterManager.respawnIfPresent(id);
194
269
  }
270
+ updateUserAvatar(avatar) {
271
+ if (this.clientId === null) {
272
+ throw new Error("Client ID not set");
273
+ }
274
+ const user = this.userProfiles.get(this.clientId);
275
+ if (!user) {
276
+ throw new Error("User not found");
277
+ }
278
+ const newUser = {
279
+ ...user,
280
+ characterDescription: {
281
+ meshFileUrl: avatar.meshFileUrl ?? void 0,
282
+ mmlCharacterUrl: avatar.mmlCharacterUrl ?? void 0,
283
+ mmlCharacterString: avatar.mmlCharacterString ?? void 0
284
+ }
285
+ };
286
+ this.userProfiles.set(this.clientId, newUser);
287
+ this.updateUserProfile(this.clientId, newUser);
288
+ }
195
289
  sendChatMessageToServer(message) {
196
290
  this.mmlCompositionScene.onChatMessage(message);
197
291
  if (this.clientId === null || this.networkChat === null)
198
292
  return;
199
293
  this.networkChat.sendChatMessage(message);
200
294
  }
295
+ sendIdentityUpdateToServer(avatar) {
296
+ if (!this.clientId) {
297
+ throw new Error("Client ID not set");
298
+ }
299
+ const userProfile = this.userProfiles.get(this.clientId);
300
+ if (!userProfile) {
301
+ throw new Error("User profile not found");
302
+ }
303
+ this.networkClient.sendMessage({
304
+ type: USER_NETWORKING_USER_UPDATE_MESSAGE_TYPE,
305
+ userIdentity: {
306
+ username: userProfile.username,
307
+ characterDescription: {
308
+ mmlCharacterString: avatar.mmlCharacterString,
309
+ mmlCharacterUrl: avatar.mmlCharacterUrl,
310
+ meshFileUrl: avatar.meshFileUrl
311
+ }
312
+ }
313
+ });
314
+ }
201
315
  connectToVoiceChat() {
202
316
  if (this.clientId === null)
203
317
  return;
@@ -212,6 +326,19 @@ var Networked3dWebExperienceClient = class {
212
326
  });
213
327
  }
214
328
  }
329
+ setupTweakPane() {
330
+ if (this.tweakPane) {
331
+ return;
332
+ }
333
+ this.tweakPane = new TweakPane(
334
+ this.element,
335
+ this.composer.renderer,
336
+ this.scene,
337
+ this.composer.effectComposer
338
+ );
339
+ this.cameraManager.setupTweakPane(this.tweakPane);
340
+ this.composer.setupTweakPane(this.tweakPane);
341
+ }
215
342
  connectToTextChat() {
216
343
  if (this.clientId === null) {
217
344
  return;
@@ -222,17 +349,20 @@ var Networked3dWebExperienceClient = class {
222
349
  throw new Error("User not found");
223
350
  }
224
351
  if (this.textChatUI === null) {
225
- this.textChatUI = new TextChatUI(
226
- this.element,
227
- user.username,
228
- this.sendChatMessageToServer.bind(this)
229
- );
352
+ const textChatUISettings = {
353
+ holderElement: this.element,
354
+ clientname: user.username,
355
+ sendMessageToServerMethod: this.sendChatMessageToServer.bind(this),
356
+ visibleByDefault: this.config.chatVisibleByDefault,
357
+ stringToHslOptions: this.config.userNameToColorOptions
358
+ };
359
+ this.textChatUI = new TextChatUI(textChatUISettings);
230
360
  this.textChatUI.init();
231
361
  }
232
362
  this.networkChat = new ChatNetworkingClient({
233
363
  url: this.config.chatNetworkAddress,
234
364
  sessionToken: this.config.sessionToken,
235
- websocketFactory: (url) => new WebSocket(`${url}?id=${this.clientId}`),
365
+ websocketFactory: (url) => new WebSocket(url),
236
366
  statusUpdateCallback: (status) => {
237
367
  if (status === WebsocketStatus.Disconnected || status === WebsocketStatus.Reconnecting) {
238
368
  }
@@ -243,10 +373,25 @@ var Networked3dWebExperienceClient = class {
243
373
  const username = ((_a = this.userProfiles.get(clientId)) == null ? void 0 : _a.username) || "Unknown";
244
374
  this.textChatUI.addTextMessage(username, chatNetworkingUpdate.text);
245
375
  }
376
+ },
377
+ onServerError: (error) => {
378
+ console.error(`Chat server error: ${error.message}. errorType: ${error.errorType}`);
379
+ this.disposeWithError(error.message);
246
380
  }
247
381
  });
248
382
  }
249
383
  }
384
+ mountAvatarSelectionUI() {
385
+ var _a, _b;
386
+ this.avatarSelectionUI = new AvatarSelectionUI({
387
+ holderElement: this.element,
388
+ visibleByDefault: false,
389
+ sendMessageToServerMethod: this.sendIdentityUpdateToServer.bind(this),
390
+ availableAvatars: ((_a = this.config.avatarConfiguration) == null ? void 0 : _a.availableAvatars) ?? [],
391
+ allowCustomAvatars: (_b = this.config.avatarConfiguration) == null ? void 0 : _b.allowCustomAvatars
392
+ });
393
+ this.avatarSelectionUI.init();
394
+ }
250
395
  update() {
251
396
  var _a, _b, _c, _d;
252
397
  this.timeManager.update();
@@ -269,7 +414,7 @@ var Networked3dWebExperienceClient = class {
269
414
  }
270
415
  }
271
416
  }
272
- requestAnimationFrame(() => {
417
+ this.currentRequestAnimationFrame = requestAnimationFrame(() => {
273
418
  this.update();
274
419
  });
275
420
  }
@@ -305,6 +450,31 @@ var Networked3dWebExperienceClient = class {
305
450
  this.cameraManager.reverseUpdateFromPositions();
306
451
  }
307
452
  }
453
+ disposeWithError(message) {
454
+ this.dispose();
455
+ this.errorScreen = new ErrorScreen("An error occurred", message);
456
+ this.element.append(this.errorScreen.element);
457
+ }
458
+ dispose() {
459
+ var _a, _b, _c, _d;
460
+ this.networkClient.stop();
461
+ (_a = this.networkChat) == null ? void 0 : _a.stop();
462
+ for (const [key, element] of Object.entries(this.mmlFrames)) {
463
+ element.remove();
464
+ }
465
+ this.mmlFrames = {};
466
+ (_b = this.textChatUI) == null ? void 0 : _b.dispose();
467
+ this.mmlCompositionScene.dispose();
468
+ this.composer.dispose();
469
+ (_c = this.tweakPane) == null ? void 0 : _c.dispose();
470
+ if (this.currentRequestAnimationFrame !== null) {
471
+ cancelAnimationFrame(this.currentRequestAnimationFrame);
472
+ this.currentRequestAnimationFrame = null;
473
+ }
474
+ this.cameraManager.dispose();
475
+ this.loadingScreen.dispose();
476
+ (_d = this.errorScreen) == null ? void 0 : _d.dispose();
477
+ }
308
478
  setupMMLScene() {
309
479
  registerCustomElementsToWindow(window);
310
480
  this.mmlCompositionScene = new MMLCompositionScene({
@@ -320,34 +490,8 @@ var Networked3dWebExperienceClient = class {
320
490
  });
321
491
  this.scene.add(this.mmlCompositionScene.group);
322
492
  setGlobalMMLScene(this.mmlCompositionScene.mmlScene);
323
- if (this.config.mmlDocuments) {
324
- for (const mmlDocument of this.config.mmlDocuments) {
325
- const frameElement = document.createElement("m-frame");
326
- frameElement.setAttribute("src", mmlDocument.url);
327
- if (mmlDocument.position) {
328
- frameElement.setAttribute("x", mmlDocument.position.x.toString());
329
- frameElement.setAttribute("y", mmlDocument.position.y.toString());
330
- frameElement.setAttribute("z", mmlDocument.position.z.toString());
331
- }
332
- if (mmlDocument.rotation) {
333
- frameElement.setAttribute("rx", mmlDocument.rotation.x.toString());
334
- frameElement.setAttribute("ry", mmlDocument.rotation.y.toString());
335
- frameElement.setAttribute("rz", mmlDocument.rotation.z.toString());
336
- }
337
- if (mmlDocument.scale) {
338
- if (mmlDocument.scale.x !== void 0) {
339
- frameElement.setAttribute("sx", mmlDocument.scale.x.toString());
340
- }
341
- if (mmlDocument.scale.y !== void 0) {
342
- frameElement.setAttribute("sy", mmlDocument.scale.y.toString());
343
- }
344
- if (mmlDocument.scale.z !== void 0) {
345
- frameElement.setAttribute("sz", mmlDocument.scale.z.toString());
346
- }
347
- }
348
- document.body.appendChild(frameElement);
349
- }
350
- }
493
+ setGlobalDocumentTimeManager(this.mmlCompositionScene.documentTimeManager);
494
+ this.setMMLDocuments(this.config.mmlDocuments ?? {});
351
495
  const mmlProgressManager = this.mmlCompositionScene.mmlScene.getLoadingProgressManager();
352
496
  this.loadingProgressManager.addLoadingDocument(mmlProgressManager, "mml", mmlProgressManager);
353
497
  mmlProgressManager.addProgressCallback(() => {
@@ -355,6 +499,71 @@ var Networked3dWebExperienceClient = class {
355
499
  });
356
500
  mmlProgressManager.setInitialLoad(true);
357
501
  }
502
+ createFrame(mmlDocument) {
503
+ const frameElement = document.createElement("m-frame");
504
+ frameElement.setAttribute("src", mmlDocument.url);
505
+ this.updateFrameAttributes(frameElement, mmlDocument);
506
+ return frameElement;
507
+ }
508
+ updateFrameAttributes(frameElement, mmlDocument) {
509
+ var _a, _b, _c;
510
+ const existingSrc = frameElement.getAttribute("src");
511
+ if (existingSrc !== mmlDocument.url) {
512
+ frameElement.setAttribute("src", mmlDocument.url);
513
+ }
514
+ if (mmlDocument.position) {
515
+ frameElement.setAttribute("x", mmlDocument.position.x.toString());
516
+ frameElement.setAttribute("y", mmlDocument.position.y.toString());
517
+ frameElement.setAttribute("z", mmlDocument.position.z.toString());
518
+ } else {
519
+ frameElement.setAttribute("x", "0");
520
+ frameElement.setAttribute("y", "0");
521
+ frameElement.setAttribute("z", "0");
522
+ }
523
+ if (mmlDocument.rotation) {
524
+ frameElement.setAttribute("rx", mmlDocument.rotation.x.toString());
525
+ frameElement.setAttribute("ry", mmlDocument.rotation.y.toString());
526
+ frameElement.setAttribute("rz", mmlDocument.rotation.z.toString());
527
+ } else {
528
+ frameElement.setAttribute("rx", "0");
529
+ frameElement.setAttribute("ry", "0");
530
+ frameElement.setAttribute("rz", "0");
531
+ }
532
+ if (((_a = mmlDocument.scale) == null ? void 0 : _a.x) !== void 0) {
533
+ frameElement.setAttribute("sx", mmlDocument.scale.x.toString());
534
+ } else {
535
+ frameElement.setAttribute("sx", "1");
536
+ }
537
+ if (((_b = mmlDocument.scale) == null ? void 0 : _b.y) !== void 0) {
538
+ frameElement.setAttribute("sy", mmlDocument.scale.y.toString());
539
+ } else {
540
+ frameElement.setAttribute("sy", "1");
541
+ }
542
+ if (((_c = mmlDocument.scale) == null ? void 0 : _c.z) !== void 0) {
543
+ frameElement.setAttribute("sz", mmlDocument.scale.z.toString());
544
+ } else {
545
+ frameElement.setAttribute("sz", "1");
546
+ }
547
+ }
548
+ setMMLDocuments(mmlDocuments) {
549
+ const newFramesMap = {};
550
+ for (const [key, mmlDocSpec] of Object.entries(mmlDocuments)) {
551
+ const existing = this.mmlFrames[key];
552
+ if (!existing) {
553
+ const frameElement = this.createFrame(mmlDocSpec);
554
+ document.body.appendChild(frameElement);
555
+ newFramesMap[key] = frameElement;
556
+ } else {
557
+ delete this.mmlFrames[key];
558
+ newFramesMap[key] = existing;
559
+ this.updateFrameAttributes(existing, mmlDocSpec);
560
+ }
561
+ }
562
+ for (const [key, element] of Object.entries(this.mmlFrames)) {
563
+ element.remove();
564
+ }
565
+ this.mmlFrames = newFramesMap;
566
+ }
358
567
  };
359
568
  export {
360
569
  Networked3dWebExperienceClient
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/Networked3dWebExperienceClient.ts"],
4
- "sourcesContent": ["import {\n AnimationConfig,\n CameraManager,\n CharacterDescription,\n CharacterManager,\n CharacterModelLoader,\n CharacterState,\n CollisionsManager,\n Composer,\n decodeCharacterAndCamera,\n EnvironmentConfiguration,\n getSpawnPositionInsideCircle,\n GroundPlane,\n KeyInputManager,\n LoadingScreen,\n MMLCompositionScene,\n TimeManager,\n TweakPane,\n VirtualJoystick,\n} from \"@mml-io/3d-web-client-core\";\nimport { ChatNetworkingClient, FromClientChatMessage, TextChatUI } from \"@mml-io/3d-web-text-chat\";\nimport {\n UserData,\n UserNetworkingClient,\n UserNetworkingClientUpdate,\n WebsocketStatus,\n} from \"@mml-io/3d-web-user-networking\";\nimport { VoiceChatManager } from \"@mml-io/3d-web-voice-chat\";\nimport {\n IMMLScene,\n LoadingProgressManager,\n registerCustomElementsToWindow,\n setGlobalMMLScene,\n} from \"mml-web\";\nimport { AudioListener, Euler, Scene, Vector3 } from \"three\";\n\ntype MMLDocumentConfiguration = {\n url: string;\n position?: {\n x: number;\n y: number;\n z: number;\n };\n rotation?: {\n x: number;\n y: number;\n z: number;\n };\n scale?: {\n x: number;\n y: number;\n z: number;\n };\n};\n\nexport type Networked3dWebExperienceClientConfig = {\n sessionToken: string;\n chatNetworkAddress?: string;\n voiceChatAddress?: string;\n userNetworkAddress: string;\n mmlDocuments?: Array<MMLDocumentConfiguration>;\n animationConfig: AnimationConfig;\n environmentConfiguration?: EnvironmentConfiguration;\n skyboxHdrJpgUrl: string;\n enableTweakPane?: boolean;\n updateURLLocation?: boolean;\n};\n\nexport class Networked3dWebExperienceClient {\n private element: HTMLDivElement;\n\n private scene = new Scene();\n private composer: Composer;\n private tweakPane?: TweakPane;\n private audioListener = new AudioListener();\n\n private cameraManager: CameraManager;\n\n private collisionsManager = new CollisionsManager(this.scene);\n\n private characterModelLoader = new CharacterModelLoader();\n private characterManager: CharacterManager;\n\n private timeManager = new TimeManager();\n\n private keyInputManager = new KeyInputManager();\n private virtualJoystick: VirtualJoystick;\n\n private mmlCompositionScene: MMLCompositionScene;\n\n private clientId: number | null = null;\n private networkClient: UserNetworkingClient;\n private remoteUserStates = new Map<number, CharacterState>();\n private userProfiles = new Map<number, UserData>();\n\n private networkChat: ChatNetworkingClient | null = null;\n private textChatUI: TextChatUI | null = null;\n\n private voiceChatManager: VoiceChatManager | null = null;\n private readonly latestCharacterObject = {\n characterState: null as null | CharacterState,\n };\n private characterControllerPaneSet: boolean = false;\n\n private initialLoadCompleted = false;\n private loadingProgressManager = new LoadingProgressManager();\n private loadingScreen: LoadingScreen;\n\n constructor(\n private holderElement: HTMLElement,\n private config: Networked3dWebExperienceClientConfig,\n ) {\n this.element = document.createElement(\"div\");\n this.element.style.position = \"absolute\";\n this.element.style.width = \"100%\";\n this.element.style.height = \"100%\";\n this.holderElement.appendChild(this.element);\n\n document.addEventListener(\"mousedown\", () => {\n if (this.audioListener.context.state === \"suspended\") {\n this.audioListener.context.resume();\n }\n });\n\n this.cameraManager = new CameraManager(this.element, this.collisionsManager);\n this.cameraManager.camera.add(this.audioListener);\n\n this.virtualJoystick = new VirtualJoystick(this.element, {\n radius: 70,\n inner_radius: 20,\n x: 70,\n y: 0,\n mouse_support: false,\n });\n\n this.composer = new Composer({\n scene: this.scene,\n camera: this.cameraManager.camera,\n spawnSun: true,\n environmentConfiguration: this.config.environmentConfiguration,\n });\n\n this.composer.useHDRJPG(this.config.skyboxHdrJpgUrl);\n this.element.appendChild(this.composer.renderer.domElement);\n\n if (this.config.enableTweakPane !== false) {\n this.tweakPane = new TweakPane(\n this.element,\n this.composer.renderer,\n this.scene,\n this.composer.effectComposer,\n );\n this.cameraManager.setupTweakPane(this.tweakPane);\n this.composer.setupTweakPane(this.tweakPane);\n }\n\n const resizeObserver = new ResizeObserver(() => {\n this.composer.fitContainer();\n });\n resizeObserver.observe(this.element);\n\n const initialNetworkLoadRef = {};\n this.loadingProgressManager.addLoadingAsset(initialNetworkLoadRef, \"network\", \"network\");\n this.networkClient = new UserNetworkingClient({\n url: this.config.userNetworkAddress,\n sessionToken: this.config.sessionToken,\n websocketFactory: (url: string) => new WebSocket(url),\n statusUpdateCallback: (status: WebsocketStatus) => {\n if (status === WebsocketStatus.Disconnected || status === WebsocketStatus.Reconnecting) {\n // The connection was lost after being established - the connection may be re-established with a different client ID\n this.characterManager.clear();\n this.remoteUserStates.clear();\n this.clientId = null;\n }\n },\n assignedIdentity: (clientId: number) => {\n console.log(`Assigned ID: ${clientId}`);\n this.clientId = clientId;\n if (this.initialLoadCompleted) {\n // Already loaded - respawn the character\n this.spawnCharacter();\n } else {\n this.loadingProgressManager.completedLoadingAsset(initialNetworkLoadRef);\n }\n },\n clientUpdate: (\n remoteClientId: number,\n userNetworkingClientUpdate: null | UserNetworkingClientUpdate,\n ) => {\n if (userNetworkingClientUpdate === null) {\n this.remoteUserStates.delete(remoteClientId);\n } else {\n this.remoteUserStates.set(remoteClientId, userNetworkingClientUpdate);\n }\n },\n clientProfileUpdated: (\n clientId: number,\n username: string,\n characterDescription: CharacterDescription,\n ): void => {\n this.updateUserProfile(clientId, {\n username,\n characterDescription,\n });\n },\n });\n\n this.characterManager = new CharacterManager({\n composer: this.composer,\n characterModelLoader: this.characterModelLoader,\n collisionsManager: this.collisionsManager,\n cameraManager: this.cameraManager,\n timeManager: this.timeManager,\n keyInputManager: this.keyInputManager,\n virtualJoystick: this.virtualJoystick,\n remoteUserStates: this.remoteUserStates,\n sendUpdate: (characterState: CharacterState) => {\n this.latestCharacterObject.characterState = characterState;\n this.networkClient.sendUpdate(characterState);\n },\n animationConfig: this.config.animationConfig,\n characterResolve: (characterId: number) => {\n return this.resolveCharacterData(characterId);\n },\n updateURLLocation: this.config.updateURLLocation !== false,\n });\n this.scene.add(this.characterManager.group);\n\n if (this.config.environmentConfiguration?.groundPlane !== false) {\n const groundPlane = new GroundPlane();\n this.collisionsManager.addMeshesGroup(groundPlane);\n this.scene.add(groundPlane);\n }\n\n this.setupMMLScene();\n\n this.loadingScreen = new LoadingScreen(this.loadingProgressManager);\n document.body.append(this.loadingScreen.element);\n\n this.loadingProgressManager.addProgressCallback(() => {\n const [, completed] = this.loadingProgressManager.toRatio();\n if (completed && !this.initialLoadCompleted) {\n this.initialLoadCompleted = true;\n /*\n When all content (in particular MML) has loaded, spawn the character (this is to avoid the character falling\n through as-yet-unloaded geometry)\n */\n this.connectToVoiceChat();\n this.connectToTextChat();\n this.spawnCharacter();\n }\n });\n this.loadingProgressManager.setInitialLoad(true);\n }\n\n static createFullscreenHolder(): HTMLDivElement {\n document.body.style.margin = \"0\";\n document.body.style.overflow = \"hidden\";\n\n const holder = document.createElement(\"div\");\n holder.style.position = \"absolute\";\n holder.style.width = \"100%\";\n holder.style.height = \"100%\";\n holder.style.overflow = \"hidden\";\n document.body.appendChild(holder);\n return holder;\n }\n\n private resolveCharacterData(clientId: number): {\n username: string;\n characterDescription: CharacterDescription;\n } {\n const user = this.userProfiles.get(clientId)!;\n if (!user) {\n throw new Error(`Failed to resolve user for clientId ${clientId}`);\n }\n\n return {\n username: user.username,\n characterDescription: user.characterDescription,\n };\n }\n\n private updateUserProfile(id: number, userData: UserData) {\n console.log(`Update user_profile for id=${id} (username=${userData.username})`);\n\n this.userProfiles.set(id, userData);\n\n this.characterManager.respawnIfPresent(id);\n }\n\n private sendChatMessageToServer(message: string): void {\n this.mmlCompositionScene.onChatMessage(message);\n if (this.clientId === null || this.networkChat === null) return;\n this.networkChat.sendChatMessage(message);\n }\n\n private connectToVoiceChat() {\n if (this.clientId === null) return;\n\n if (this.voiceChatManager === null && this.config.voiceChatAddress) {\n this.voiceChatManager = new VoiceChatManager({\n url: this.config.voiceChatAddress,\n holderElement: this.element,\n userId: this.clientId,\n remoteUserStates: this.remoteUserStates,\n latestCharacterObj: this.latestCharacterObject,\n autoJoin: false,\n });\n }\n }\n\n private connectToTextChat() {\n if (this.clientId === null) {\n return;\n }\n if (this.networkChat === null && this.config.chatNetworkAddress) {\n const user = this.userProfiles.get(this.clientId);\n if (!user) {\n throw new Error(\"User not found\");\n }\n\n if (this.textChatUI === null) {\n this.textChatUI = new TextChatUI(\n this.element,\n user.username,\n this.sendChatMessageToServer.bind(this),\n );\n this.textChatUI.init();\n }\n\n this.networkChat = new ChatNetworkingClient({\n url: this.config.chatNetworkAddress,\n sessionToken: this.config.sessionToken,\n websocketFactory: (url: string) => new WebSocket(`${url}?id=${this.clientId}`),\n statusUpdateCallback: (status: WebsocketStatus) => {\n if (status === WebsocketStatus.Disconnected || status === WebsocketStatus.Reconnecting) {\n // The connection was lost after being established - the connection may be re-established with a different client ID\n }\n },\n clientChatUpdate: (\n clientId: number,\n chatNetworkingUpdate: null | FromClientChatMessage,\n ) => {\n if (chatNetworkingUpdate !== null && this.textChatUI !== null) {\n const username = this.userProfiles.get(clientId)?.username || \"Unknown\";\n this.textChatUI.addTextMessage(username, chatNetworkingUpdate.text);\n }\n },\n });\n }\n }\n\n public update(): void {\n this.timeManager.update();\n this.characterManager.update();\n this.voiceChatManager?.speakingParticipants.forEach((value: boolean, id: number) => {\n this.characterManager.setSpeakingCharacter(id, value);\n });\n this.cameraManager.update();\n this.composer.sun?.updateCharacterPosition(this.characterManager.localCharacter?.position);\n this.composer.render(this.timeManager);\n if (this.tweakPane?.guiVisible) {\n this.tweakPane.updateStats(this.timeManager);\n this.tweakPane.updateCameraData(this.cameraManager);\n if (this.characterManager.localCharacter && this.characterManager.localController) {\n if (!this.characterControllerPaneSet) {\n this.characterControllerPaneSet = true;\n this.characterManager.setupTweakPane(this.tweakPane);\n } else {\n this.tweakPane.updateCharacterData(this.characterManager.localController);\n }\n }\n }\n requestAnimationFrame(() => {\n this.update();\n });\n }\n\n private spawnCharacter() {\n if (this.clientId === null) {\n throw new Error(\"Client ID not set\");\n }\n const spawnPosition = getSpawnPositionInsideCircle(3, 30, this.clientId!, 0.4);\n const spawnRotation = new Euler(0, 0, 0);\n let cameraPosition: Vector3 | null = null;\n if (window.location.hash && window.location.hash.length > 1) {\n const urlParams = decodeCharacterAndCamera(window.location.hash.substring(1));\n spawnPosition.copy(urlParams.character.position);\n spawnRotation.setFromQuaternion(urlParams.character.quaternion);\n cameraPosition = urlParams.camera.position;\n }\n const ownIdentity = this.userProfiles.get(this.clientId);\n if (!ownIdentity) {\n throw new Error(\"Own identity not found\");\n }\n\n this.characterManager.spawnLocalCharacter(\n this.clientId!,\n ownIdentity.username,\n ownIdentity.characterDescription,\n spawnPosition,\n spawnRotation,\n );\n if (cameraPosition !== null) {\n this.cameraManager.camera.position.copy(cameraPosition);\n this.cameraManager.setTarget(\n new Vector3().add(spawnPosition).add(this.characterManager.headTargetOffset),\n );\n this.cameraManager.reverseUpdateFromPositions();\n }\n }\n\n private setupMMLScene() {\n registerCustomElementsToWindow(window);\n this.mmlCompositionScene = new MMLCompositionScene({\n targetElement: this.element,\n renderer: this.composer.renderer,\n scene: this.scene,\n camera: this.cameraManager.camera,\n audioListener: this.audioListener,\n collisionsManager: this.collisionsManager,\n getUserPositionAndRotation: () => {\n return this.characterManager.getLocalCharacterPositionAndRotation();\n },\n });\n this.scene.add(this.mmlCompositionScene.group);\n setGlobalMMLScene(this.mmlCompositionScene.mmlScene as IMMLScene);\n\n if (this.config.mmlDocuments) {\n for (const mmlDocument of this.config.mmlDocuments) {\n const frameElement = document.createElement(\"m-frame\");\n frameElement.setAttribute(\"src\", mmlDocument.url);\n if (mmlDocument.position) {\n frameElement.setAttribute(\"x\", mmlDocument.position.x.toString());\n frameElement.setAttribute(\"y\", mmlDocument.position.y.toString());\n frameElement.setAttribute(\"z\", mmlDocument.position.z.toString());\n }\n if (mmlDocument.rotation) {\n frameElement.setAttribute(\"rx\", mmlDocument.rotation.x.toString());\n frameElement.setAttribute(\"ry\", mmlDocument.rotation.y.toString());\n frameElement.setAttribute(\"rz\", mmlDocument.rotation.z.toString());\n }\n if (mmlDocument.scale) {\n if (mmlDocument.scale.x !== undefined) {\n frameElement.setAttribute(\"sx\", mmlDocument.scale.x.toString());\n }\n if (mmlDocument.scale.y !== undefined) {\n frameElement.setAttribute(\"sy\", mmlDocument.scale.y.toString());\n }\n if (mmlDocument.scale.z !== undefined) {\n frameElement.setAttribute(\"sz\", mmlDocument.scale.z.toString());\n }\n }\n document.body.appendChild(frameElement);\n }\n }\n\n const mmlProgressManager = this.mmlCompositionScene.mmlScene.getLoadingProgressManager!()!;\n this.loadingProgressManager.addLoadingDocument(mmlProgressManager, \"mml\", mmlProgressManager);\n mmlProgressManager.addProgressCallback(() => {\n this.loadingProgressManager.updateDocumentProgress(mmlProgressManager);\n });\n mmlProgressManager.setInitialLoad(true);\n }\n}\n"],
5
- "mappings": "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",
6
- "names": []
4
+ "sourcesContent": ["import {\n AvatarSelectionUI,\n AvatarType,\n AvatarConfiguration,\n} from \"@mml-io/3d-web-avatar-selection-ui\";\nimport {\n AnimationConfig,\n CameraManager,\n CharacterDescription,\n CharacterManager,\n CharacterModelLoader,\n CharacterState,\n CollisionsManager,\n Composer,\n decodeCharacterAndCamera,\n EnvironmentConfiguration,\n ErrorScreen,\n getSpawnPositionInsideCircle,\n GroundPlane,\n KeyInputManager,\n LoadingScreen,\n MMLCompositionScene,\n TimeManager,\n TweakPane,\n VirtualJoystick,\n} from \"@mml-io/3d-web-client-core\";\nimport {\n ChatNetworkingClient,\n ChatNetworkingClientChatMessage,\n ChatNetworkingServerErrorType,\n StringToHslOptions,\n TextChatUI,\n TextChatUIProps,\n} from \"@mml-io/3d-web-text-chat\";\nimport {\n USER_NETWORKING_AUTHENTICATION_FAILED_ERROR_TYPE,\n USER_NETWORKING_CONNECTION_LIMIT_REACHED_ERROR_TYPE,\n USER_NETWORKING_SERVER_SHUTDOWN_ERROR_TYPE,\n USER_NETWORKING_USER_UPDATE_MESSAGE_TYPE,\n UserData,\n UserNetworkingClient,\n UserNetworkingClientUpdate,\n UserNetworkingServerErrorType,\n WebsocketStatus,\n} from \"@mml-io/3d-web-user-networking\";\nimport { VoiceChatManager } from \"@mml-io/3d-web-voice-chat\";\nimport {\n IMMLScene,\n LoadingProgressManager,\n registerCustomElementsToWindow,\n setGlobalDocumentTimeManager,\n setGlobalMMLScene,\n} from \"mml-web\";\nimport { AudioListener, Euler, Scene, Vector3 } from \"three\";\n\ntype MMLDocumentConfiguration = {\n url: string;\n position?: {\n x: number;\n y: number;\n z: number;\n };\n rotation?: {\n x: number;\n y: number;\n z: number;\n };\n scale?: {\n x: number;\n y: number;\n z: number;\n };\n};\n\nexport type Networked3dWebExperienceClientConfig = {\n userNetworkAddress: string;\n sessionToken: string;\n chatVisibleByDefault?: boolean;\n userNameToColorOptions?: StringToHslOptions;\n animationConfig: AnimationConfig;\n voiceChatAddress?: string;\n updateURLLocation?: boolean;\n onServerBroadcast?: (broadcast: { broadcastType: string; payload: any }) => void;\n} & UpdatableConfig;\n\nexport type UpdatableConfig = {\n chatNetworkAddress?: string | null;\n mmlDocuments?: { [key: string]: MMLDocumentConfiguration };\n environmentConfiguration?: EnvironmentConfiguration;\n avatarConfiguration?: AvatarConfiguration;\n enableTweakPane?: boolean;\n};\n\nexport class Networked3dWebExperienceClient {\n private element: HTMLDivElement;\n private canvasHolder: HTMLDivElement;\n\n private scene = new Scene();\n private composer: Composer;\n private tweakPane: TweakPane | null = null;\n private audioListener = new AudioListener();\n\n private cameraManager: CameraManager;\n\n private collisionsManager = new CollisionsManager(this.scene);\n\n private characterModelLoader = new CharacterModelLoader();\n private characterManager: CharacterManager;\n\n private timeManager = new TimeManager();\n\n private keyInputManager = new KeyInputManager();\n private virtualJoystick: VirtualJoystick;\n\n private mmlCompositionScene: MMLCompositionScene;\n private mmlFrames: { [key: string]: HTMLElement } = {};\n\n private clientId: number | null = null;\n private networkClient: UserNetworkingClient;\n private remoteUserStates = new Map<number, CharacterState>();\n private userProfiles = new Map<number, UserData>();\n\n private networkChat: ChatNetworkingClient | null = null;\n private textChatUI: TextChatUI | null = null;\n\n private avatarSelectionUI: AvatarSelectionUI | null = null;\n\n private voiceChatManager: VoiceChatManager | null = null;\n private readonly latestCharacterObject = {\n characterState: null as null | CharacterState,\n };\n private characterControllerPaneSet: boolean = false;\n\n private initialLoadCompleted = false;\n private loadingProgressManager = new LoadingProgressManager();\n private loadingScreen: LoadingScreen;\n private errorScreen?: ErrorScreen;\n private currentRequestAnimationFrame: number | null = null;\n private groundPlane: GroundPlane | null = null;\n\n constructor(\n private holderElement: HTMLElement,\n private config: Networked3dWebExperienceClientConfig,\n ) {\n this.element = document.createElement(\"div\");\n this.element.style.position = \"absolute\";\n this.element.style.width = \"100%\";\n this.element.style.height = \"100%\";\n this.holderElement.appendChild(this.element);\n\n document.addEventListener(\"mousedown\", () => {\n if (this.audioListener.context.state === \"suspended\") {\n this.audioListener.context.resume();\n }\n });\n\n this.canvasHolder = document.createElement(\"div\");\n this.canvasHolder.style.position = \"absolute\";\n this.canvasHolder.style.width = \"100%\";\n this.canvasHolder.style.height = \"100%\";\n this.element.appendChild(this.canvasHolder);\n\n this.cameraManager = new CameraManager(this.canvasHolder, this.collisionsManager);\n this.cameraManager.camera.add(this.audioListener);\n\n this.virtualJoystick = new VirtualJoystick(this.element, {\n radius: 70,\n innerRadius: 20,\n mouseSupport: false,\n });\n\n this.composer = new Composer({\n scene: this.scene,\n camera: this.cameraManager.camera,\n spawnSun: true,\n environmentConfiguration: this.config.environmentConfiguration,\n });\n this.canvasHolder.appendChild(this.composer.renderer.domElement);\n\n if (this.config.enableTweakPane !== false) {\n this.setupTweakPane();\n }\n\n const resizeObserver = new ResizeObserver(() => {\n this.composer.fitContainer();\n });\n resizeObserver.observe(this.element);\n\n const initialNetworkLoadRef = {};\n this.loadingProgressManager.addLoadingAsset(initialNetworkLoadRef, \"network\", \"network\");\n this.networkClient = new UserNetworkingClient({\n url: this.config.userNetworkAddress,\n sessionToken: this.config.sessionToken,\n websocketFactory: (url: string) => new WebSocket(url),\n statusUpdateCallback: (status: WebsocketStatus) => {\n if (status === WebsocketStatus.Disconnected || status === WebsocketStatus.Reconnecting) {\n // The connection was lost after being established - the connection may be re-established with a different client ID\n this.characterManager.clear();\n this.remoteUserStates.clear();\n this.clientId = null;\n }\n },\n assignedIdentity: (clientId: number) => {\n console.log(`Assigned ID: ${clientId}`);\n this.clientId = clientId;\n if (this.initialLoadCompleted) {\n // Already loaded - respawn the character\n this.spawnCharacter();\n } else {\n this.loadingProgressManager.completedLoadingAsset(initialNetworkLoadRef);\n }\n },\n clientUpdate: (\n remoteClientId: number,\n userNetworkingClientUpdate: null | UserNetworkingClientUpdate,\n ) => {\n if (userNetworkingClientUpdate === null) {\n this.remoteUserStates.delete(remoteClientId);\n } else {\n this.remoteUserStates.set(remoteClientId, userNetworkingClientUpdate);\n }\n },\n clientProfileUpdated: (\n clientId: number,\n username: string,\n characterDescription: CharacterDescription,\n ): void => {\n this.updateUserProfile(clientId, {\n username,\n characterDescription,\n });\n },\n onServerError: (error: { message: string; errorType: UserNetworkingServerErrorType }) => {\n switch (error.errorType) {\n case USER_NETWORKING_AUTHENTICATION_FAILED_ERROR_TYPE:\n this.disposeWithError(error.message);\n break;\n case USER_NETWORKING_CONNECTION_LIMIT_REACHED_ERROR_TYPE:\n this.disposeWithError(error.message);\n break;\n case USER_NETWORKING_SERVER_SHUTDOWN_ERROR_TYPE:\n this.disposeWithError(error.message || \"Server shutdown\");\n break;\n default:\n console.error(`Unhandled server error: ${error.message}`);\n this.disposeWithError(error.message);\n }\n },\n onServerBroadcast: (broadcast: { broadcastType: string; payload: any }) => {\n this.config.onServerBroadcast?.(broadcast);\n },\n });\n\n this.characterManager = new CharacterManager({\n composer: this.composer,\n characterModelLoader: this.characterModelLoader,\n collisionsManager: this.collisionsManager,\n cameraManager: this.cameraManager,\n timeManager: this.timeManager,\n keyInputManager: this.keyInputManager,\n virtualJoystick: this.virtualJoystick,\n remoteUserStates: this.remoteUserStates,\n sendUpdate: (characterState: CharacterState) => {\n this.latestCharacterObject.characterState = characterState;\n this.networkClient.sendUpdate(characterState);\n },\n animationConfig: this.config.animationConfig,\n characterResolve: (characterId: number) => {\n return this.resolveCharacterData(characterId);\n },\n updateURLLocation: this.config.updateURLLocation !== false,\n });\n this.scene.add(this.characterManager.group);\n\n this.setGroundPlaneEnabled(this.config.environmentConfiguration?.groundPlane ?? true);\n\n this.setupMMLScene();\n\n this.loadingScreen = new LoadingScreen(this.loadingProgressManager);\n this.element.append(this.loadingScreen.element);\n\n this.loadingProgressManager.addProgressCallback(() => {\n const [, completed] = this.loadingProgressManager.toRatio();\n if (completed && !this.initialLoadCompleted) {\n this.initialLoadCompleted = true;\n /*\n When all content (in particular MML) has loaded, spawn the character (this is to avoid the character falling\n through as-yet-unloaded geometry)\n */\n this.connectToVoiceChat();\n this.connectToTextChat();\n this.mountAvatarSelectionUI();\n this.spawnCharacter();\n }\n });\n this.loadingProgressManager.setInitialLoad(true);\n }\n\n private setGroundPlaneEnabled(enabled: boolean) {\n if (enabled && this.groundPlane === null) {\n this.groundPlane = new GroundPlane();\n this.collisionsManager.addMeshesGroup(this.groundPlane);\n this.scene.add(this.groundPlane);\n } else if (!enabled && this.groundPlane !== null) {\n this.collisionsManager.removeMeshesGroup(this.groundPlane);\n this.scene.remove(this.groundPlane);\n this.groundPlane = null;\n }\n }\n\n public updateConfig(config: Partial<UpdatableConfig>) {\n this.config = {\n ...this.config,\n ...config,\n };\n if (config.environmentConfiguration) {\n this.composer.updateEnvironmentConfiguration(config.environmentConfiguration);\n this.setGroundPlaneEnabled(config.environmentConfiguration.groundPlane ?? true);\n }\n\n if (config.avatarConfiguration && this.avatarSelectionUI) {\n this.avatarSelectionUI?.updateAvatarConfig(config.avatarConfiguration);\n }\n\n if (config.enableTweakPane !== undefined) {\n if (config.enableTweakPane === false && this.tweakPane !== null) {\n this.tweakPane.dispose();\n this.tweakPane = null;\n } else if (config.enableTweakPane === true && this.tweakPane === null) {\n this.setupTweakPane();\n }\n }\n\n if (config.chatNetworkAddress !== undefined) {\n if (config.chatNetworkAddress === null && this.networkChat !== null) {\n this.networkChat.stop();\n this.networkChat = null;\n this.textChatUI?.dispose();\n this.textChatUI = null;\n } else {\n this.connectToTextChat();\n }\n }\n if (config.mmlDocuments) {\n this.setMMLDocuments(config.mmlDocuments);\n }\n }\n\n static createFullscreenHolder(): HTMLDivElement {\n document.body.style.margin = \"0\";\n document.body.style.overflow = \"hidden\";\n\n const holder = document.createElement(\"div\");\n holder.style.position = \"absolute\";\n holder.style.width = \"100%\";\n holder.style.height = \"100%\";\n holder.style.overflow = \"hidden\";\n document.body.appendChild(holder);\n return holder;\n }\n\n private resolveCharacterData(clientId: number): {\n username: string;\n characterDescription: CharacterDescription;\n } {\n const user = this.userProfiles.get(clientId)!;\n\n if (!user) {\n throw new Error(`Failed to resolve user for clientId ${clientId}`);\n }\n\n return {\n username: user.username,\n characterDescription: user.characterDescription,\n };\n }\n\n private updateUserProfile(id: number, userData: UserData) {\n console.log(`Update user_profile for id=${id} (username=${userData.username})`);\n\n this.userProfiles.set(id, userData);\n\n this.characterManager.respawnIfPresent(id);\n }\n\n private updateUserAvatar(avatar: AvatarType) {\n if (this.clientId === null) {\n throw new Error(\"Client ID not set\");\n }\n const user = this.userProfiles.get(this.clientId);\n if (!user) {\n throw new Error(\"User not found\");\n }\n\n const newUser = {\n ...user,\n characterDescription: {\n meshFileUrl: avatar.meshFileUrl ?? undefined,\n mmlCharacterUrl: avatar.mmlCharacterUrl ?? undefined,\n mmlCharacterString: avatar.mmlCharacterString ?? undefined,\n },\n } as UserData;\n\n this.userProfiles.set(this.clientId, newUser);\n this.updateUserProfile(this.clientId, newUser);\n }\n\n private sendChatMessageToServer(message: string): void {\n this.mmlCompositionScene.onChatMessage(message);\n if (this.clientId === null || this.networkChat === null) return;\n this.networkChat.sendChatMessage(message);\n }\n\n private sendIdentityUpdateToServer(avatar: AvatarType) {\n if (!this.clientId) {\n throw new Error(\"Client ID not set\");\n }\n\n const userProfile = this.userProfiles.get(this.clientId);\n\n if (!userProfile) {\n throw new Error(\"User profile not found\");\n }\n\n this.networkClient.sendMessage({\n type: USER_NETWORKING_USER_UPDATE_MESSAGE_TYPE,\n userIdentity: {\n username: userProfile.username,\n characterDescription: {\n mmlCharacterString: avatar.mmlCharacterString,\n mmlCharacterUrl: avatar.mmlCharacterUrl,\n meshFileUrl: avatar.meshFileUrl,\n } as CharacterDescription,\n },\n });\n }\n\n private connectToVoiceChat() {\n if (this.clientId === null) return;\n\n if (this.voiceChatManager === null && this.config.voiceChatAddress) {\n this.voiceChatManager = new VoiceChatManager({\n url: this.config.voiceChatAddress,\n holderElement: this.element,\n userId: this.clientId,\n remoteUserStates: this.remoteUserStates,\n latestCharacterObj: this.latestCharacterObject,\n autoJoin: false,\n });\n }\n }\n\n private setupTweakPane() {\n if (this.tweakPane) {\n return;\n }\n this.tweakPane = new TweakPane(\n this.element,\n this.composer.renderer,\n this.scene,\n this.composer.effectComposer,\n );\n this.cameraManager.setupTweakPane(this.tweakPane);\n this.composer.setupTweakPane(this.tweakPane);\n }\n\n private connectToTextChat() {\n if (this.clientId === null) {\n return;\n }\n if (this.networkChat === null && this.config.chatNetworkAddress) {\n const user = this.userProfiles.get(this.clientId);\n if (!user) {\n throw new Error(\"User not found\");\n }\n\n if (this.textChatUI === null) {\n const textChatUISettings: TextChatUIProps = {\n holderElement: this.element,\n clientname: user.username,\n sendMessageToServerMethod: this.sendChatMessageToServer.bind(this),\n visibleByDefault: this.config.chatVisibleByDefault,\n stringToHslOptions: this.config.userNameToColorOptions,\n };\n this.textChatUI = new TextChatUI(textChatUISettings);\n this.textChatUI.init();\n }\n\n this.networkChat = new ChatNetworkingClient({\n url: this.config.chatNetworkAddress,\n sessionToken: this.config.sessionToken,\n websocketFactory: (url: string) => new WebSocket(url),\n statusUpdateCallback: (status: WebsocketStatus) => {\n if (status === WebsocketStatus.Disconnected || status === WebsocketStatus.Reconnecting) {\n // The connection was lost after being established - the connection may be re-established with a different client ID\n }\n },\n clientChatUpdate: (\n clientId: number,\n chatNetworkingUpdate: null | ChatNetworkingClientChatMessage,\n ) => {\n if (chatNetworkingUpdate !== null && this.textChatUI !== null) {\n const username = this.userProfiles.get(clientId)?.username || \"Unknown\";\n this.textChatUI.addTextMessage(username, chatNetworkingUpdate.text);\n }\n },\n onServerError: (error: { message: string; errorType: ChatNetworkingServerErrorType }) => {\n console.error(`Chat server error: ${error.message}. errorType: ${error.errorType}`);\n this.disposeWithError(error.message);\n },\n });\n }\n }\n\n private mountAvatarSelectionUI() {\n this.avatarSelectionUI = new AvatarSelectionUI({\n holderElement: this.element,\n visibleByDefault: false,\n sendMessageToServerMethod: this.sendIdentityUpdateToServer.bind(this),\n availableAvatars: this.config.avatarConfiguration?.availableAvatars ?? [],\n allowCustomAvatars: this.config.avatarConfiguration?.allowCustomAvatars,\n });\n this.avatarSelectionUI.init();\n }\n\n public update(): void {\n this.timeManager.update();\n this.characterManager.update();\n this.voiceChatManager?.speakingParticipants.forEach((value: boolean, id: number) => {\n this.characterManager.setSpeakingCharacter(id, value);\n });\n this.cameraManager.update();\n this.composer.sun?.updateCharacterPosition(this.characterManager.localCharacter?.position);\n this.composer.render(this.timeManager);\n if (this.tweakPane?.guiVisible) {\n this.tweakPane.updateStats(this.timeManager);\n this.tweakPane.updateCameraData(this.cameraManager);\n if (this.characterManager.localCharacter && this.characterManager.localController) {\n if (!this.characterControllerPaneSet) {\n this.characterControllerPaneSet = true;\n this.characterManager.setupTweakPane(this.tweakPane);\n } else {\n this.tweakPane.updateCharacterData(this.characterManager.localController);\n }\n }\n }\n this.currentRequestAnimationFrame = requestAnimationFrame(() => {\n this.update();\n });\n }\n\n private spawnCharacter() {\n if (this.clientId === null) {\n throw new Error(\"Client ID not set\");\n }\n const spawnPosition = getSpawnPositionInsideCircle(3, 30, this.clientId!, 0.4);\n const spawnRotation = new Euler(0, 0, 0);\n let cameraPosition: Vector3 | null = null;\n if (window.location.hash && window.location.hash.length > 1) {\n const urlParams = decodeCharacterAndCamera(window.location.hash.substring(1));\n spawnPosition.copy(urlParams.character.position);\n spawnRotation.setFromQuaternion(urlParams.character.quaternion);\n cameraPosition = urlParams.camera.position;\n }\n const ownIdentity = this.userProfiles.get(this.clientId);\n if (!ownIdentity) {\n throw new Error(\"Own identity not found\");\n }\n\n this.characterManager.spawnLocalCharacter(\n this.clientId!,\n ownIdentity.username,\n ownIdentity.characterDescription,\n spawnPosition,\n spawnRotation,\n );\n\n if (cameraPosition !== null) {\n this.cameraManager.camera.position.copy(cameraPosition);\n this.cameraManager.setTarget(\n new Vector3().add(spawnPosition).add(this.characterManager.headTargetOffset),\n );\n this.cameraManager.reverseUpdateFromPositions();\n }\n }\n\n private disposeWithError(message: string) {\n this.dispose();\n this.errorScreen = new ErrorScreen(\"An error occurred\", message);\n this.element.append(this.errorScreen.element);\n }\n\n public dispose() {\n this.networkClient.stop();\n this.networkChat?.stop();\n for (const [key, element] of Object.entries(this.mmlFrames)) {\n element.remove();\n }\n this.mmlFrames = {};\n this.textChatUI?.dispose();\n this.mmlCompositionScene.dispose();\n this.composer.dispose();\n this.tweakPane?.dispose();\n if (this.currentRequestAnimationFrame !== null) {\n cancelAnimationFrame(this.currentRequestAnimationFrame);\n this.currentRequestAnimationFrame = null;\n }\n this.cameraManager.dispose();\n this.loadingScreen.dispose();\n this.errorScreen?.dispose();\n }\n\n private setupMMLScene() {\n registerCustomElementsToWindow(window);\n this.mmlCompositionScene = new MMLCompositionScene({\n targetElement: this.element,\n renderer: this.composer.renderer,\n scene: this.scene,\n camera: this.cameraManager.camera,\n audioListener: this.audioListener,\n collisionsManager: this.collisionsManager,\n getUserPositionAndRotation: () => {\n return this.characterManager.getLocalCharacterPositionAndRotation();\n },\n });\n this.scene.add(this.mmlCompositionScene.group);\n setGlobalMMLScene(this.mmlCompositionScene.mmlScene as IMMLScene);\n setGlobalDocumentTimeManager(this.mmlCompositionScene.documentTimeManager);\n\n this.setMMLDocuments(this.config.mmlDocuments ?? {});\n\n const mmlProgressManager = this.mmlCompositionScene.mmlScene.getLoadingProgressManager!()!;\n this.loadingProgressManager.addLoadingDocument(mmlProgressManager, \"mml\", mmlProgressManager);\n mmlProgressManager.addProgressCallback(() => {\n this.loadingProgressManager.updateDocumentProgress(mmlProgressManager);\n });\n mmlProgressManager.setInitialLoad(true);\n }\n\n private createFrame(mmlDocument: MMLDocumentConfiguration) {\n const frameElement = document.createElement(\"m-frame\");\n frameElement.setAttribute(\"src\", mmlDocument.url);\n this.updateFrameAttributes(frameElement, mmlDocument);\n return frameElement;\n }\n\n private updateFrameAttributes(frameElement: HTMLElement, mmlDocument: MMLDocumentConfiguration) {\n const existingSrc = frameElement.getAttribute(\"src\");\n if (existingSrc !== mmlDocument.url) {\n frameElement.setAttribute(\"src\", mmlDocument.url);\n }\n if (mmlDocument.position) {\n frameElement.setAttribute(\"x\", mmlDocument.position.x.toString());\n frameElement.setAttribute(\"y\", mmlDocument.position.y.toString());\n frameElement.setAttribute(\"z\", mmlDocument.position.z.toString());\n } else {\n frameElement.setAttribute(\"x\", \"0\");\n frameElement.setAttribute(\"y\", \"0\");\n frameElement.setAttribute(\"z\", \"0\");\n }\n if (mmlDocument.rotation) {\n frameElement.setAttribute(\"rx\", mmlDocument.rotation.x.toString());\n frameElement.setAttribute(\"ry\", mmlDocument.rotation.y.toString());\n frameElement.setAttribute(\"rz\", mmlDocument.rotation.z.toString());\n } else {\n frameElement.setAttribute(\"rx\", \"0\");\n frameElement.setAttribute(\"ry\", \"0\");\n frameElement.setAttribute(\"rz\", \"0\");\n }\n if (mmlDocument.scale?.x !== undefined) {\n frameElement.setAttribute(\"sx\", mmlDocument.scale.x.toString());\n } else {\n frameElement.setAttribute(\"sx\", \"1\");\n }\n if (mmlDocument.scale?.y !== undefined) {\n frameElement.setAttribute(\"sy\", mmlDocument.scale.y.toString());\n } else {\n frameElement.setAttribute(\"sy\", \"1\");\n }\n if (mmlDocument.scale?.z !== undefined) {\n frameElement.setAttribute(\"sz\", mmlDocument.scale.z.toString());\n } else {\n frameElement.setAttribute(\"sz\", \"1\");\n }\n }\n\n private setMMLDocuments(mmlDocuments: { [key: string]: MMLDocumentConfiguration }) {\n const newFramesMap: { [key: string]: HTMLElement } = {};\n for (const [key, mmlDocSpec] of Object.entries(mmlDocuments)) {\n const existing = this.mmlFrames[key];\n if (!existing) {\n const frameElement = this.createFrame(mmlDocSpec);\n document.body.appendChild(frameElement);\n newFramesMap[key] = frameElement;\n } else {\n delete this.mmlFrames[key];\n newFramesMap[key] = existing;\n this.updateFrameAttributes(existing, mmlDocSpec);\n }\n }\n for (const [key, element] of Object.entries(this.mmlFrames)) {\n element.remove();\n }\n this.mmlFrames = newFramesMap;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["_a"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mml-io/3d-web-experience-client",
3
- "version": "0.17.0",
3
+ "version": "0.19.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -18,16 +18,17 @@
18
18
  "lint-fix": "eslint \"./{src,test}/**/*.{js,jsx,ts,tsx}\" --fix"
19
19
  },
20
20
  "dependencies": {
21
- "@mml-io/3d-web-client-core": "^0.17.0",
22
- "@mml-io/3d-web-text-chat": "^0.17.0",
23
- "@mml-io/3d-web-user-networking": "^0.17.0",
24
- "@mml-io/3d-web-voice-chat": "^0.17.0",
25
- "mml-web": "^0.15.0",
21
+ "@mml-io/3d-web-avatar-selection-ui": "^0.19.0",
22
+ "@mml-io/3d-web-client-core": "^0.19.0",
23
+ "@mml-io/3d-web-text-chat": "^0.19.0",
24
+ "@mml-io/3d-web-user-networking": "^0.19.0",
25
+ "@mml-io/3d-web-voice-chat": "^0.19.0",
26
+ "mml-web": "0.17.1",
26
27
  "three": "0.163.0"
27
28
  },
28
29
  "devDependencies": {
29
- "@types/node": "^20.12.7",
30
+ "@types/node": "^20.14.10",
30
31
  "@types/three": "0.163.0"
31
32
  },
32
- "gitHead": "bc97b49ea69d920e0824a6885f7e8fca440e2e12"
33
+ "gitHead": "1d785e68643dd46c63b49d9fcb0fc1d73097a414"
33
34
  }