@mml-io/3d-web-client-core 0.21.6 → 0.22.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.
@@ -59,6 +59,7 @@ export declare class CameraManager {
59
59
  private easeOutExpo;
60
60
  updateAspect(aspect: number): void;
61
61
  recomputeFoV(immediately?: boolean): void;
62
+ isFlyCameraOn(): boolean;
62
63
  toggleFlyCamera(): void;
63
64
  get activeCamera(): PerspectiveCamera;
64
65
  update(): void;
@@ -12,6 +12,38 @@ import { CharacterModelLoader } from "./CharacterModelLoader";
12
12
  import { CharacterState } from "./CharacterState";
13
13
  import { LocalController } from "./LocalController";
14
14
  import { RemoteController } from "./RemoteController";
15
+ type SpawnPosition = {
16
+ x: number;
17
+ y: number;
18
+ z: number;
19
+ };
20
+ type SpawnPositionVariance = {
21
+ x: number;
22
+ y: number;
23
+ z: number;
24
+ };
25
+ type RespawnTrigger = {
26
+ minX: number;
27
+ maxX: number;
28
+ minY: number;
29
+ maxY: number;
30
+ minZ: number;
31
+ maxZ: number;
32
+ };
33
+ export type SpawnConfiguration = {
34
+ spawnPosition?: Partial<SpawnPosition>;
35
+ spawnPositionVariance?: Partial<SpawnPositionVariance>;
36
+ spawnYRotation?: number;
37
+ respawnTrigger?: Partial<RespawnTrigger>;
38
+ enableRespawnButton?: boolean;
39
+ };
40
+ export type SpawnConfigurationState = {
41
+ spawnPosition: SpawnPosition;
42
+ spawnPositionVariance: SpawnPositionVariance;
43
+ spawnYRotation: number;
44
+ respawnTrigger: RespawnTrigger;
45
+ enableRespawnButton: boolean;
46
+ };
15
47
  export type CharacterManagerConfig = {
16
48
  composer: Composer;
17
49
  characterModelLoader: CharacterModelLoader;
@@ -23,6 +55,7 @@ export type CharacterManagerConfig = {
23
55
  remoteUserStates: Map<number, CharacterState>;
24
56
  sendUpdate: (update: CharacterState) => void;
25
57
  animationConfig: AnimationConfig;
58
+ spawnConfiguration: SpawnConfigurationState;
26
59
  characterResolve: (clientId: number) => {
27
60
  username: string;
28
61
  characterDescription: CharacterDescription;
@@ -43,6 +76,7 @@ export declare class CharacterManager {
43
76
  private lastUpdateSentTime;
44
77
  constructor(config: CharacterManagerConfig);
45
78
  spawnLocalCharacter(id: number, username: string, characterDescription: CharacterDescription, spawnPosition?: Vector3, spawnRotation?: Euler): void;
79
+ createRespawnButton(): HTMLDivElement;
46
80
  setupTweakPane(tweakPane: TweakPane): void;
47
81
  spawnRemoteCharacter(id: number, username: string, characterDescription: CharacterDescription, spawnPosition?: Vector3, spawnRotation?: Euler): void;
48
82
  getLocalCharacterPositionAndRotation(): PositionAndRotation;
@@ -53,3 +87,4 @@ export declare class CharacterManager {
53
87
  respawnIfPresent(id: number): void;
54
88
  update(): void;
55
89
  }
90
+ export {};
@@ -5,6 +5,7 @@ import { KeyInputManager } from "../input/KeyInputManager";
5
5
  import { VirtualJoystick } from "../input/VirtualJoystick";
6
6
  import { TimeManager } from "../time/TimeManager";
7
7
  import { Character } from "./Character";
8
+ import { SpawnConfigurationState } from "./CharacterManager";
8
9
  import { CharacterState } from "./CharacterState";
9
10
  export type LocalControllerConfig = {
10
11
  id: number;
@@ -14,6 +15,7 @@ export type LocalControllerConfig = {
14
15
  virtualJoystick?: VirtualJoystick;
15
16
  cameraManager: CameraManager;
16
17
  timeManager: TimeManager;
18
+ spawnConfiguration: SpawnConfigurationState;
17
19
  };
18
20
  export declare class LocalController {
19
21
  private config;
@@ -70,7 +72,14 @@ export declare class LocalController {
70
72
  jumpReleased: boolean;
71
73
  networkState: CharacterState;
72
74
  private controlState;
75
+ private minimumX;
76
+ private maximumX;
77
+ private minimumY;
78
+ private maximumY;
79
+ private minimumZ;
80
+ private maximumZ;
73
81
  constructor(config: LocalControllerConfig);
82
+ updateSpawnConfig(spawnConfig: SpawnConfigurationState): void;
74
83
  update(): void;
75
84
  private getTargetAnimation;
76
85
  private updateRotationOffset;
@@ -85,5 +94,5 @@ export declare class LocalController {
85
94
  position: Vector3;
86
95
  } | null;
87
96
  private updateNetworkState;
88
- private resetPosition;
97
+ resetPosition(): void;
89
98
  }
package/build/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { CameraManager } from "./camera/CameraManager";
2
2
  export { CharacterDescription, AnimationConfig } from "./character/Character";
3
- export { CharacterManager } from "./character/CharacterManager";
3
+ export { CharacterManager, SpawnConfiguration, SpawnConfigurationState, } from "./character/CharacterManager";
4
4
  export * from "./character/url-position";
5
5
  export * from "./helpers/math-helpers";
6
6
  export { CharacterModelLoader } from "./character/CharacterModelLoader";
package/build/index.js CHANGED
@@ -431,6 +431,9 @@ var CameraManager = class {
431
431
  this.fov = this.targetFOV;
432
432
  }
433
433
  }
434
+ isFlyCameraOn() {
435
+ return this.isMainCameraActive === false && this.orbitControls.enabled === true;
436
+ }
434
437
  toggleFlyCamera() {
435
438
  this.isMainCameraActive = !this.isMainCameraActive;
436
439
  this.orbitControls.enabled = !this.isMainCameraActive;
@@ -1530,6 +1533,7 @@ var Character = class extends Group {
1530
1533
  };
1531
1534
 
1532
1535
  // src/character/CharacterManager.ts
1536
+ import { radToDeg } from "@mml-io/mml-web";
1533
1537
  import { Euler as Euler2, Group as Group2, Quaternion as Quaternion5, Vector3 as Vector39 } from "three";
1534
1538
 
1535
1539
  // src/character/LocalController.ts
@@ -1778,6 +1782,45 @@ var LocalController = class {
1778
1782
  rotation: { quaternionY: 0, quaternionW: 1 },
1779
1783
  state: 0 /* idle */
1780
1784
  };
1785
+ this.minimumX = this.config.spawnConfiguration.respawnTrigger.minX;
1786
+ this.maximumX = this.config.spawnConfiguration.respawnTrigger.maxX;
1787
+ this.minimumY = this.config.spawnConfiguration.respawnTrigger.minY;
1788
+ this.maximumY = this.config.spawnConfiguration.respawnTrigger.maxY;
1789
+ this.minimumZ = this.config.spawnConfiguration.respawnTrigger.minZ;
1790
+ this.maximumZ = this.config.spawnConfiguration.respawnTrigger.maxZ;
1791
+ const maxAbsSpawnX = Math.abs(this.config.spawnConfiguration.spawnPosition.x) + Math.abs(this.config.spawnConfiguration.spawnPositionVariance.x);
1792
+ const maxAbsSpawnY = Math.abs(this.config.spawnConfiguration.spawnPosition.y) + Math.abs(this.config.spawnConfiguration.spawnPositionVariance.y);
1793
+ const maxAbsSpawnZ = Math.abs(this.config.spawnConfiguration.spawnPosition.z) + Math.abs(this.config.spawnConfiguration.spawnPositionVariance.z);
1794
+ if (Math.abs(this.minimumX) < maxAbsSpawnX || Math.abs(this.maximumX) < maxAbsSpawnX) {
1795
+ this.minimumX = -maxAbsSpawnX - 1;
1796
+ this.maximumX = maxAbsSpawnX + 1;
1797
+ console.warn(
1798
+ "The respawnTrigger X values are out of the bounds of the spawnPosition + spawnPositionVariance. Please check your respawnTrigger config."
1799
+ );
1800
+ }
1801
+ if (Math.abs(this.minimumY) < maxAbsSpawnY || Math.abs(this.maximumY) < maxAbsSpawnY) {
1802
+ this.minimumY = -maxAbsSpawnY - 1;
1803
+ this.maximumY = maxAbsSpawnY + 1;
1804
+ console.warn(
1805
+ "The respawnTrigger Y values are out of the bounds of the spawnPosition + spawnPositionVariance. Please check your respawnTrigger config."
1806
+ );
1807
+ }
1808
+ if (Math.abs(this.minimumZ) < maxAbsSpawnZ) {
1809
+ this.minimumZ = -maxAbsSpawnZ - 1;
1810
+ this.maximumZ = maxAbsSpawnZ + 1;
1811
+ console.warn(
1812
+ "The respawnTrigger Z values are out of the bounds of the spawnPosition + spawnPositionVariance. Please check your respawnTrigger config."
1813
+ );
1814
+ }
1815
+ }
1816
+ updateSpawnConfig(spawnConfig) {
1817
+ this.config.spawnConfiguration = spawnConfig;
1818
+ this.minimumX = spawnConfig.respawnTrigger.minX;
1819
+ this.maximumX = spawnConfig.respawnTrigger.maxX;
1820
+ this.minimumY = spawnConfig.respawnTrigger.minY;
1821
+ this.maximumY = spawnConfig.respawnTrigger.maxY;
1822
+ this.minimumZ = spawnConfig.respawnTrigger.minZ;
1823
+ this.maximumZ = spawnConfig.respawnTrigger.maxZ;
1781
1824
  }
1782
1825
  update() {
1783
1826
  var _a, _b;
@@ -1804,7 +1847,13 @@ var LocalController = class {
1804
1847
  i
1805
1848
  );
1806
1849
  }
1807
- if (this.config.character.position.y < -100) {
1850
+ const outOfBounds = this.config.character.position.x < this.minimumX || // left
1851
+ this.config.character.position.x > this.maximumX || // right
1852
+ this.config.character.position.z < this.minimumZ || // back
1853
+ this.config.character.position.z > this.maximumZ || // front
1854
+ this.config.character.position.y < this.minimumY || // down
1855
+ this.config.character.position.y > this.maximumY;
1856
+ if (outOfBounds) {
1808
1857
  this.resetPosition();
1809
1858
  }
1810
1859
  this.updateNetworkState();
@@ -2063,8 +2112,34 @@ var LocalController = class {
2063
2112
  };
2064
2113
  }
2065
2114
  resetPosition() {
2115
+ const randomWithVariance = (value, variance) => {
2116
+ const min = value - variance;
2117
+ const max = value + variance;
2118
+ return Math.random() * (max - min) + min;
2119
+ };
2120
+ this.characterVelocity.x = 0;
2066
2121
  this.characterVelocity.y = 0;
2067
- this.config.character.position.y = 3;
2122
+ this.characterVelocity.z = 0;
2123
+ this.config.character.position.set(
2124
+ randomWithVariance(
2125
+ this.config.spawnConfiguration.spawnPosition.x,
2126
+ this.config.spawnConfiguration.spawnPositionVariance.x
2127
+ ),
2128
+ randomWithVariance(
2129
+ this.config.spawnConfiguration.spawnPosition.y,
2130
+ this.config.spawnConfiguration.spawnPositionVariance.y
2131
+ ),
2132
+ randomWithVariance(
2133
+ this.config.spawnConfiguration.spawnPosition.z,
2134
+ this.config.spawnConfiguration.spawnPositionVariance.z
2135
+ )
2136
+ );
2137
+ const respawnRotation = new Euler(
2138
+ 0,
2139
+ -this.config.spawnConfiguration.spawnYRotation * (Math.PI / 180),
2140
+ 0
2141
+ );
2142
+ this.config.character.rotation.set(respawnRotation.x, respawnRotation.y, respawnRotation.z);
2068
2143
  this.characterOnGround = false;
2069
2144
  this.doubleJumpUsed = false;
2070
2145
  this.jumpReleased = true;
@@ -2102,8 +2177,13 @@ var RemoteController = class {
2102
2177
  }
2103
2178
  updateFromNetwork(clientUpdate) {
2104
2179
  const { position, rotation, state } = clientUpdate;
2105
- this.config.character.position.lerp(new Vector37(position.x, position.y, position.z), 0.15);
2106
- const rotationQuaternion = new Quaternion3(0, rotation.quaternionY, 0, rotation.quaternionW);
2180
+ const distanceSquared = this.config.character.position.distanceToSquared(position);
2181
+ if (distanceSquared > 5 * 5) {
2182
+ this.config.character.position.copy(position);
2183
+ } else {
2184
+ this.config.character.position.lerp(new Vector37(position.x, position.y, position.z), 0.15);
2185
+ }
2186
+ const rotationQuaternion = tempQuaternion.set(0, rotation.quaternionY, 0, rotation.quaternionW);
2107
2187
  this.config.character.quaternion.slerp(rotationQuaternion, 0.6);
2108
2188
  if (state !== this.currentAnimation) {
2109
2189
  this.currentAnimation = state;
@@ -2183,13 +2263,40 @@ var CharacterManager = class {
2183
2263
  keyInputManager: this.config.keyInputManager,
2184
2264
  virtualJoystick: this.config.virtualJoystick,
2185
2265
  cameraManager: this.config.cameraManager,
2186
- timeManager: this.config.timeManager
2266
+ timeManager: this.config.timeManager,
2267
+ spawnConfiguration: this.config.spawnConfiguration
2187
2268
  });
2188
2269
  this.localCharacter.position.set(spawnPosition.x, spawnPosition.y, spawnPosition.z);
2189
2270
  this.localCharacter.rotation.set(spawnRotation.x, spawnRotation.y, spawnRotation.z);
2190
2271
  this.group.add(character);
2191
2272
  this.localCharacterSpawned = true;
2192
2273
  }
2274
+ createRespawnButton() {
2275
+ const respawnButton = document.createElement("div");
2276
+ respawnButton.className = "respawn-button";
2277
+ respawnButton.textContent = "RESPAWN";
2278
+ respawnButton.addEventListener("click", () => {
2279
+ this.localController.resetPosition();
2280
+ });
2281
+ respawnButton.style.position = "absolute";
2282
+ respawnButton.style.top = "14px";
2283
+ respawnButton.style.left = "8px";
2284
+ respawnButton.style.zIndex = "102";
2285
+ respawnButton.style.backgroundColor = "rgba(0, 0, 0, 0.7)";
2286
+ respawnButton.style.color = "#ffffff";
2287
+ respawnButton.style.borderRadius = "8px";
2288
+ respawnButton.style.border = "1px solid rgba(255, 255, 255, 0.21)";
2289
+ respawnButton.style.height = "22px";
2290
+ respawnButton.style.padding = "8px";
2291
+ respawnButton.style.cursor = "pointer";
2292
+ respawnButton.style.fontSize = "12px";
2293
+ respawnButton.style.fontFamily = "Helvetica, sans-serif";
2294
+ respawnButton.style.userSelect = "none";
2295
+ respawnButton.style.display = "flex";
2296
+ respawnButton.style.alignItems = "center";
2297
+ respawnButton.style.justifyContent = "center";
2298
+ return respawnButton;
2299
+ }
2193
2300
  setupTweakPane(tweakPane) {
2194
2301
  tweakPane.setupCharacterController(this.localController);
2195
2302
  }
@@ -2215,9 +2322,14 @@ var CharacterManager = class {
2215
2322
  }
2216
2323
  getLocalCharacterPositionAndRotation() {
2217
2324
  if (this.localCharacter && this.localCharacter && this.localCharacter) {
2325
+ const rotation = this.localCharacter.rotation;
2218
2326
  return {
2219
2327
  position: this.localCharacter.position,
2220
- rotation: this.localCharacter.rotation
2328
+ rotation: {
2329
+ x: radToDeg(rotation.x),
2330
+ y: radToDeg(rotation.y),
2331
+ z: radToDeg(rotation.z)
2332
+ }
2221
2333
  };
2222
2334
  }
2223
2335
  return {
@@ -2453,8 +2565,17 @@ var KeyInputManager = class {
2453
2565
  return this.keys.get(key) || false;
2454
2566
  }
2455
2567
  createKeyBinding(key, callback) {
2568
+ if (this.bindings.has(key)) {
2569
+ return;
2570
+ }
2456
2571
  this.bindings.set(key, callback);
2457
2572
  }
2573
+ removeKeyBinding(key) {
2574
+ if (!this.bindings.has(key)) {
2575
+ return;
2576
+ }
2577
+ this.bindings.delete(key);
2578
+ }
2458
2579
  isMovementKeyPressed() {
2459
2580
  return ["w" /* W */, "a" /* A */, "s" /* S */, "d" /* D */].some((key) => this.isKeyPressed(key));
2460
2581
  }
@@ -5536,6 +5657,7 @@ var Composer = class {
5536
5657
  }
5537
5658
  this.updateSkyboxAndEnvValues();
5538
5659
  this.updateAmbientLightValues();
5660
+ this.updateBloomValues();
5539
5661
  this.updateSunValues();
5540
5662
  this.updateFogValues();
5541
5663
  }
@@ -5808,6 +5930,13 @@ var Composer = class {
5808
5930
  this.updateSkyboxRotation();
5809
5931
  }
5810
5932
  }
5933
+ updateBloomValues() {
5934
+ var _a, _b;
5935
+ if (typeof ((_b = (_a = this.environmentConfiguration) == null ? void 0 : _a.postProcessing) == null ? void 0 : _b.bloomIntensity) === "number") {
5936
+ extrasValues.bloom = this.environmentConfiguration.postProcessing.bloomIntensity;
5937
+ }
5938
+ this.bloomEffect.intensity = extrasValues.bloom;
5939
+ }
5811
5940
  updateAmbientLightValues() {
5812
5941
  var _a, _b;
5813
5942
  if (typeof ((_b = (_a = this.environmentConfiguration) == null ? void 0 : _a.ambientLight) == null ? void 0 : _b.intensity) === "number") {