@mml-io/3d-web-client-core 0.0.0-experimental-928ce80-20250424 → 0.0.0-experimental-36db237-20250514
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.
@@ -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
|
-
|
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
@@ -1778,6 +1778,45 @@ var LocalController = class {
|
|
1778
1778
|
rotation: { quaternionY: 0, quaternionW: 1 },
|
1779
1779
|
state: 0 /* idle */
|
1780
1780
|
};
|
1781
|
+
this.minimumX = this.config.spawnConfiguration.respawnTrigger.minX;
|
1782
|
+
this.maximumX = this.config.spawnConfiguration.respawnTrigger.maxX;
|
1783
|
+
this.minimumY = this.config.spawnConfiguration.respawnTrigger.minY;
|
1784
|
+
this.maximumY = this.config.spawnConfiguration.respawnTrigger.maxY;
|
1785
|
+
this.minimumZ = this.config.spawnConfiguration.respawnTrigger.minZ;
|
1786
|
+
this.maximumZ = this.config.spawnConfiguration.respawnTrigger.maxZ;
|
1787
|
+
const maxAbsSpawnX = Math.abs(this.config.spawnConfiguration.spawnPosition.x) + Math.abs(this.config.spawnConfiguration.spawnPositionVariance.x);
|
1788
|
+
const maxAbsSpawnY = Math.abs(this.config.spawnConfiguration.spawnPosition.y) + Math.abs(this.config.spawnConfiguration.spawnPositionVariance.y);
|
1789
|
+
const maxAbsSpawnZ = Math.abs(this.config.spawnConfiguration.spawnPosition.z) + Math.abs(this.config.spawnConfiguration.spawnPositionVariance.z);
|
1790
|
+
if (Math.abs(this.minimumX) < maxAbsSpawnX || Math.abs(this.maximumX) < maxAbsSpawnX) {
|
1791
|
+
this.minimumX = -maxAbsSpawnX - 1;
|
1792
|
+
this.maximumX = maxAbsSpawnX + 1;
|
1793
|
+
console.warn(
|
1794
|
+
"The respawnTrigger X values are out of the bounds of the spawnPosition + spawnPositionVariance. Please check your respawnTrigger config."
|
1795
|
+
);
|
1796
|
+
}
|
1797
|
+
if (Math.abs(this.minimumY) < maxAbsSpawnY || Math.abs(this.maximumY) < maxAbsSpawnY) {
|
1798
|
+
this.minimumY = -maxAbsSpawnY - 1;
|
1799
|
+
this.maximumY = maxAbsSpawnY + 1;
|
1800
|
+
console.warn(
|
1801
|
+
"The respawnTrigger Y values are out of the bounds of the spawnPosition + spawnPositionVariance. Please check your respawnTrigger config."
|
1802
|
+
);
|
1803
|
+
}
|
1804
|
+
if (Math.abs(this.minimumZ) < maxAbsSpawnZ) {
|
1805
|
+
this.minimumZ = -maxAbsSpawnZ - 1;
|
1806
|
+
this.maximumZ = maxAbsSpawnZ + 1;
|
1807
|
+
console.warn(
|
1808
|
+
"The respawnTrigger Z values are out of the bounds of the spawnPosition + spawnPositionVariance. Please check your respawnTrigger config."
|
1809
|
+
);
|
1810
|
+
}
|
1811
|
+
}
|
1812
|
+
updateSpawnConfig(spawnConfig) {
|
1813
|
+
this.config.spawnConfiguration = spawnConfig;
|
1814
|
+
this.minimumX = spawnConfig.respawnTrigger.minX;
|
1815
|
+
this.maximumX = spawnConfig.respawnTrigger.maxX;
|
1816
|
+
this.minimumY = spawnConfig.respawnTrigger.minY;
|
1817
|
+
this.maximumY = spawnConfig.respawnTrigger.maxY;
|
1818
|
+
this.minimumZ = spawnConfig.respawnTrigger.minZ;
|
1819
|
+
this.maximumZ = spawnConfig.respawnTrigger.maxZ;
|
1781
1820
|
}
|
1782
1821
|
update() {
|
1783
1822
|
var _a, _b;
|
@@ -1804,7 +1843,13 @@ var LocalController = class {
|
|
1804
1843
|
i
|
1805
1844
|
);
|
1806
1845
|
}
|
1807
|
-
|
1846
|
+
const outOfBounds = this.config.character.position.x < this.minimumX || // left
|
1847
|
+
this.config.character.position.x > this.maximumX || // right
|
1848
|
+
this.config.character.position.z < this.minimumZ || // back
|
1849
|
+
this.config.character.position.z > this.maximumZ || // front
|
1850
|
+
this.config.character.position.y < this.minimumY || // down
|
1851
|
+
this.config.character.position.y > this.maximumY;
|
1852
|
+
if (outOfBounds) {
|
1808
1853
|
this.resetPosition();
|
1809
1854
|
}
|
1810
1855
|
this.updateNetworkState();
|
@@ -2063,8 +2108,34 @@ var LocalController = class {
|
|
2063
2108
|
};
|
2064
2109
|
}
|
2065
2110
|
resetPosition() {
|
2111
|
+
const randomWithVariance = (value, variance) => {
|
2112
|
+
const min = value - variance;
|
2113
|
+
const max = value + variance;
|
2114
|
+
return Math.random() * (max - min) + min;
|
2115
|
+
};
|
2116
|
+
this.characterVelocity.x = 0;
|
2066
2117
|
this.characterVelocity.y = 0;
|
2067
|
-
this.
|
2118
|
+
this.characterVelocity.z = 0;
|
2119
|
+
this.config.character.position.set(
|
2120
|
+
randomWithVariance(
|
2121
|
+
this.config.spawnConfiguration.spawnPosition.x,
|
2122
|
+
this.config.spawnConfiguration.spawnPositionVariance.x
|
2123
|
+
),
|
2124
|
+
randomWithVariance(
|
2125
|
+
this.config.spawnConfiguration.spawnPosition.y,
|
2126
|
+
this.config.spawnConfiguration.spawnPositionVariance.y
|
2127
|
+
),
|
2128
|
+
randomWithVariance(
|
2129
|
+
this.config.spawnConfiguration.spawnPosition.z,
|
2130
|
+
this.config.spawnConfiguration.spawnPositionVariance.z
|
2131
|
+
)
|
2132
|
+
);
|
2133
|
+
const respawnRotation = new Euler(
|
2134
|
+
0,
|
2135
|
+
-this.config.spawnConfiguration.spawnYRotation * (Math.PI / 180),
|
2136
|
+
0
|
2137
|
+
);
|
2138
|
+
this.config.character.rotation.set(respawnRotation.x, respawnRotation.y, respawnRotation.z);
|
2068
2139
|
this.characterOnGround = false;
|
2069
2140
|
this.doubleJumpUsed = false;
|
2070
2141
|
this.jumpReleased = true;
|
@@ -2102,8 +2173,13 @@ var RemoteController = class {
|
|
2102
2173
|
}
|
2103
2174
|
updateFromNetwork(clientUpdate) {
|
2104
2175
|
const { position, rotation, state } = clientUpdate;
|
2105
|
-
this.config.character.position.
|
2106
|
-
|
2176
|
+
const distanceSquared = this.config.character.position.distanceToSquared(position);
|
2177
|
+
if (distanceSquared > 5 * 5) {
|
2178
|
+
this.config.character.position.copy(position);
|
2179
|
+
} else {
|
2180
|
+
this.config.character.position.lerp(new Vector37(position.x, position.y, position.z), 0.15);
|
2181
|
+
}
|
2182
|
+
const rotationQuaternion = tempQuaternion.set(0, rotation.quaternionY, 0, rotation.quaternionW);
|
2107
2183
|
this.config.character.quaternion.slerp(rotationQuaternion, 0.6);
|
2108
2184
|
if (state !== this.currentAnimation) {
|
2109
2185
|
this.currentAnimation = state;
|
@@ -2183,13 +2259,40 @@ var CharacterManager = class {
|
|
2183
2259
|
keyInputManager: this.config.keyInputManager,
|
2184
2260
|
virtualJoystick: this.config.virtualJoystick,
|
2185
2261
|
cameraManager: this.config.cameraManager,
|
2186
|
-
timeManager: this.config.timeManager
|
2262
|
+
timeManager: this.config.timeManager,
|
2263
|
+
spawnConfiguration: this.config.spawnConfiguration
|
2187
2264
|
});
|
2188
2265
|
this.localCharacter.position.set(spawnPosition.x, spawnPosition.y, spawnPosition.z);
|
2189
2266
|
this.localCharacter.rotation.set(spawnRotation.x, spawnRotation.y, spawnRotation.z);
|
2190
2267
|
this.group.add(character);
|
2191
2268
|
this.localCharacterSpawned = true;
|
2192
2269
|
}
|
2270
|
+
createRespawnButton() {
|
2271
|
+
const respawnButton = document.createElement("div");
|
2272
|
+
respawnButton.className = "respawn-button";
|
2273
|
+
respawnButton.textContent = "RESPAWN";
|
2274
|
+
respawnButton.addEventListener("click", () => {
|
2275
|
+
this.localController.resetPosition();
|
2276
|
+
});
|
2277
|
+
respawnButton.style.position = "absolute";
|
2278
|
+
respawnButton.style.top = "14px";
|
2279
|
+
respawnButton.style.left = "8px";
|
2280
|
+
respawnButton.style.zIndex = "102";
|
2281
|
+
respawnButton.style.backgroundColor = "rgba(0, 0, 0, 0.7)";
|
2282
|
+
respawnButton.style.color = "#ffffff";
|
2283
|
+
respawnButton.style.borderRadius = "8px";
|
2284
|
+
respawnButton.style.border = "1px solid rgba(255, 255, 255, 0.21)";
|
2285
|
+
respawnButton.style.height = "22px";
|
2286
|
+
respawnButton.style.padding = "8px";
|
2287
|
+
respawnButton.style.cursor = "pointer";
|
2288
|
+
respawnButton.style.fontSize = "12px";
|
2289
|
+
respawnButton.style.fontFamily = "Helvetica, sans-serif";
|
2290
|
+
respawnButton.style.userSelect = "none";
|
2291
|
+
respawnButton.style.display = "flex";
|
2292
|
+
respawnButton.style.alignItems = "center";
|
2293
|
+
respawnButton.style.justifyContent = "center";
|
2294
|
+
return respawnButton;
|
2295
|
+
}
|
2193
2296
|
setupTweakPane(tweakPane) {
|
2194
2297
|
tweakPane.setupCharacterController(this.localController);
|
2195
2298
|
}
|