@sadhaka/loom-engine 0.11.0 → 0.13.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.
Files changed (51) hide show
  1. package/COMMERCIAL_LICENSE_TERMS.md +74 -0
  2. package/README.md +230 -6
  3. package/dist/components/peer-sprite.d.ts +25 -0
  4. package/dist/components/peer-sprite.d.ts.map +1 -0
  5. package/dist/components/peer-sprite.js +48 -0
  6. package/dist/components/peer-sprite.js.map +1 -0
  7. package/dist/engine.d.ts +6 -1
  8. package/dist/engine.d.ts.map +1 -1
  9. package/dist/engine.js +35 -1
  10. package/dist/engine.js.map +1 -1
  11. package/dist/index.d.ts +19 -3
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +17 -2
  14. package/dist/index.js.map +1 -1
  15. package/dist/network/mock-multiplayer-bridge.d.ts +34 -0
  16. package/dist/network/mock-multiplayer-bridge.d.ts.map +1 -0
  17. package/dist/network/mock-multiplayer-bridge.js +91 -0
  18. package/dist/network/mock-multiplayer-bridge.js.map +1 -0
  19. package/dist/network/multiplayer-bridge.d.ts +45 -0
  20. package/dist/network/multiplayer-bridge.d.ts.map +1 -0
  21. package/dist/network/multiplayer-bridge.js +34 -0
  22. package/dist/network/multiplayer-bridge.js.map +1 -0
  23. package/dist/network/peer-pool.d.ts +46 -0
  24. package/dist/network/peer-pool.d.ts.map +1 -0
  25. package/dist/network/peer-pool.js +185 -0
  26. package/dist/network/peer-pool.js.map +1 -0
  27. package/dist/network/sse-multiplayer-bridge.d.ts +36 -0
  28. package/dist/network/sse-multiplayer-bridge.d.ts.map +1 -0
  29. package/dist/network/sse-multiplayer-bridge.js +264 -0
  30. package/dist/network/sse-multiplayer-bridge.js.map +1 -0
  31. package/dist/renderer/shaders/sprite-shader-source.d.ts +4 -0
  32. package/dist/renderer/shaders/sprite-shader-source.d.ts.map +1 -0
  33. package/dist/renderer/shaders/sprite-shader-source.js +83 -0
  34. package/dist/renderer/shaders/sprite-shader-source.js.map +1 -0
  35. package/dist/renderer/sprite-batcher.d.ts +30 -0
  36. package/dist/renderer/sprite-batcher.d.ts.map +1 -0
  37. package/dist/renderer/sprite-batcher.js +146 -0
  38. package/dist/renderer/sprite-batcher.js.map +1 -0
  39. package/dist/renderer/texture-atlas.d.ts +24 -0
  40. package/dist/renderer/texture-atlas.d.ts.map +1 -0
  41. package/dist/renderer/texture-atlas.js +173 -0
  42. package/dist/renderer/texture-atlas.js.map +1 -0
  43. package/dist/renderer/webgl2-device.d.ts +53 -0
  44. package/dist/renderer/webgl2-device.d.ts.map +1 -0
  45. package/dist/renderer/webgl2-device.js +596 -0
  46. package/dist/renderer/webgl2-device.js.map +1 -0
  47. package/dist/systems/peer-presence-system.d.ts +19 -0
  48. package/dist/systems/peer-presence-system.d.ts.map +1 -0
  49. package/dist/systems/peer-presence-system.js +118 -0
  50. package/dist/systems/peer-presence-system.js.map +1 -0
  51. package/package.json +11 -5
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@
8
8
  // the previous suffix `-perf-9-1` lingered after package.json was
9
9
  // bumped to 0.10.0, surfacing as a drift bug in
10
10
  // engine.LOOM_ENGINE_VERSION-based diagnostics.
11
- export const LOOM_ENGINE_VERSION = '0.11.0';
11
+ export const LOOM_ENGINE_VERSION = '0.13.0';
12
12
  export { vec2, vec3, rect, clamp, lerp, smoothstep, approxEq, rectContains, rectIntersects, visibleInView, } from './util/math.js';
13
13
  export { rgba, hexToRgba, rgbaToHexString, rgbaToCssString, colorLerp, COLOR_WHITE, COLOR_BLACK, COLOR_TRANSPARENT, COLOR_KNOT_STR, COLOR_KNOT_DEX, COLOR_KNOT_INT, COLOR_KNOT_CENTER, } from './util/color.js';
