@worldmesh/runtime 0.2.1 → 0.2.3
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/README.md +48 -8
- package/dist/audio/footsteps.d.ts +37 -0
- package/dist/audio/footsteps.d.ts.map +1 -0
- package/dist/audio/footsteps.js +178 -0
- package/dist/audio/footsteps.js.map +1 -0
- package/dist/avatar/descriptor.d.ts +15 -0
- package/dist/avatar/descriptor.d.ts.map +1 -1
- package/dist/avatar/descriptor.js +19 -0
- package/dist/avatar/descriptor.js.map +1 -1
- package/dist/avatar/loader.d.ts +12 -1
- package/dist/avatar/loader.d.ts.map +1 -1
- package/dist/avatar/loader.js +16 -1
- package/dist/avatar/loader.js.map +1 -1
- package/dist/avatar/share.d.ts +30 -0
- package/dist/avatar/share.d.ts.map +1 -0
- package/dist/avatar/share.js +203 -0
- package/dist/avatar/share.js.map +1 -0
- package/dist/camera/cameraRig.d.ts +4 -0
- package/dist/camera/cameraRig.d.ts.map +1 -1
- package/dist/camera/cameraRig.js +10 -1
- package/dist/camera/cameraRig.js.map +1 -1
- package/dist/camera/viewHandoff.d.ts +20 -0
- package/dist/camera/viewHandoff.d.ts.map +1 -0
- package/dist/camera/viewHandoff.js +64 -0
- package/dist/camera/viewHandoff.js.map +1 -0
- package/dist/controls/input.d.ts +29 -0
- package/dist/controls/input.d.ts.map +1 -1
- package/dist/controls/input.js +124 -1
- package/dist/controls/input.js.map +1 -1
- package/dist/controls/touch.d.ts +10 -0
- package/dist/controls/touch.d.ts.map +1 -1
- package/dist/controls/touch.js +57 -1
- package/dist/controls/touch.js.map +1 -1
- package/dist/core/worldmesh.d.ts +9 -0
- package/dist/core/worldmesh.d.ts.map +1 -1
- package/dist/core/worldmesh.js +498 -26
- package/dist/core/worldmesh.js.map +1 -1
- package/dist/hosted.d.ts +3 -0
- package/dist/hosted.d.ts.map +1 -0
- package/dist/hosted.js +5 -0
- package/dist/hosted.js.map +1 -0
- package/dist/index.d.ts +16 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -7
- package/dist/index.js.map +1 -1
- package/dist/load.d.ts +23 -0
- package/dist/load.d.ts.map +1 -0
- package/dist/load.js +83 -0
- package/dist/load.js.map +1 -0
- package/dist/net/follow.d.ts +7 -0
- package/dist/net/follow.d.ts.map +1 -0
- package/dist/net/follow.js +10 -0
- package/dist/net/follow.js.map +1 -0
- package/dist/net/presence.d.ts +125 -3
- package/dist/net/presence.d.ts.map +1 -1
- package/dist/net/presence.js +471 -24
- package/dist/net/presence.js.map +1 -1
- package/dist/net/roomFull.d.ts +44 -0
- package/dist/net/roomFull.d.ts.map +1 -0
- package/dist/net/roomFull.js +147 -0
- package/dist/net/roomFull.js.map +1 -0
- package/dist/player/avatar.d.ts +17 -4
- package/dist/player/avatar.d.ts.map +1 -1
- package/dist/player/avatar.js +85 -18
- package/dist/player/avatar.js.map +1 -1
- package/dist/player/player.d.ts +6 -2
- package/dist/player/player.d.ts.map +1 -1
- package/dist/player/player.js +13 -3
- package/dist/player/player.js.map +1 -1
- package/dist/player/stroke.d.ts +11 -0
- package/dist/player/stroke.d.ts.map +1 -0
- package/dist/player/stroke.js +96 -0
- package/dist/player/stroke.js.map +1 -0
- package/dist/portals/portals.d.ts +1 -1
- package/dist/portals/portals.d.ts.map +1 -1
- package/dist/portals/portals.js +6 -2
- package/dist/portals/portals.js.map +1 -1
- package/dist/types.d.ts +53 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/overlay.d.ts +18 -0
- package/dist/ui/overlay.d.ts.map +1 -1
- package/dist/ui/overlay.js +166 -1
- package/dist/ui/overlay.js.map +1 -1
- package/dist/version.d.ts +4 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +4 -0
- package/dist/version.js.map +1 -0
- package/dist/xr/session.d.ts +13 -0
- package/dist/xr/session.d.ts.map +1 -0
- package/dist/xr/session.js +33 -0
- package/dist/xr/session.js.map +1 -0
- package/package.json +1 -1
- package/src/audio/footsteps.ts +185 -0
- package/src/avatar/descriptor.ts +28 -0
- package/src/avatar/loader.ts +19 -2
- package/src/avatar/share.ts +196 -0
- package/src/camera/cameraRig.ts +10 -1
- package/src/camera/viewHandoff.ts +67 -0
- package/src/controls/input.ts +119 -1
- package/src/controls/touch.ts +59 -1
- package/src/core/worldmesh.ts +495 -25
- package/src/hosted.ts +4 -0
- package/src/index.ts +16 -9
- package/src/load.ts +103 -0
- package/src/net/follow.ts +9 -0
- package/src/net/presence.ts +547 -27
- package/src/net/roomFull.ts +160 -0
- package/src/player/avatar.ts +87 -18
- package/src/player/player.ts +13 -4
- package/src/player/stroke.ts +93 -0
- package/src/portals/portals.ts +5 -2
- package/src/types.ts +52 -9
- package/src/ui/overlay.ts +171 -1
- package/src/version.ts +3 -0
- package/src/xr/session.ts +33 -0
package/src/hosted.ts
ADDED
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { createWorldMesh } from './core/worldmesh.js';
|
|
1
|
+
export { DOORWAY_VIEW_PARAM, createWorldMesh } from './core/worldmesh.js';
|
|
2
2
|
export { Emitter } from './core/events.js';
|
|
3
3
|
export { Input } from './controls/input.js';
|
|
4
4
|
export { TouchControls, isTouchDevice } from './controls/touch.js';
|
|
@@ -7,6 +7,7 @@ export { DEFAULT_ABILITIES, resolveAbilities } from './abilities/abilities.js';
|
|
|
7
7
|
export { CollisionWorld } from './movement/collision.js';
|
|
8
8
|
export { DEFAULT_TUNING, MovementController } from './movement/controller.js';
|
|
9
9
|
export { CameraRig } from './camera/cameraRig.js';
|
|
10
|
+
export { VIEW_PARAM, VIEW_STORAGE_KEY, getRememberedView, rememberView, takeViewHandoff, withView } from './camera/viewHandoff.js';
|
|
10
11
|
export { Player } from './player/player.js';
|
|
11
12
|
export {
|
|
12
13
|
AVATAR_EXPRESSIONS,
|
|
@@ -20,9 +21,10 @@ export {
|
|
|
20
21
|
setAvatarColor,
|
|
21
22
|
} from './player/avatar.js';
|
|
22
23
|
export type { AvatarExpression, AvatarMotion } from './player/avatar.js';
|
|
24
|
+
export { isStrokeMaterial, setFigureStroke, setStrokeOpacity } from './player/stroke.js';
|
|
23
25
|
export { PortalManager, buildTravelUrl, getReferringWorld } from './portals/portals.js';
|
|
24
|
-
export { isLoadableUrl, parseAvatarDescriptor } from './avatar/descriptor.js';
|
|
25
|
-
export type { AvatarDescriptor, AvatarFormat } from './avatar/descriptor.js';
|
|
26
|
+
export { isLoadableUrl, parseAvatarDescriptor, parseAvatarShare } from './avatar/descriptor.js';
|
|
27
|
+
export type { AvatarDescriptor, AvatarFormat, SignedAvatarShare } from './avatar/descriptor.js';
|
|
26
28
|
export {
|
|
27
29
|
AVATAR_TICKET_PARAM,
|
|
28
30
|
AVATAR_TICKET_STORAGE_KEY,
|
|
@@ -32,16 +34,21 @@ export {
|
|
|
32
34
|
takeAvatarTicket,
|
|
33
35
|
withAvatarTicket,
|
|
34
36
|
} from './avatar/handoff.js';
|
|
35
|
-
export { loadAvatarModel } from './avatar/loader.js';
|
|
37
|
+
export { downloadAvatarModel, loadAvatarModel } from './avatar/loader.js';
|
|
36
38
|
export type { LoadAvatarOptions, LoadedAvatar } from './avatar/loader.js';
|
|
37
39
|
export { Overlay } from './ui/overlay.js';
|
|
40
|
+
export { immersiveVrSupported, requestImmersiveVr, IMMERSIVE_VR } from './xr/session.js';
|
|
38
41
|
export { deserializePlayerState, serializePlayerState } from './net/adapter.js';
|
|
39
|
-
export { DEFAULT_PRESENCE_SERVER, Presence } from './net/presence.js';
|
|
40
|
-
export
|
|
42
|
+
export { DEFAULT_PRESENCE_SERVER, Presence, createNameTag, createSpeechBubble } from './net/presence.js';
|
|
43
|
+
export { easeYaw } from './net/follow.js';
|
|
44
|
+
export type { PresenceOptions, SharedAvatar } from './net/presence.js';
|
|
45
|
+
export { SharedAvatarLink, createShareVerifier, shareableAvatar } from './avatar/share.js';
|
|
46
|
+
export { isOverAllowanceSignal, isRoomFullSignal, occupancyIsFull, occupancyProbeUrl, probeRoom, probeRoomFull, roomFullLabel } from './net/roomFull.js';
|
|
47
|
+
export type { RoomProbe } from './net/roomFull.js';
|
|
41
48
|
|
|
42
|
-
export
|
|
43
|
-
|
|
44
|
-
export
|
|
49
|
+
export { WORLDMESH_PROTOCOL, WORLDMESH_VERSION } from './version.js';
|
|
50
|
+
export { HOSTED_RUNTIME_URL, loadWorldMesh } from './load.js';
|
|
51
|
+
export type { LoadWorldMeshOptions } from './load.js';
|
|
45
52
|
|
|
46
53
|
export type {
|
|
47
54
|
Abilities,
|
package/src/load.ts
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import type { WorldMeshHandle, WorldMeshOptions } from './types.js';
|
|
3
|
+
import { WORLDMESH_PROTOCOL, WORLDMESH_VERSION } from './version.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The current runtime for this protocol, served by WorldMesh
|
|
7
|
+
* (scripts/build-hosted.mjs). `loadWorldMesh` runs it, so a fix reaches a
|
|
8
|
+
* world the next time it is opened, without the world rebuilding.
|
|
9
|
+
*/
|
|
10
|
+
export const HOSTED_RUNTIME_URL = `https://worldmesh.net/runtime/${WORLDMESH_PROTOCOL}/index.js`;
|
|
11
|
+
|
|
12
|
+
/** Where the hosted runtime picks up the world's own Three.js (scripts/build-hosted.mjs). */
|
|
13
|
+
const THREE_KEY = Symbol.for('worldmesh.three');
|
|
14
|
+
const DEFAULT_TIMEOUT_MS = 8000;
|
|
15
|
+
/**
|
|
16
|
+
* The runtime is asked for at a new URL this often, which bounds how long a
|
|
17
|
+
* browser keeps an old one. Cache headers can't: worldmesh.net's Browser
|
|
18
|
+
* Cache TTL stretches any shorter max-age on a .js file to 4 hours.
|
|
19
|
+
*/
|
|
20
|
+
const REFRESH_MS = 5 * 60_000;
|
|
21
|
+
|
|
22
|
+
export interface LoadWorldMeshOptions {
|
|
23
|
+
/** Run the runtime from here instead: a preview or a self-hosted copy. */
|
|
24
|
+
url?: string;
|
|
25
|
+
/** Give up on it after this many milliseconds and use the bundled copy. Default 8000. */
|
|
26
|
+
timeoutMs?: number;
|
|
27
|
+
/** false: always use the copy bundled with the world, as `createWorldMesh` does. */
|
|
28
|
+
hosted?: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** What the hosted runtime exports (src/hosted.ts). */
|
|
32
|
+
interface HostedRuntime {
|
|
33
|
+
createWorldMesh(options: WorldMeshOptions): WorldMeshHandle;
|
|
34
|
+
WORLDMESH_PROTOCOL: number;
|
|
35
|
+
WORLDMESH_VERSION: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const loading = new Map<string, Promise<HostedRuntime | null>>();
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* `createWorldMesh`, kept current: runs the latest runtime WorldMesh serves for
|
|
42
|
+
* this protocol, with the world's own Three.js. If that cannot be loaded in
|
|
43
|
+
* time, or does not start, the copy bundled with the world runs instead, so
|
|
44
|
+
* the world works as it did when it was built.
|
|
45
|
+
*/
|
|
46
|
+
export async function loadWorldMesh(options: WorldMeshOptions, load: LoadWorldMeshOptions = {}): Promise<WorldMeshHandle> {
|
|
47
|
+
const useHosted = load.hosted !== false && typeof window !== 'undefined';
|
|
48
|
+
const hosted = useHosted ? await hostedRuntime(load.url ?? HOSTED_RUNTIME_URL, load.timeoutMs ?? DEFAULT_TIMEOUT_MS) : null;
|
|
49
|
+
if (hosted) {
|
|
50
|
+
try {
|
|
51
|
+
return hosted.createWorldMesh(options);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.warn(`[WorldMesh] Runtime ${hosted.WORLDMESH_VERSION} did not start; using the copy bundled with this world (${WORLDMESH_VERSION}).`, error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const { createWorldMesh } = await import('./core/worldmesh.js');
|
|
57
|
+
return createWorldMesh(options);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function hostedRuntime(url: string, timeoutMs: number): Promise<HostedRuntime | null> {
|
|
61
|
+
let pending = loading.get(url);
|
|
62
|
+
if (!pending) {
|
|
63
|
+
pending = importHosted(url, timeoutMs);
|
|
64
|
+
loading.set(url, pending);
|
|
65
|
+
}
|
|
66
|
+
return pending;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function importHosted(url: string, timeoutMs: number): Promise<HostedRuntime | null> {
|
|
70
|
+
const shared = globalThis as unknown as Record<symbol, unknown>;
|
|
71
|
+
shared[THREE_KEY] ??= THREE;
|
|
72
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
73
|
+
const timeout = new Promise<null>((resolve) => {
|
|
74
|
+
timer = setTimeout(() => resolve(null), timeoutMs);
|
|
75
|
+
});
|
|
76
|
+
const fallback = `using the copy bundled with this world (${WORLDMESH_VERSION})`;
|
|
77
|
+
try {
|
|
78
|
+
// Left to the browser: bundlers must not try to resolve or inline it.
|
|
79
|
+
const imported = import(/* webpackIgnore: true */ /* @vite-ignore */ refreshed(url)) as Promise<HostedRuntime>;
|
|
80
|
+
const runtime = await Promise.race([imported, timeout]);
|
|
81
|
+
if (!runtime) {
|
|
82
|
+
console.info(`[WorldMesh] ${url} took longer than ${timeoutMs} ms; ${fallback}.`);
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
if (runtime.WORLDMESH_PROTOCOL !== WORLDMESH_PROTOCOL || typeof runtime.createWorldMesh !== 'function') {
|
|
86
|
+
console.warn(`[WorldMesh] ${url} is not a protocol ${WORLDMESH_PROTOCOL} runtime; ${fallback}.`);
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
return runtime;
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.info(`[WorldMesh] Could not load ${url}; ${fallback}.`, error);
|
|
92
|
+
return null;
|
|
93
|
+
} finally {
|
|
94
|
+
clearTimeout(timer);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** `url` with `v` set to the current REFRESH_MS slot, e.g. `…/index.js?v=5867331`. */
|
|
99
|
+
function refreshed(url: string): string {
|
|
100
|
+
const fresh = new URL(url, globalThis.location?.href);
|
|
101
|
+
fresh.searchParams.set('v', String(Math.floor(Date.now() / REFRESH_MS)));
|
|
102
|
+
return fresh.href;
|
|
103
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turn `yaw` toward `target` by `blend` (0 to 1) of the way, the short way
|
|
3
|
+
* round. Radians; the result is not wrapped. Remote figures ease toward the
|
|
4
|
+
* facing their owner last reported with this.
|
|
5
|
+
*/
|
|
6
|
+
export function easeYaw(yaw: number, target: number, blend: number): number {
|
|
7
|
+
const delta = Math.atan2(Math.sin(target - yaw), Math.cos(target - yaw));
|
|
8
|
+
return yaw + delta * blend;
|
|
9
|
+
}
|