@sadhaka/loom-engine 0.12.0 → 0.14.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.
- package/README.md +113 -1
- package/dist/components/peer-sprite.d.ts +25 -0
- package/dist/components/peer-sprite.d.ts.map +1 -0
- package/dist/components/peer-sprite.js +48 -0
- package/dist/components/peer-sprite.js.map +1 -0
- package/dist/director/ai/ai-plugin-registry.d.ts +20 -0
- package/dist/director/ai/ai-plugin-registry.d.ts.map +1 -0
- package/dist/director/ai/ai-plugin-registry.js +232 -0
- package/dist/director/ai/ai-plugin-registry.js.map +1 -0
- package/dist/director/ai/mock-ai-plugin.d.ts +24 -0
- package/dist/director/ai/mock-ai-plugin.d.ts.map +1 -0
- package/dist/director/ai/mock-ai-plugin.js +83 -0
- package/dist/director/ai/mock-ai-plugin.js.map +1 -0
- package/dist/director/ai/plugin-context.d.ts +27 -0
- package/dist/director/ai/plugin-context.d.ts.map +1 -0
- package/dist/director/ai/plugin-context.js +152 -0
- package/dist/director/ai/plugin-context.js.map +1 -0
- package/dist/director/ai/plugin.d.ts +57 -0
- package/dist/director/ai/plugin.d.ts.map +1 -0
- package/dist/director/ai/plugin.js +32 -0
- package/dist/director/ai/plugin.js.map +1 -0
- package/dist/director/index.d.ts +27 -0
- package/dist/director/index.d.ts.map +1 -0
- package/dist/director/index.js +26 -0
- package/dist/director/index.js.map +1 -0
- package/dist/director/zone/mock-zone-bridge.d.ts +22 -0
- package/dist/director/zone/mock-zone-bridge.d.ts.map +1 -0
- package/dist/director/zone/mock-zone-bridge.js +107 -0
- package/dist/director/zone/mock-zone-bridge.js.map +1 -0
- package/dist/director/zone/sse-zone-bridge.d.ts +40 -0
- package/dist/director/zone/sse-zone-bridge.d.ts.map +1 -0
- package/dist/director/zone/sse-zone-bridge.js +164 -0
- package/dist/director/zone/sse-zone-bridge.js.map +1 -0
- package/dist/director/zone/zone-event-bridge.d.ts +21 -0
- package/dist/director/zone/zone-event-bridge.d.ts.map +1 -0
- package/dist/director/zone/zone-event-bridge.js +24 -0
- package/dist/director/zone/zone-event-bridge.js.map +1 -0
- package/dist/director/zone/zone-event-envelope.d.ts +90 -0
- package/dist/director/zone/zone-event-envelope.d.ts.map +1 -0
- package/dist/director/zone/zone-event-envelope.js +104 -0
- package/dist/director/zone/zone-event-envelope.js.map +1 -0
- package/dist/director/zone/zone-event-log.d.ts +17 -0
- package/dist/director/zone/zone-event-log.d.ts.map +1 -0
- package/dist/director/zone/zone-event-log.js +46 -0
- package/dist/director/zone/zone-event-log.js.map +1 -0
- package/dist/director/zone/zone-event-system.d.ts +14 -0
- package/dist/director/zone/zone-event-system.d.ts.map +1 -0
- package/dist/director/zone/zone-event-system.js +179 -0
- package/dist/director/zone/zone-event-system.js.map +1 -0
- package/dist/director/zone/zone-state-resource.d.ts +15 -0
- package/dist/director/zone/zone-state-resource.d.ts.map +1 -0
- package/dist/director/zone/zone-state-resource.js +60 -0
- package/dist/director/zone/zone-state-resource.js.map +1 -0
- package/dist/index.d.ts +25 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/network/mock-multiplayer-bridge.d.ts +34 -0
- package/dist/network/mock-multiplayer-bridge.d.ts.map +1 -0
- package/dist/network/mock-multiplayer-bridge.js +91 -0
- package/dist/network/mock-multiplayer-bridge.js.map +1 -0
- package/dist/network/multiplayer-bridge.d.ts +45 -0
- package/dist/network/multiplayer-bridge.d.ts.map +1 -0
- package/dist/network/multiplayer-bridge.js +34 -0
- package/dist/network/multiplayer-bridge.js.map +1 -0
- package/dist/network/peer-pool.d.ts +46 -0
- package/dist/network/peer-pool.d.ts.map +1 -0
- package/dist/network/peer-pool.js +185 -0
- package/dist/network/peer-pool.js.map +1 -0
- package/dist/network/sse-multiplayer-bridge.d.ts +36 -0
- package/dist/network/sse-multiplayer-bridge.d.ts.map +1 -0
- package/dist/network/sse-multiplayer-bridge.js +264 -0
- package/dist/network/sse-multiplayer-bridge.js.map +1 -0
- package/dist/server/index.d.ts +7 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +33 -0
- package/dist/server/index.js.map +1 -0
- package/dist/systems/peer-presence-system.d.ts +19 -0
- package/dist/systems/peer-presence-system.d.ts.map +1 -0
- package/dist/systems/peer-presence-system.js +118 -0
- package/dist/systems/peer-presence-system.js.map +1 -0
- package/package.json +6 -2
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// PluginContext concrete implementations.
|
|
2
|
+
//
|
|
3
|
+
// MapPluginStorage - in-memory KV backed by a single Map, namespaced
|
|
4
|
+
// per (pluginName, key). Survives across ticks;
|
|
5
|
+
// cleared when the registry calls clearPlugin().
|
|
6
|
+
// ConsolePluginLogger - tags every line with the plugin name and
|
|
7
|
+
// writes to console.{info,warn,error}. Suitable
|
|
8
|
+
// for tests + dev; production consumers can
|
|
9
|
+
// drop in a structured-log impl.
|
|
10
|
+
//
|
|
11
|
+
// These are reference implementations. Consumers wiring against
|
|
12
|
+
// `@sadhaka/loom-engine/server` may substitute their own
|
|
13
|
+
// PluginStorage / PluginLogger impls (e.g. Redis-backed storage,
|
|
14
|
+
// pino-backed logger) without changing the SPI surface.
|
|
15
|
+
//
|
|
16
|
+
// The registry does not assume MapPluginStorage; the SPI is
|
|
17
|
+
// the only contract. These exist so a consumer can stand a plugin
|
|
18
|
+
// up in five lines without writing a storage adapter first.
|
|
19
|
+
// ----- MapPluginStorage -----
|
|
20
|
+
//
|
|
21
|
+
// In-memory storage shared across all plugins; per-plugin namespace
|
|
22
|
+
// is enforced by composing the storage key as `${pluginName}::${key}`.
|
|
23
|
+
// `clearPlugin(name)` wipes every entry tagged with that plugin so
|
|
24
|
+
// unregister + re-register starts clean.
|
|
25
|
+
export class MapPluginStorage {
|
|
26
|
+
store = new Map();
|
|
27
|
+
// Build a per-plugin facade that satisfies the PluginStorage
|
|
28
|
+
// interface; the facade scopes get/set/delete to the plugin's
|
|
29
|
+
// namespace so plugin authors never see the composite key.
|
|
30
|
+
forPlugin(pluginName) {
|
|
31
|
+
var self = this;
|
|
32
|
+
return {
|
|
33
|
+
async get(key) {
|
|
34
|
+
return self.store.get(self.composeKey(pluginName, key));
|
|
35
|
+
},
|
|
36
|
+
async set(key, value) {
|
|
37
|
+
self.store.set(self.composeKey(pluginName, key), value);
|
|
38
|
+
},
|
|
39
|
+
async delete(key) {
|
|
40
|
+
self.store.delete(self.composeKey(pluginName, key));
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
// Wipe all entries belonging to a plugin. Called by the registry
|
|
45
|
+
// on unregister(). Iterates once; cost is O(total entries) but
|
|
46
|
+
// unregister is rare.
|
|
47
|
+
clearPlugin(pluginName) {
|
|
48
|
+
var prefix = pluginName + '::';
|
|
49
|
+
var keysToDelete = [];
|
|
50
|
+
var iter = this.store.keys();
|
|
51
|
+
var next = iter.next();
|
|
52
|
+
while (!next.done) {
|
|
53
|
+
var k = next.value;
|
|
54
|
+
if (k.startsWith(prefix)) {
|
|
55
|
+
keysToDelete.push(k);
|
|
56
|
+
}
|
|
57
|
+
next = iter.next();
|
|
58
|
+
}
|
|
59
|
+
for (var i = 0; i < keysToDelete.length; i++) {
|
|
60
|
+
var key = keysToDelete[i];
|
|
61
|
+
if (key !== undefined) {
|
|
62
|
+
this.store.delete(key);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Inspect-only: total number of entries across all plugins. Useful
|
|
67
|
+
// in tests when asserting clearPlugin shrinks the store.
|
|
68
|
+
size() {
|
|
69
|
+
return this.store.size;
|
|
70
|
+
}
|
|
71
|
+
composeKey(pluginName, key) {
|
|
72
|
+
return pluginName + '::' + key;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// ----- ConsolePluginLogger -----
|
|
76
|
+
//
|
|
77
|
+
// Tags every line with `[plugin: <name>]` and forwards to the
|
|
78
|
+
// matching console method. Meta is JSON-stringified and appended;
|
|
79
|
+
// circular refs fall back to a short description so logging never
|
|
80
|
+
// throws at the boundary.
|
|
81
|
+
export class ConsolePluginLogger {
|
|
82
|
+
pluginName;
|
|
83
|
+
constructor(pluginName) {
|
|
84
|
+
this.pluginName = pluginName;
|
|
85
|
+
}
|
|
86
|
+
info(msg, meta) {
|
|
87
|
+
this.write('info', msg, meta);
|
|
88
|
+
}
|
|
89
|
+
warn(msg, meta) {
|
|
90
|
+
this.write('warn', msg, meta);
|
|
91
|
+
}
|
|
92
|
+
error(msg, meta) {
|
|
93
|
+
this.write('error', msg, meta);
|
|
94
|
+
}
|
|
95
|
+
write(level, msg, meta) {
|
|
96
|
+
var tag = '[plugin: ' + this.pluginName + ']';
|
|
97
|
+
var line = tag + ' ' + msg;
|
|
98
|
+
var metaStr = '';
|
|
99
|
+
if (meta) {
|
|
100
|
+
try {
|
|
101
|
+
metaStr = ' ' + JSON.stringify(meta);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
metaStr = ' [meta-not-serializable]';
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
var out = line + metaStr;
|
|
108
|
+
if (level === 'info') {
|
|
109
|
+
console.info(out);
|
|
110
|
+
}
|
|
111
|
+
else if (level === 'warn') {
|
|
112
|
+
console.warn(out);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
console.error(out);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export function buildPluginContext(opts) {
|
|
120
|
+
var pluginName = opts.pluginName;
|
|
121
|
+
var logger = opts.logger ?? new ConsolePluginLogger(pluginName);
|
|
122
|
+
var storage = opts.storage.forPlugin(pluginName);
|
|
123
|
+
var getZonePeers = opts.getZonePeers ??
|
|
124
|
+
function () {
|
|
125
|
+
return [];
|
|
126
|
+
};
|
|
127
|
+
var getCharacterState = opts.getCharacterState ??
|
|
128
|
+
function (characterId) {
|
|
129
|
+
return {
|
|
130
|
+
characterId,
|
|
131
|
+
zone: '',
|
|
132
|
+
x: 0,
|
|
133
|
+
y: 0,
|
|
134
|
+
hp_current: 0,
|
|
135
|
+
hp_max: 0,
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
var getZoneState = opts.getZoneState ??
|
|
139
|
+
function () {
|
|
140
|
+
return new Map();
|
|
141
|
+
};
|
|
142
|
+
var now = opts.now ?? Date.now;
|
|
143
|
+
return {
|
|
144
|
+
getZonePeers,
|
|
145
|
+
getCharacterState,
|
|
146
|
+
getZoneState,
|
|
147
|
+
storage,
|
|
148
|
+
logger,
|
|
149
|
+
now,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=plugin-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-context.js","sourceRoot":"","sources":["../../../src/director/ai/plugin-context.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,qEAAqE;AACrE,iEAAiE;AACjE,sEAAsE;AACtE,kEAAkE;AAClE,uDAAuD;AACvD,EAAE;AACF,gEAAgE;AAChE,yDAAyD;AACzD,iEAAiE;AACjE,wDAAwD;AACxD,EAAE;AACF,4DAA4D;AAC5D,kEAAkE;AAClE,4DAA4D;AAU5D,+BAA+B;AAC/B,EAAE;AACF,oEAAoE;AACpE,uEAAuE;AACvE,mEAAmE;AACnE,yCAAyC;AACzC,MAAM,OAAO,gBAAgB;IACV,KAAK,GAAG,IAAI,GAAG,EAAmB,CAAC;IAEpD,6DAA6D;IAC7D,8DAA8D;IAC9D,2DAA2D;IAC3D,SAAS,CAAC,UAAkB;QAC1B,IAAI,IAAI,GAAG,IAAI,CAAC;QAChB,OAAO;YACL,KAAK,CAAC,GAAG,CAAC,GAAW;gBACnB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;YAC1D,CAAC;YACD,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAc;gBACnC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;YAC1D,CAAC;YACD,KAAK,CAAC,MAAM,CAAC,GAAW;gBACtB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;YACtD,CAAC;SACF,CAAC;IACJ,CAAC;IAED,iEAAiE;IACjE,+DAA+D;IAC/D,sBAAsB;IACtB,WAAW,CAAC,UAAkB;QAC5B,IAAI,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC;QAC/B,IAAI,YAAY,GAAa,EAAE,CAAC;QAChC,IAAI,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAClB,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;YACnB,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBACzB,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACvB,CAAC;YACD,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACrB,CAAC;QACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,IAAI,GAAG,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAC1B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;gBACtB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,yDAAyD;IACzD,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;IAEO,UAAU,CAAC,UAAkB,EAAE,GAAW;QAChD,OAAO,UAAU,GAAG,IAAI,GAAG,GAAG,CAAC;IACjC,CAAC;CACF;AAED,kCAAkC;AAClC,EAAE;AACF,8DAA8D;AAC9D,kEAAkE;AAClE,kEAAkE;AAClE,0BAA0B;AAC1B,MAAM,OAAO,mBAAmB;IACD;IAA7B,YAA6B,UAAkB;QAAlB,eAAU,GAAV,UAAU,CAAQ;IAAG,CAAC;IAEnD,IAAI,CAAC,GAAW,EAAE,IAA8B;QAC9C,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IAChC,CAAC;IAED,IAAI,CAAC,GAAW,EAAE,IAA8B;QAC9C,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,GAAW,EAAE,IAA8B;QAC/C,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IAEO,KAAK,CACX,KAAgC,EAChC,GAAW,EACX,IAA8B;QAE9B,IAAI,GAAG,GAAG,WAAW,GAAG,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC;QAC9C,IAAI,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;QAC3B,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC;gBACH,OAAO,GAAG,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YACvC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,GAAG,0BAA0B,CAAC;YACvC,CAAC;QACH,CAAC;QACD,IAAI,GAAG,GAAG,IAAI,GAAG,OAAO,CAAC;QACzB,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;aAAM,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YAC5B,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;CACF;AA0BD,MAAM,UAAU,kBAAkB,CAAC,IAA+B;IAChE,IAAI,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;IACjC,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAChE,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IACjD,IAAI,YAAY,GACd,IAAI,CAAC,YAAY;QACjB;YACE,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;IACJ,IAAI,iBAAiB,GACnB,IAAI,CAAC,iBAAiB;QACtB,UAAU,WAAmB;YAC3B,OAAO;gBACL,WAAW;gBACX,IAAI,EAAE,EAAE;gBACR,CAAC,EAAE,CAAC;gBACJ,CAAC,EAAE,CAAC;gBACJ,UAAU,EAAE,CAAC;gBACb,MAAM,EAAE,CAAC;aACV,CAAC;QACJ,CAAC,CAAC;IACJ,IAAI,YAAY,GACd,IAAI,CAAC,YAAY;QACjB;YACE,OAAO,IAAI,GAAG,EAAmB,CAAC;QACpC,CAAC,CAAC;IACJ,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IAC/B,OAAO;QACL,YAAY;QACZ,iBAAiB;QACjB,YAAY;QACZ,OAAO;QACP,MAAM;QACN,GAAG;KACJ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { DirectorEvent } from '../event-envelope.js';
|
|
2
|
+
import type { ZoneEvent } from '../zone/zone-event-envelope.js';
|
|
3
|
+
export type { ZoneEvent };
|
|
4
|
+
export interface EmittedEvents {
|
|
5
|
+
characterEvents?: DirectorEvent[];
|
|
6
|
+
zoneEvents?: ZoneEvent[];
|
|
7
|
+
}
|
|
8
|
+
export interface PeerInfo {
|
|
9
|
+
characterId: string;
|
|
10
|
+
userId: string;
|
|
11
|
+
zone: string;
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
name: string | null;
|
|
15
|
+
}
|
|
16
|
+
export interface PlayerAction {
|
|
17
|
+
kind: 'damage' | 'interact' | 'speak' | 'use_item' | (string & {});
|
|
18
|
+
payload: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
export interface CharacterState {
|
|
21
|
+
characterId: string;
|
|
22
|
+
zone: string;
|
|
23
|
+
x: number;
|
|
24
|
+
y: number;
|
|
25
|
+
hp_current: number;
|
|
26
|
+
hp_max: number;
|
|
27
|
+
}
|
|
28
|
+
export interface PluginStorage {
|
|
29
|
+
get(key: string): Promise<unknown | undefined>;
|
|
30
|
+
set(key: string, value: unknown): Promise<void>;
|
|
31
|
+
delete(key: string): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
export interface PluginLogger {
|
|
34
|
+
info(msg: string, meta?: Record<string, unknown>): void;
|
|
35
|
+
warn(msg: string, meta?: Record<string, unknown>): void;
|
|
36
|
+
error(msg: string, meta?: Record<string, unknown>): void;
|
|
37
|
+
}
|
|
38
|
+
export interface PluginContext {
|
|
39
|
+
getZonePeers(zoneId: string): ReadonlyArray<PeerInfo>;
|
|
40
|
+
getCharacterState(characterId: string): Readonly<CharacterState>;
|
|
41
|
+
getZoneState(zoneId: string): ReadonlyMap<string, unknown>;
|
|
42
|
+
storage: PluginStorage;
|
|
43
|
+
logger: PluginLogger;
|
|
44
|
+
now: () => number;
|
|
45
|
+
}
|
|
46
|
+
export interface IAIPlugin {
|
|
47
|
+
readonly name: string;
|
|
48
|
+
readonly version: string;
|
|
49
|
+
readonly priority: number;
|
|
50
|
+
onTick?(ctx: PluginContext): Promise<EmittedEvents>;
|
|
51
|
+
onPeerJoin?(ctx: PluginContext, peer: PeerInfo): Promise<EmittedEvents>;
|
|
52
|
+
onPeerLeave?(ctx: PluginContext, peer: PeerInfo): Promise<EmittedEvents>;
|
|
53
|
+
onZoneEnter?(ctx: PluginContext, peer: PeerInfo, fromZone: string | null): Promise<EmittedEvents>;
|
|
54
|
+
onPlayerAction?(ctx: PluginContext, peer: PeerInfo, action: PlayerAction): Promise<EmittedEvents>;
|
|
55
|
+
dispose?(): Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/director/ai/plugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// IAIPlugin - server-side plugin SPI for the Director.
|
|
2
|
+
//
|
|
3
|
+
// Per LOOM-DIRECTOR-PROTOCOL-V2 Section 5: the engine no longer
|
|
4
|
+
// hardcodes a single Anthropic flow. Consumers register any number of
|
|
5
|
+
// IAIPlugin implementations against the AIPluginRegistry, and the
|
|
6
|
+
// runtime dispatches lifecycle hooks (tick, peer join/leave, zone
|
|
7
|
+
// enter, player action). Each hook returns EmittedEvents - either
|
|
8
|
+
// per-character v1 envelopes, v2 zone events, or both.
|
|
9
|
+
//
|
|
10
|
+
// This module is server-only. The browser bundle never imports it.
|
|
11
|
+
// It is exposed only via the `@sadhaka/loom-engine/server` entry
|
|
12
|
+
// point so consumers can wire LLM-backed plugins (Anthropic, OpenAI,
|
|
13
|
+
// local models, deterministic state machines, ...) on the Node side
|
|
14
|
+
// while the browser engine stays small.
|
|
15
|
+
//
|
|
16
|
+
// `ZoneEvent` (LOOM-DIRECTOR-PROTOCOL-V2 §3) is defined in
|
|
17
|
+
// `src/director/zone/zone-event-envelope.ts` (Track A, merged into
|
|
18
|
+
// 0.14.0 alongside this module). The registry carries zone events
|
|
19
|
+
// opaquely - it never dereferences fields beyond the discriminated
|
|
20
|
+
// union - so the only consumer of the strict type is plugin authors
|
|
21
|
+
// constructing ZoneEvent values in their hook returns.
|
|
22
|
+
//
|
|
23
|
+
// Spec invariants preserved:
|
|
24
|
+
// - All hooks are async; they return EmittedEvents.
|
|
25
|
+
// - Hooks not implemented by a plugin are simply omitted; the
|
|
26
|
+
// registry checks `typeof plugin.onX === 'function'` before call.
|
|
27
|
+
// - Plugins are pure-ish: given a context, they return events.
|
|
28
|
+
// State mutation is the engine's job (open question 8.2 resolved).
|
|
29
|
+
// - Plugin-direct event emission outside its returned EmittedEvents
|
|
30
|
+
// is not supported; the registry is the single funnel.
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../src/director/ai/plugin.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,EAAE;AACF,gEAAgE;AAChE,sEAAsE;AACtE,kEAAkE;AAClE,kEAAkE;AAClE,kEAAkE;AAClE,uDAAuD;AACvD,EAAE;AACF,mEAAmE;AACnE,iEAAiE;AACjE,qEAAqE;AACrE,oEAAoE;AACpE,wCAAwC;AACxC,EAAE;AACF,2DAA2D;AAC3D,mEAAmE;AACnE,kEAAkE;AAClE,mEAAmE;AACnE,oEAAoE;AACpE,uDAAuD;AACvD,EAAE;AACF,6BAA6B;AAC7B,sDAAsD;AACtD,gEAAgE;AAChE,sEAAsE;AACtE,iEAAiE;AACjE,uEAAuE;AACvE,sEAAsE;AACtE,2DAA2D"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type { EventEnvelope, DirectorEvent, DirectorEventType, DirectorEventDataMap, EventPriority, EncounterSpawnData, EncounterTickData, EncounterEndData, EncounterLootData, KnotContextData, KnotPaletteHex, KnotMood, VeBudgetUpdateData, VeilTier, SceneTransitionData, SceneTransitionKind, NarratorLineData, NarratorVoice, SystemHeartbeatData, SystemReplayCompleteData, SystemSnapshotRequiredData, MobSpec, BossSpec, DropSpec, } from './event-envelope.js';
|
|
2
|
+
export { parseEnvelope, parseEnvelopeJson, priorityFor, EventEnvelopeParseError, } from './event-envelope.js';
|
|
3
|
+
export type { IDirectorBridge, DirectorBridgeStatus, DirectorBridgeStats, } from './director-bridge.js';
|
|
4
|
+
export { RESOURCE_DIRECTOR_BRIDGE, RESOURCE_KNOT_CONTEXT, } from './director-bridge.js';
|
|
5
|
+
export { MockDirectorBridge } from './mock-director-bridge.js';
|
|
6
|
+
export type { SSEDirectorBridgeOptions } from './sse-director-bridge.js';
|
|
7
|
+
export { SSEDirectorBridge } from './sse-director-bridge.js';
|
|
8
|
+
export type { KnotPaletteRgba } from './knot-context-resource.js';
|
|
9
|
+
export { KnotContextResource } from './knot-context-resource.js';
|
|
10
|
+
export type { DirectorEventLog } from './director-system.js';
|
|
11
|
+
export { DirectorSystem, RESOURCE_DIRECTOR_LOG, createDirectorEventLog, } from './director-system.js';
|
|
12
|
+
export type { DirectorEncounterSystemOptions } from './director-encounter-system.js';
|
|
13
|
+
export { DirectorEncounterSystem } from './director-encounter-system.js';
|
|
14
|
+
export type { ZoneEventEnvelope, ZoneEvent, ZoneEventType, ZoneEventDataMap, ZoneBossSpec, ZoneBossSpawnData, ZoneBossTickData, ZoneBossEndData, ZoneBossOutcome, ZoneBossHit, ZoneNarratorData, ZoneKnotData, ZoneStateData, ZoneSnapshotData, ZoneStateChange, } from './zone/zone-event-envelope.js';
|
|
15
|
+
export { parseZoneEnvelope, parseZoneEnvelopeJson, priorityFor as zonePriorityFor, ZoneEventEnvelopeParseError, } from './zone/zone-event-envelope.js';
|
|
16
|
+
export type { IZoneEventBridge, ZoneEventBridgeStatus, ZoneEventBridgeStats, } from './zone/zone-event-bridge.js';
|
|
17
|
+
export { RESOURCE_ZONE_EVENT_BRIDGE } from './zone/zone-event-bridge.js';
|
|
18
|
+
export { MockZoneBridge } from './zone/mock-zone-bridge.js';
|
|
19
|
+
export type { SSEZoneBridgeOptions, SSEZoneBridgeEventSource, } from './zone/sse-zone-bridge.js';
|
|
20
|
+
export { SSEZoneBridge } from './zone/sse-zone-bridge.js';
|
|
21
|
+
export type { ZoneEventLog, ZoneEventLogEntry, } from './zone/zone-event-log.js';
|
|
22
|
+
export { RESOURCE_ZONE_EVENT_LOG, ZONE_RING_SIZE, createZoneEventLog, getOrCreateZoneEntry, pushZoneEvent, } from './zone/zone-event-log.js';
|
|
23
|
+
export type { DirectorZoneStateResource } from './zone/zone-state-resource.js';
|
|
24
|
+
export { RESOURCE_DIRECTOR_ZONE_STATE, createDirectorZoneStateResource, getOrCreateZoneStateMap, applyZoneStateChanges, replaceZoneStateFromSnapshot, } from './zone/zone-state-resource.js';
|
|
25
|
+
export type { ZoneEventSystemOptions } from './zone/zone-event-system.js';
|
|
26
|
+
export { ZoneEventSystem } from './zone/zone-event-system.js';
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/director/index.ts"],"names":[],"mappings":"AAaA,YAAY,EACV,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,oBAAoB,EACpB,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,QAAQ,EACR,kBAAkB,EAClB,QAAQ,EACR,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,aAAa,EACb,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC1B,OAAO,EACP,QAAQ,EACR,QAAQ,GACT,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,eAAe,EACf,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,YAAY,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,YAAY,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,8BAA8B,EAAE,MAAM,gCAAgC,CAAC;AACrF,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAGzE,YAAY,EACV,iBAAiB,EACjB,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,eAAe,GAChB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,WAAW,IAAI,eAAe,EAC9B,2BAA2B,GAC5B,MAAM,+BAA+B,CAAC;AACvC,YAAY,EACV,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,YAAY,EACV,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,YAAY,EACV,YAAY,EACZ,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,uBAAuB,EACvB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,GACd,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EACL,4BAA4B,EAC5B,+BAA+B,EAC/B,uBAAuB,EACvB,qBAAqB,EACrB,4BAA4B,GAC7B,MAAM,+BAA+B,CAAC;AACvC,YAAY,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Director module barrel - re-exports the v1 (Phase 6) surface plus
|
|
2
|
+
// the v2 (Phase 16) zone-event surface.
|
|
3
|
+
//
|
|
4
|
+
// v1 lives at the top level of src/director/. v2 lives under
|
|
5
|
+
// src/director/zone/. Track B's AI Plugin SPI lives under
|
|
6
|
+
// src/director/ai/ and is re-exported via @sadhaka/loom-engine/server,
|
|
7
|
+
// not from here. We do not pull AI plugin types into this barrel so
|
|
8
|
+
// the browser bundle stays small.
|
|
9
|
+
//
|
|
10
|
+
// Engine-level public re-exports happen in ../index.ts. Internal
|
|
11
|
+
// callers can import from this barrel for convenience.
|
|
12
|
+
export { parseEnvelope, parseEnvelopeJson, priorityFor, EventEnvelopeParseError, } from './event-envelope.js';
|
|
13
|
+
export { RESOURCE_DIRECTOR_BRIDGE, RESOURCE_KNOT_CONTEXT, } from './director-bridge.js';
|
|
14
|
+
export { MockDirectorBridge } from './mock-director-bridge.js';
|
|
15
|
+
export { SSEDirectorBridge } from './sse-director-bridge.js';
|
|
16
|
+
export { KnotContextResource } from './knot-context-resource.js';
|
|
17
|
+
export { DirectorSystem, RESOURCE_DIRECTOR_LOG, createDirectorEventLog, } from './director-system.js';
|
|
18
|
+
export { DirectorEncounterSystem } from './director-encounter-system.js';
|
|
19
|
+
export { parseZoneEnvelope, parseZoneEnvelopeJson, priorityFor as zonePriorityFor, ZoneEventEnvelopeParseError, } from './zone/zone-event-envelope.js';
|
|
20
|
+
export { RESOURCE_ZONE_EVENT_BRIDGE } from './zone/zone-event-bridge.js';
|
|
21
|
+
export { MockZoneBridge } from './zone/mock-zone-bridge.js';
|
|
22
|
+
export { SSEZoneBridge } from './zone/sse-zone-bridge.js';
|
|
23
|
+
export { RESOURCE_ZONE_EVENT_LOG, ZONE_RING_SIZE, createZoneEventLog, getOrCreateZoneEntry, pushZoneEvent, } from './zone/zone-event-log.js';
|
|
24
|
+
export { RESOURCE_DIRECTOR_ZONE_STATE, createDirectorZoneStateResource, getOrCreateZoneStateMap, applyZoneStateChanges, replaceZoneStateFromSnapshot, } from './zone/zone-state-resource.js';
|
|
25
|
+
export { ZoneEventSystem } from './zone/zone-event-system.js';
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/director/index.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,wCAAwC;AACxC,EAAE;AACF,6DAA6D;AAC7D,0DAA0D;AAC1D,uEAAuE;AACvE,oEAAoE;AACpE,kCAAkC;AAClC,EAAE;AACF,iEAAiE;AACjE,uDAAuD;AA6BvD,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAM7B,OAAO,EACL,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAoBzE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,WAAW,IAAI,eAAe,EAC9B,2BAA2B,GAC5B,MAAM,+BAA+B,CAAC;AAMvC,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAK5D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAK1D,OAAO,EACL,uBAAuB,EACvB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,GACd,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,4BAA4B,EAC5B,+BAA+B,EAC/B,uBAAuB,EACvB,qBAAqB,EACrB,4BAA4B,GAC7B,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ZoneEvent } from './zone-event-envelope.js';
|
|
2
|
+
import { type IZoneEventBridge, type ZoneEventBridgeStatus, type ZoneEventBridgeStats } from './zone-event-bridge.js';
|
|
3
|
+
export declare class MockZoneBridge implements IZoneEventBridge {
|
|
4
|
+
private queue;
|
|
5
|
+
private statusValue;
|
|
6
|
+
private readonly lastEventIdByZone;
|
|
7
|
+
private readonly statsValue;
|
|
8
|
+
start(): void;
|
|
9
|
+
stop(): void;
|
|
10
|
+
status(): ZoneEventBridgeStatus;
|
|
11
|
+
isConnected(): boolean;
|
|
12
|
+
getLastEventId(zone: string): number;
|
|
13
|
+
pollEvents(): ZoneEvent[];
|
|
14
|
+
stats(): Readonly<ZoneEventBridgeStats>;
|
|
15
|
+
enqueueIncoming(event: ZoneEvent): void;
|
|
16
|
+
enqueueIncomingJson(json: string): boolean;
|
|
17
|
+
enqueueAll(events: ReadonlyArray<ZoneEvent>): void;
|
|
18
|
+
bumpReconnect(): void;
|
|
19
|
+
setServerDrops(p1: number, p2: number): void;
|
|
20
|
+
pending(): number;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=mock-zone-bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-zone-bridge.d.ts","sourceRoot":"","sources":["../../../src/director/zone/mock-zone-bridge.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAC1B,MAAM,wBAAwB,CAAC;AAEhC,qBAAa,cAAe,YAAW,gBAAgB;IACrD,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAkC;IACpE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAYzB;IAEF,KAAK,IAAI,IAAI;IAIb,IAAI,IAAI,IAAI;IAIZ,MAAM,IAAI,qBAAqB;IAI/B,WAAW,IAAI,OAAO;IAItB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIpC,UAAU,IAAI,SAAS,EAAE;IAOzB,KAAK,IAAI,QAAQ,CAAC,oBAAoB,CAAC;IAmBvC,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAavC,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAQ1C,UAAU,CAAC,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,GAAG,IAAI;IAQlD,aAAa,IAAI,IAAI;IAKrB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAM5C,OAAO,IAAI,MAAM;CAGlB"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// MockZoneBridge - in-memory v2 zone-event source for tests + offline
|
|
2
|
+
// demos.
|
|
3
|
+
//
|
|
4
|
+
// Tests inject envelopes via enqueueIncoming() and let ZoneEventSystem
|
|
5
|
+
// drain them. The demo path can also use this when running without a
|
|
6
|
+
// backend connection. pollEvents() drains the queue in FIFO order.
|
|
7
|
+
//
|
|
8
|
+
// Tracks per-zone lastEventId so the IZoneEventBridge contract is
|
|
9
|
+
// satisfied. Does not reconnect, does not validate envelopes when fed
|
|
10
|
+
// objects directly - that's parseZoneEnvelope's job upstream of
|
|
11
|
+
// enqueueIncoming(). enqueueIncomingJson() is a convenience that runs
|
|
12
|
+
// the parser first and silently drops malformed payloads (mirrors how
|
|
13
|
+
// SSEZoneBridge would handle a bad frame).
|
|
14
|
+
import { parseZoneEnvelopeJson } from './zone-event-envelope.js';
|
|
15
|
+
export class MockZoneBridge {
|
|
16
|
+
queue = [];
|
|
17
|
+
statusValue = 'idle';
|
|
18
|
+
lastEventIdByZone = new Map();
|
|
19
|
+
statsValue = {
|
|
20
|
+
eventsReceived: 0,
|
|
21
|
+
reconnects: 0,
|
|
22
|
+
outOfOrderEvents: 0,
|
|
23
|
+
serverDropsP1: 0,
|
|
24
|
+
serverDropsP2: 0,
|
|
25
|
+
};
|
|
26
|
+
start() {
|
|
27
|
+
this.statusValue = 'connected';
|
|
28
|
+
}
|
|
29
|
+
stop() {
|
|
30
|
+
this.statusValue = 'closed';
|
|
31
|
+
}
|
|
32
|
+
status() {
|
|
33
|
+
return this.statusValue;
|
|
34
|
+
}
|
|
35
|
+
isConnected() {
|
|
36
|
+
return this.statusValue === 'connected';
|
|
37
|
+
}
|
|
38
|
+
getLastEventId(zone) {
|
|
39
|
+
return this.lastEventIdByZone.get(zone) ?? 0;
|
|
40
|
+
}
|
|
41
|
+
pollEvents() {
|
|
42
|
+
if (this.queue.length === 0)
|
|
43
|
+
return [];
|
|
44
|
+
const out = this.queue;
|
|
45
|
+
this.queue = [];
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
stats() {
|
|
49
|
+
// Allocate the read-only view fresh each call so mutations after
|
|
50
|
+
// the call don't leak through. lastEventIdByZone is wrapped in a
|
|
51
|
+
// shallow clone; spec calls this rare so cost is fine.
|
|
52
|
+
return {
|
|
53
|
+
eventsReceived: this.statsValue.eventsReceived,
|
|
54
|
+
reconnects: this.statsValue.reconnects,
|
|
55
|
+
outOfOrderEvents: this.statsValue.outOfOrderEvents,
|
|
56
|
+
serverDropsP1: this.statsValue.serverDropsP1,
|
|
57
|
+
serverDropsP2: this.statsValue.serverDropsP2,
|
|
58
|
+
lastEventIdByZone: new Map(this.lastEventIdByZone),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// ----- Mock-only injection helpers -----
|
|
62
|
+
// Enqueue a parsed envelope as if the server pushed it. Out-of-order
|
|
63
|
+
// injection is allowed; the consumer's per-zone gap detection should
|
|
64
|
+
// handle it.
|
|
65
|
+
enqueueIncoming(event) {
|
|
66
|
+
this.queue.push(event);
|
|
67
|
+
this.statsValue.eventsReceived++;
|
|
68
|
+
const prev = this.lastEventIdByZone.get(event.zone_id) ?? 0;
|
|
69
|
+
if (event.id > prev) {
|
|
70
|
+
this.lastEventIdByZone.set(event.zone_id, event.id);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
this.statsValue.outOfOrderEvents++;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Convenience: enqueue from a JSON string. Silently drops malformed
|
|
77
|
+
// payloads, matching the SSE bridge's parse-error behaviour.
|
|
78
|
+
enqueueIncomingJson(json) {
|
|
79
|
+
const ev = parseZoneEnvelopeJson(json);
|
|
80
|
+
if (!ev)
|
|
81
|
+
return false;
|
|
82
|
+
this.enqueueIncoming(ev);
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
// Convenience: bulk enqueue.
|
|
86
|
+
enqueueAll(events) {
|
|
87
|
+
for (let i = 0; i < events.length; i++) {
|
|
88
|
+
const e = events[i];
|
|
89
|
+
if (e)
|
|
90
|
+
this.enqueueIncoming(e);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Mock-only: simulate the server crediting a reconnect.
|
|
94
|
+
bumpReconnect() {
|
|
95
|
+
this.statsValue.reconnects++;
|
|
96
|
+
}
|
|
97
|
+
// Mock-only: simulate server-side drop counters from a heartbeat.
|
|
98
|
+
setServerDrops(p1, p2) {
|
|
99
|
+
this.statsValue.serverDropsP1 = p1;
|
|
100
|
+
this.statsValue.serverDropsP2 = p2;
|
|
101
|
+
}
|
|
102
|
+
// Inspect-only: how many events are buffered waiting for a poll.
|
|
103
|
+
pending() {
|
|
104
|
+
return this.queue.length;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=mock-zone-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-zone-bridge.js","sourceRoot":"","sources":["../../../src/director/zone/mock-zone-bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ZoneEvent } from './zone-event-envelope.js';
|
|
2
|
+
import { type IZoneEventBridge, type ZoneEventBridgeStatus, type ZoneEventBridgeStats } from './zone-event-bridge.js';
|
|
3
|
+
export interface SSEZoneBridgeEventSource {
|
|
4
|
+
readonly readyState: number;
|
|
5
|
+
addEventListener(type: string, listener: (event: {
|
|
6
|
+
data?: unknown;
|
|
7
|
+
}) => void): void;
|
|
8
|
+
removeEventListener?(type: string, listener: (event: {
|
|
9
|
+
data?: unknown;
|
|
10
|
+
}) => void): void;
|
|
11
|
+
}
|
|
12
|
+
export interface SSEZoneBridgeOptions {
|
|
13
|
+
eventSource: SSEZoneBridgeEventSource;
|
|
14
|
+
characterId: string;
|
|
15
|
+
currentZone: () => string;
|
|
16
|
+
eventName?: string;
|
|
17
|
+
filterAtReceive?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare class SSEZoneBridge implements IZoneEventBridge {
|
|
20
|
+
private readonly es;
|
|
21
|
+
private readonly characterId;
|
|
22
|
+
private readonly currentZone;
|
|
23
|
+
private readonly eventName;
|
|
24
|
+
private readonly filterAtReceive;
|
|
25
|
+
private listener;
|
|
26
|
+
private queue;
|
|
27
|
+
private statusValue;
|
|
28
|
+
private readonly lastEventIdByZone;
|
|
29
|
+
private readonly statsValue;
|
|
30
|
+
constructor(opts: SSEZoneBridgeOptions);
|
|
31
|
+
start(): void;
|
|
32
|
+
stop(): void;
|
|
33
|
+
status(): ZoneEventBridgeStatus;
|
|
34
|
+
isConnected(): boolean;
|
|
35
|
+
getLastEventId(zone: string): number;
|
|
36
|
+
pollEvents(): ZoneEvent[];
|
|
37
|
+
stats(): Readonly<ZoneEventBridgeStats>;
|
|
38
|
+
private handleRaw;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=sse-zone-bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-zone-bridge.d.ts","sourceRoot":"","sources":["../../../src/director/zone/sse-zone-bridge.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAC1B,MAAM,wBAAwB,CAAC;AAIhC,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,GAC5C,IAAI,CAAC;IACR,mBAAmB,CAAC,CAClB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,GAC5C,IAAI,CAAC;CAGT;AAED,MAAM,WAAW,oBAAoB;IAInC,WAAW,EAAE,wBAAwB,CAAC;IAItC,WAAW,EAAE,MAAM,CAAC;IAMpB,WAAW,EAAE,MAAM,MAAM,CAAC;IAG1B,SAAS,CAAC,EAAE,MAAM,CAAC;IAInB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAOD,qBAAa,aAAc,YAAW,gBAAgB;IACpD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAA2B;IAC9C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAe;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAU;IAE1C,OAAO,CAAC,QAAQ,CAAsD;IACtE,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAkC;IACpE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAYzB;gBAEU,IAAI,EAAE,oBAAoB;IAWtC,KAAK,IAAI,IAAI;IAeb,IAAI,IAAI,IAAI;IAQZ,MAAM,IAAI,qBAAqB;IAe/B,WAAW,IAAI,OAAO;IAItB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIpC,UAAU,IAAI,SAAS,EAAE;IAOzB,KAAK,IAAI,QAAQ,CAAC,oBAAoB,CAAC;IAavC,OAAO,CAAC,SAAS;CA6BlB"}
|