14
14
  export { EntityAllocator, NULL_ENTITY, entityIndex, entityGeneration, makeEntity, } from './entity.js';
@@ -21,9 +21,18 @@ export { ResourceRegistry, createTimeResource, createVeilBudgetResource, RESOURC
21
21
  // Default systems
22
22
  export { SpriteRenderSystem } from './systems/sprite-render-system.js';
23
23
  // Engine facade
24
- export { Engine } from './engine.js';
24
+ export { Engine, registerBackend, isBackendRegistered } from './engine.js';
25
25
  export { createCamera, getCameraViewRect, worldToScreen, screenToWorld, } from './renderer/camera.js';
26
26
  export { Canvas2DDevice, } from './renderer/canvas2d-device.js';
27
+ // WebGL2 backend (Phase 14.1). Importing this symbol triggers the
28
+ // module's self-registration of the 'webgl2' backend factory, so
29
+ // Engine.create({ backend: 'webgl2' }) starts working from then on.
30
+ // Canvas2D-only consumers do not import this and the entire WebGL2
31
+ // path tree-shakes out of the bundle.
32
+ export { WebGL2Device } from './renderer/webgl2-device.js';
33
+ export { TextureAtlas, makeParticleDiscAtlas, } from './renderer/texture-atlas.js';
34
+ export { SpriteBatcher, FLOATS_PER_INSTANCE, } from './renderer/sprite-batcher.js';
35
+ export { SPRITE_VERT_SRC, SPRITE_FRAG_SRC, UNIT_QUAD_VERTICES, } from './renderer/shaders/sprite-shader-source.js';
27
36
  export { ISO_TILE_WIDTH, ISO_TILE_HEIGHT, ISO_HALF_W, ISO_HALF_H, ISO_Z_SCALE, tileToIso, worldToIso, isoToTile, isoDepthKey, } from './renderer/iso-projection.js';
28
37
  export { loadSpriteSheet, computeFrameIndex, SpriteSheetLoadError, } from './asset/sprite-sheet-loader.js';
29
38
  export { synthesizeDefaultClip, clipDurationMs, frameInClipAt, manifestFrameIndex, } from './animation/animation-clip.js';
@@ -66,4 +75,10 @@ export { createZoneState, beginTransition, tickTransition, isTransitioning, RESO
66
75
  export { ZONE_CATALOG } from './zone/zone-catalog.js';
67
76
  export { InteractablePool, POOL_INTERACTABLE, INTERACTABLE_FLAG_ACTIVE, } from './components/interactable.js';
68
77
  export { InteractionSystem, createLastInteraction, RESOURCE_LAST_INTERACTION, } from './systems/interaction-system.js';
78
+ export { RESOURCE_MULTIPLAYER_BRIDGE, RESOURCE_PEER_POOL, BROADCAST_HZ, BROADCAST_MIN_INTERVAL_MS, } from './network/multiplayer-bridge.js';
79
+ export { PeerPool } from './network/peer-pool.js';
80
+ export { MockMultiplayerBridge } from './network/mock-multiplayer-bridge.js';
81
+ export { SSEMultiplayerBridge } from './network/sse-multiplayer-bridge.js';
82
+ export { PeerSpritePool, POOL_PEER_SPRITE } from './components/peer-sprite.js';
83
+ export { PeerPresenceSystem, PeerRenderSystem, } from './systems/peer-presence-system.js';
69
84
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { type IMultiplayerBridge, type MultiplayerBridgeStatus, type MultiplayerBridgeStats, type PresenceMessage } from './multiplayer-bridge.js';
2
+ export interface MockMultiplayerBridgeOptions {
3
+ nowMs?: () => number;
4
+ }
5
+ interface SentBroadcast {
6
+ x: number;
7
+ y: number;
8
+ zone: string;
9
+ tsMs: number;
10
+ sentAtMs: number;
11
+ }
12
+ export declare class MockMultiplayerBridge implements IMultiplayerBridge {
13
+ private queue;
14
+ private statusValue;
15
+ private statsValue;
16
+ private readonly nowMs;
17
+ private lastBroadcastMs;
18
+ private sentBroadcasts;
19
+ constructor(opts?: MockMultiplayerBridgeOptions);
20
+ connect(): void;
21
+ disconnect(): void;
22
+ status(): MultiplayerBridgeStatus;
23
+ pollMessages(): PresenceMessage[];
24
+ broadcastPosition(x: number, y: number, zone: string, tsMs: number): void;
25
+ stats(): Readonly<MultiplayerBridgeStats>;
26
+ enqueueIncoming(msg: PresenceMessage): void;
27
+ enqueueIncomingAll(msgs: ReadonlyArray<PresenceMessage>): void;
28
+ getSentBroadcasts(): ReadonlyArray<Readonly<SentBroadcast>>;
29
+ pendingIncoming(): number;
30
+ resetRateLimit(): void;
31
+ getLastBroadcastMs(): number;
32
+ }
33
+ export {};
34
+ //# sourceMappingURL=mock-multiplayer-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-multiplayer-bridge.d.ts","sourceRoot":"","sources":["../../src/network/mock-multiplayer-bridge.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,eAAe,EAErB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,4BAA4B;IAI3C,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;CACtB;AAED,UAAU,aAAa;IACrB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IAIb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,qBAAsB,YAAW,kBAAkB;IAC9D,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,UAAU,CAKhB;IACF,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,cAAc,CAAuB;gBAEjC,IAAI,GAAE,4BAAiC;IAInD,OAAO,IAAI,IAAI;IAKf,UAAU,IAAI,IAAI;IAIlB,MAAM,IAAI,uBAAuB;IAIjC,YAAY,IAAI,eAAe,EAAE;IAOjC,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAWzE,KAAK,IAAI,QAAQ,CAAC,sBAAsB,CAAC;IAOzC,eAAe,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI;IAK3C,kBAAkB,CAAC,IAAI,EAAE,aAAa,CAAC,eAAe,CAAC,GAAG,IAAI;IAS9D,iBAAiB,IAAI,aAAa,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IAK3D,eAAe,IAAI,MAAM;IAMzB,cAAc,IAAI,IAAI;IAKtB,kBAAkB,IAAI,MAAM;CAG7B"}
@@ -0,0 +1,91 @@
1
+ // MockMultiplayerBridge - in-memory presence transport for tests +
2
+ // offline demos.
3
+ //
4
+ // Tests inject incoming presence frames via enqueueIncoming() and let
5
+ // PeerPresenceSystem drain them. broadcastPosition() captures local
6
+ // sends in a getSentBroadcasts() buffer so tests can assert on them.
7
+ // pollMessages() drains the inbound queue in FIFO order.
8
+ //
9
+ // Rate-limiting: shared with the SSE bridge via BROADCAST_MIN_INTERVAL_MS.
10
+ // A nowMs() injection point lets tests fast-forward time without
11
+ // touching the real clock.
12
+ import { BROADCAST_MIN_INTERVAL_MS, } from './multiplayer-bridge.js';
13
+ export class MockMultiplayerBridge {
14
+ queue = [];
15
+ statusValue = 'idle';
16
+ statsValue = {
17
+ messagesReceived: 0,
18
+ messagesSent: 0,
19
+ rateLimitedDrops: 0,
20
+ reconnects: 0,
21
+ };
22
+ nowMs;
23
+ lastBroadcastMs = -Infinity;
24
+ sentBroadcasts = [];
25
+ constructor(opts = {}) {
26
+ this.nowMs = opts.nowMs ?? (() => (typeof performance !== 'undefined' ? performance.now() : Date.now()));
27
+ }
28
+ connect() {
29
+ if (this.statusValue === 'connected')
30
+ return;
31
+ this.statusValue = 'connected';
32
+ }
33
+ disconnect() {
34
+ this.statusValue = 'closed';
35
+ }
36
+ status() {
37
+ return this.statusValue;
38
+ }
39
+ pollMessages() {
40
+ if (this.queue.length === 0)
41
+ return [];
42
+ const out = this.queue;
43
+ this.queue = [];
44
+ return out;
45
+ }
46
+ broadcastPosition(x, y, zone, tsMs) {
47
+ const now = this.nowMs();
48
+ if (now - this.lastBroadcastMs < BROADCAST_MIN_INTERVAL_MS) {
49
+ this.statsValue.rateLimitedDrops++;
50
+ return;
51
+ }
52
+ this.lastBroadcastMs = now;
53
+ this.sentBroadcasts.push({ x, y, zone, tsMs, sentAtMs: now });
54
+ this.statsValue.messagesSent++;
55
+ }
56
+ stats() {
57
+ return this.statsValue;
58
+ }
59
+ // ----- Mock-only injection helpers -----
60
+ // Enqueue an inbound presence message as if it came from the server.
61
+ enqueueIncoming(msg) {
62
+ this.queue.push(msg);
63
+ this.statsValue.messagesReceived++;
64
+ }
65
+ enqueueIncomingAll(msgs) {
66
+ for (let i = 0; i < msgs.length; i++) {
67
+ const m = msgs[i];
68
+ if (m)
69
+ this.enqueueIncoming(m);
70
+ }
71
+ }
72
+ // Tests inspect what broadcastPosition let through. Returns the
73
+ // backing array; the caller may copy if they need a snapshot.
74
+ getSentBroadcasts() {
75
+ return this.sentBroadcasts;
76
+ }
77
+ // Convenience: how many inbound messages are waiting for a poll.
78
+ pendingIncoming() {
79
+ return this.queue.length;
80
+ }
81
+ // Reset rate-limiter state. Useful in tests that simulate a
82
+ // reconnect or want a clean slate.
83
+ resetRateLimit() {
84
+ this.lastBroadcastMs = -Infinity;
85
+ }
86
+ // Inspect-only: when did broadcastPosition last send (in nowMs() units).
87
+ getLastBroadcastMs() {
88
+ return this.lastBroadcastMs;
89
+ }
90
+ }
91
+ //# sourceMappingURL=mock-multiplayer-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-multiplayer-bridge.js","sourceRoot":"","sources":["../../src/network/mock-multiplayer-bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ export type MultiplayerBridgeStatus = 'idle' | 'connecting' | 'connected' | 'reconnecting' | 'closed';
2
+ export interface MultiplayerBridgeStats {
3
+ messagesReceived: number;
4
+ messagesSent: number;
5
+ rateLimitedDrops: number;
6
+ reconnects: number;
7
+ }
8
+ export interface PresenceUpdate {
9
+ kind: 'update';
10
+ characterId: string;
11
+ x: number;
12
+ y: number;
13
+ zone: string;
14
+ tsMs: number;
15
+ name?: string;
16
+ }
17
+ export interface PresenceDepart {
18
+ kind: 'depart';
19
+ characterId: string;
20
+ }
21
+ export interface PresenceSnapshot {
22
+ kind: 'snapshot';
23
+ peers: ReadonlyArray<{
24
+ characterId: string;
25
+ x: number;
26
+ y: number;
27
+ zone: string;
28
+ tsMs: number;
29
+ name?: string;
30
+ }>;
31
+ }
32
+ export type PresenceMessage = PresenceUpdate | PresenceDepart | PresenceSnapshot;
33
+ export interface IMultiplayerBridge {
34
+ connect(): void;
35
+ disconnect(): void;
36
+ status(): MultiplayerBridgeStatus;
37
+ pollMessages(): PresenceMessage[];
38
+ broadcastPosition(x: number, y: number, zone: string, tsMs: number): void;
39
+ stats(): Readonly<MultiplayerBridgeStats>;
40
+ }
41
+ export declare const RESOURCE_MULTIPLAYER_BRIDGE = "multiplayer_bridge";
42
+ export declare const RESOURCE_PEER_POOL = "peer_pool";
43
+ export declare const BROADCAST_HZ = 10;
44
+ export declare const BROADCAST_MIN_INTERVAL_MS: number;
45
+ //# sourceMappingURL=multiplayer-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multiplayer-bridge.d.ts","sourceRoot":"","sources":["../../src/network/multiplayer-bridge.ts"],"names":[],"mappings":"AAyBA,MAAM,MAAM,uBAAuB,GAC/B,MAAM,GACN,YAAY,GACZ,WAAW,GACX,cAAc,GACd,QAAQ,CAAC;AAEb,MAAM,WAAW,sBAAsB;IAErC,gBAAgB,EAAE,MAAM,CAAC;IAGzB,YAAY,EAAE,MAAM,CAAC;IAGrB,gBAAgB,EAAE,MAAM,CAAC;IAEzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAKD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAGD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAID,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,aAAa,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;QACV,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;CACJ;AAED,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,cAAc,GAAG,gBAAgB,CAAC;AAEjF,MAAM,WAAW,kBAAkB;IAGjC,OAAO,IAAI,IAAI,CAAC;IAEhB,UAAU,IAAI,IAAI,CAAC;IACnB,MAAM,IAAI,uBAAuB,CAAC;IAGlC,YAAY,IAAI,eAAe,EAAE,CAAC;IAKlC,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1E,KAAK,IAAI,QAAQ,CAAC,sBAAsB,CAAC,CAAC;CAC3C;AAGD,eAAO,MAAM,2BAA2B,uBAAuB,CAAC;AAChE,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAM9C,eAAO,MAAM,YAAY,KAAK,CAAC;AAC/B,eAAO,MAAM,yBAAyB,QAAsB,CAAC"}
@@ -0,0 +1,34 @@
1
+ // MultiplayerBridge - abstraction over the presence transport.
2
+ //
3
+ // Concrete implementations:
4
+ // MockMultiplayerBridge - in-process transport for tests + offline
5
+ // dev. enqueueIncoming() simulates server
6
+ // pushes; broadcastPosition() captures local
7
+ // sends so tests can assert on them.
8
+ // SSEMultiplayerBridge - SSE-based implementation parallel to
9
+ // SSEDirectorBridge. Browser-only; throws in
10
+ // Node test runs.
11
+ //
12
+ // The PeerPresenceSystem (PHASE_INPUT) calls pollMessages() once per
13
+ // tick to drain queued presence updates, applies them to the PeerPool,
14
+ // and advances per-peer interpolation. Bridges buffer messages between
15
+ // polls so the system's per-tick read is bounded.
16
+ //
17
+ // Wire protocol (shared with the server-side Track B implementation):
18
+ // - Server emits SSE 'presence.update' { character_id, x, y, zone, ts_ms, name? }
19
+ // - Server emits SSE 'presence.depart' { character_id }
20
+ // - Server emits SSE 'presence.snapshot' { peers: [{ character_id, x, y, zone, ts_ms, name? }, ...] }
21
+ // - Client POSTs /presence/move { character_id, x, y, zone, ts_ms }
22
+ //
23
+ // The bridge layer hides transport details. PeerPresenceSystem and
24
+ // PeerPool deal only with strongly-typed PresenceMessage values.
25
+ // Resource keys.
26
+ export const RESOURCE_MULTIPLAYER_BRIDGE = 'multiplayer_bridge';
27
+ export const RESOURCE_PEER_POOL = 'peer_pool';
28
+ // Engine-side rate limit on broadcastPosition. The wire protocol
29
+ // targets 10 Hz; bridges enforce this regardless of how often the
30
+ // caller invokes broadcastPosition. Documented in the Multiplayer
31
+ // section of README.md.
32
+ export const BROADCAST_HZ = 10;
33
+ export const BROADCAST_MIN_INTERVAL_MS = 1000 / BROADCAST_HZ;
34
+ //# sourceMappingURL=multiplayer-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multiplayer-bridge.js","sourceRoot":"","sources":["../../src/network/multiplayer-bridge.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,EAAE;AACF,4BAA4B;AAC5B,qEAAqE;AACrE,oEAAoE;AACpE,uEAAuE;AACvE,+DAA+D;AAC/D,iEAAiE;AACjE,uEAAuE;AACvE,4CAA4C;AAC5C,EAAE;AACF,qEAAqE;AACrE,uEAAuE;AACvE,uEAAuE;AACvE,kDAAkD;AAClD,EAAE;AACF,sEAAsE;AACtE,sFAAsF;AACtF,4DAA4D;AAC5D,wGAAwG;AACxG,+EAA+E;AAC/E,EAAE;AACF,mEAAmE;AACnE,iEAAiE;AA2EjE,iBAAiB;AACjB,MAAM,CAAC,MAAM,2BAA2B,GAAG,oBAAoB,CAAC;AAChE,MAAM,CAAC,MAAM,kBAAkB,GAAG,WAAW,CAAC;AAE9C,iEAAiE;AACjE,kEAAkE;AAClE,kEAAkE;AAClE,wBAAwB;AACxB,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,CAAC;AAC/B,MAAM,CAAC,MAAM,yBAAyB,GAAG,IAAI,GAAG,YAAY,CAAC"}
@@ -0,0 +1,46 @@
1
+ export interface PeerEntry {
2
+ characterId: string;
3
+ zone: string;
4
+ name: string | null;
5
+ prevX: number;
6
+ prevY: number;
7
+ prevTsMs: number;
8
+ currentX: number;
9
+ currentY: number;
10
+ currentTsMs: number;
11
+ lastRenderedFrame: number;
12
+ }
13
+ export interface RenderedPeerView {
14
+ characterId: string;
15
+ x: number;
16
+ y: number;
17
+ zone: string;
18
+ name: string | null;
19
+ }
20
+ export declare class PeerPool {
21
+ private peers;
22
+ private localCharacterId;
23
+ private scratchView;
24
+ setLocalCharacterId(id: string | null): void;
25
+ getLocalCharacterId(): string | null;
26
+ upsert(characterId: string, x: number, y: number, zone: string, tsMs: number, name?: string): void;
27
+ applySnapshot(peers: ReadonlyArray<{
28
+ characterId: string;
29
+ x: number;
30
+ y: number;
31
+ zone: string;
32
+ tsMs: number;
33
+ name?: string;
34
+ }>): void;
35
+ remove(characterId: string): boolean;
36
+ has(characterId: string): boolean;
37
+ size(): number;
38
+ get(characterId: string): Readonly<PeerEntry> | undefined;
39
+ forEachRendered(nowMs: number, frame: number, fn: (view: Readonly<RenderedPeerView>) => void): void;
40
+ getRenderedPosition(characterId: string, nowMs: number): {
41
+ x: number;
42
+ y: number;
43
+ } | null;
44
+ clear(): void;
45
+ }
46
+ //# sourceMappingURL=peer-pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peer-pool.d.ts","sourceRoot":"","sources":["../../src/network/peer-pool.ts"],"names":[],"mappings":"AA2BA,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAGpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IAGpB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAMD,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAYD,qBAAa,QAAQ;IACnB,OAAO,CAAC,KAAK,CAAqC;IAClD,OAAO,CAAC,gBAAgB,CAAuB;IAI/C,OAAO,CAAC,WAAW,CAMjB;IAEF,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAO5C,mBAAmB,IAAI,MAAM,GAAG,IAAI;IASpC,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IA0ClG,aAAa,CACX,KAAK,EAAE,aAAa,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;QACV,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC,GACD,IAAI;IAwBP,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAIpC,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAIjC,IAAI,IAAI,MAAM;IAId,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,GAAG,SAAS;IAOzD,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,gBAAgB,CAAC,KAAK,IAAI,GAAG,IAAI;IAsBnG,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAcxF,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,185 @@
1
+ // PeerPool - tracks all known remote peers and their interpolated
2
+ // world position.
3
+ //
4
+ // Each peer keeps the last two known positions (prev, current) with
5
+ // timestamps. At frame time the system asks the pool for the
6
+ // interpolated (x, y) per peer, which is computed as
7
+ // factor = clamp01((nowMs - prevTsMs) / (currentTsMs - prevTsMs))
8
+ // x = lerp(prevX, currentX, factor)
9
+ // y = lerp(prevY, currentY, factor)
10
+ //
11
+ // When a new presence.update arrives, prev <- current, current <- new.
12
+ // The factor saturates at 1 once nowMs passes currentTsMs, so a peer
13
+ // who stops sending updates simply freezes at their last known
14
+ // position rather than extrapolating off into the distance.
15
+ //
16
+ // "Acceptable lag" per the phase 15.1 spec is ~150ms (one update
17
+ // interval at the 10Hz wire rate), which is imperceptible at
18
+ // walk-speed. No CRDT, no client-side prediction beyond the
19
+ // straight-line lerp - those are deferred until shared state extends
20
+ // past raw position.
21
+ //
22
+ // Self-filter: the local character's own character_id should NOT
23
+ // appear among the rendered peers (we don't render ourselves as a
24
+ // ghost). The PeerPresenceSystem owns this filter via
25
+ // setLocalCharacterId(); peers with that id are silently skipped on
26
+ // upsert and removed if already present.
27
+ function lerp(a, b, t) {
28
+ return a + (b - a) * t;
29
+ }
30
+ function clamp01(t) {
31
+ if (t < 0)
32
+ return 0;
33
+ if (t > 1)
34
+ return 1;
35
+ return t;
36
+ }
37
+ export class PeerPool {
38
+ peers = new Map();
39
+ localCharacterId = null;
40
+ // Reused on every getRenderedPosition / forEachRendered call so the
41
+ // hot per-frame path is allocation-free.
42
+ scratchView = {
43
+ characterId: '',
44
+ x: 0,
45
+ y: 0,
46
+ zone: '',
47
+ name: null,
48
+ };
49
+ setLocalCharacterId(id) {
50
+ this.localCharacterId = id;
51
+ if (id !== null && this.peers.has(id)) {
52
+ this.peers.delete(id);
53
+ }
54
+ }
55
+ getLocalCharacterId() {
56
+ return this.localCharacterId;
57
+ }
58
+ // Apply a new presence update for a peer. If the peer is the local
59
+ // character, the update is ignored (self-filter). If this is the
60
+ // first update for the peer, prev = current = the new position so
61
+ // the lerp factor immediately saturates and the peer renders at the
62
+ // sent position.
63
+ upsert(characterId, x, y, zone, tsMs, name) {
64
+ if (this.localCharacterId !== null && characterId === this.localCharacterId) {
65
+ return;
66
+ }
67
+ const existing = this.peers.get(characterId);
68
+ if (!existing) {
69
+ this.peers.set(characterId, {
70
+ characterId,
71
+ zone,
72
+ name: name ?? null,
73
+ prevX: x,
74
+ prevY: y,
75
+ prevTsMs: tsMs,
76
+ currentX: x,
77
+ currentY: y,
78
+ currentTsMs: tsMs,
79
+ lastRenderedFrame: -1,
80
+ });
81
+ return;
82
+ }
83
+ // Out-of-order: drop messages older than current. Wire protocol
84
+ // is monotonic per character_id, but reorder buffers + reconnect
85
+ // replays can deliver an older ts after a newer one.
86
+ if (tsMs < existing.currentTsMs) {
87
+ return;
88
+ }
89
+ existing.prevX = existing.currentX;
90
+ existing.prevY = existing.currentY;
91
+ existing.prevTsMs = existing.currentTsMs;
92
+ existing.currentX = x;
93
+ existing.currentY = y;
94
+ existing.currentTsMs = tsMs;
95
+ existing.zone = zone;
96
+ if (name !== undefined) {
97
+ existing.name = name;
98
+ }
99
+ }
100
+ // Replace the entire roster with a snapshot. Peers not present in
101
+ // the snapshot are dropped; peers in the snapshot but not yet
102
+ // tracked are inserted (with prev = current so they render at the
103
+ // sent position immediately).
104
+ applySnapshot(peers) {
105
+ const seen = new Set();
106
+ for (let i = 0; i < peers.length; i++) {
107
+ const p = peers[i];
108
+ if (!p)
109
+ continue;
110
+ if (this.localCharacterId !== null && p.characterId === this.localCharacterId) {
111
+ continue;
112
+ }
113
+ seen.add(p.characterId);
114
+ this.upsert(p.characterId, p.x, p.y, p.zone, p.tsMs, p.name);
115
+ }
116
+ // Drop anyone not in the snapshot. Iterate keys snapshot first
117
+ // because Map.delete during iteration is fine but copying makes
118
+ // intent obvious.
119
+ const toRemove = [];
120
+ this.peers.forEach((_v, k) => {
121
+ if (!seen.has(k))
122
+ toRemove.push(k);
123
+ });
124
+ for (let i = 0; i < toRemove.length; i++) {
125
+ const k = toRemove[i];
126
+ if (k)
127
+ this.peers.delete(k);
128
+ }
129
+ }
130
+ remove(characterId) {
131
+ return this.peers.delete(characterId);
132
+ }
133
+ has(characterId) {
134
+ return this.peers.has(characterId);
135
+ }
136
+ size() {
137
+ return this.peers.size;
138
+ }
139
+ get(characterId) {
140
+ return this.peers.get(characterId);
141
+ }
142
+ // Iterate every tracked peer with their interpolated world
143
+ // position at nowMs. The view object is reused; consumers must
144
+ // copy any field they want to retain past the callback.
145
+ forEachRendered(nowMs, frame, fn) {
146
+ this.peers.forEach((entry) => {
147
+ const v = this.scratchView;
148
+ v.characterId = entry.characterId;
149
+ v.zone = entry.zone;
150
+ v.name = entry.name;
151
+ const dt = entry.currentTsMs - entry.prevTsMs;
152
+ if (dt <= 0) {
153
+ v.x = entry.currentX;
154
+ v.y = entry.currentY;
155
+ }
156
+ else {
157
+ const t = clamp01((nowMs - entry.prevTsMs) / dt);
158
+ v.x = lerp(entry.prevX, entry.currentX, t);
159
+ v.y = lerp(entry.prevY, entry.currentY, t);
160
+ }
161
+ entry.lastRenderedFrame = frame;
162
+ fn(v);
163
+ });
164
+ }
165
+ // Single-peer query for tests + the rare ad-hoc lookup. Hot paths
166
+ // use forEachRendered to avoid map lookups.
167
+ getRenderedPosition(characterId, nowMs) {
168
+ const entry = this.peers.get(characterId);
169
+ if (!entry)
170
+ return null;
171
+ const dt = entry.currentTsMs - entry.prevTsMs;
172
+ if (dt <= 0) {
173
+ return { x: entry.currentX, y: entry.currentY };
174
+ }
175
+ const t = clamp01((nowMs - entry.prevTsMs) / dt);
176
+ return {
177
+ x: lerp(entry.prevX, entry.currentX, t),
178
+ y: lerp(entry.prevY, entry.currentY, t),
179
+ };
180
+ }
181
+ clear() {
182
+ this.peers.clear();
183
+ }
184
+ }
185
+ //# sourceMappingURL=peer-pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peer-pool.js","sourceRoot":"","sources":["../../src/network/peer-pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { type IMultiplayerBridge, type MultiplayerBridgeStatus, type MultiplayerBridgeStats, type PresenceMessage } from './multiplayer-bridge.js';
2
+ export interface SSEMultiplayerBridgeOptions {
3
+ baseUrl: string;
4
+ broadcastUrl?: string;
5
+ characterId: string;
6
+ zone: string;
7
+ eventSourceFactory?: (url: string) => EventSource;
8
+ fetchFn?: typeof fetch;
9
+ }
10
+ export declare class SSEMultiplayerBridge implements IMultiplayerBridge {
11
+ private readonly baseUrl;
12
+ private readonly broadcastUrl;
13
+ private readonly characterId;
14
+ private readonly zone;
15
+ private readonly eventSourceFactory;
16
+ private readonly fetchFn;
17
+ private es;
18
+ private queue;
19
+ private statusValue;
20
+ private statsValue;
21
+ private lastBroadcastMs;
22
+ constructor(opts: SSEMultiplayerBridgeOptions);
23
+ connect(): void;
24
+ disconnect(): void;
25
+ status(): MultiplayerBridgeStatus;
26
+ pollMessages(): PresenceMessage[];
27
+ broadcastPosition(x: number, y: number, zone: string, tsMs: number): void;
28
+ stats(): Readonly<MultiplayerBridgeStats>;
29
+ private buildUrl;
30
+ private openConnection;
31
+ private closeConnection;
32
+ private handleUpdate;
33
+ private handleDepart;
34
+ private handleSnapshot;
35
+ }
36
+ //# sourceMappingURL=sse-multiplayer-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse-multiplayer-bridge.d.ts","sourceRoot":"","sources":["../../src/network/sse-multiplayer-bridge.ts"],"names":[],"mappings":"AA4BA,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,eAAe,EAErB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,2BAA2B;IAI1C,OAAO,EAAE,MAAM,CAAC;IAKhB,YAAY,CAAC,EAAE,MAAM,CAAC;IAItB,WAAW,EAAE,MAAM,CAAC;IAEpB,IAAI,EAAE,MAAM,CAAC;IAGb,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,WAAW,CAAC;IAClD,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACxB;AAED,qBAAa,oBAAqB,YAAW,kBAAkB;IAC7D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA+B;IAClE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IAEvC,OAAO,CAAC,EAAE,CAA4B;IACtC,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,UAAU,CAKhB;IAEF,OAAO,CAAC,eAAe,CAAqB;gBAEhC,IAAI,EAAE,2BAA2B;IAwB7C,OAAO,IAAI,IAAI;IAMf,UAAU,IAAI,IAAI;IAKlB,MAAM,IAAI,uBAAuB;IAIjC,YAAY,IAAI,eAAe,EAAE;IAOjC,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IA0BzE,KAAK,IAAI,QAAQ,CAAC,sBAAsB,CAAC;IAMzC,OAAO,CAAC,QAAQ;IAUhB,OAAO,CAAC,cAAc;IAmCtB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,YAAY;IAyBpB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,cAAc;CAsCvB"}