@alife-sdk/core 0.1.1 → 0.3.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.
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Behavior Tree — hierarchical AI task composition.
3
+ *
4
+ * Pairs well with GOAP: GOAP decides *what* goal to pursue, the BT decides
5
+ * *how* to execute it step by step. The BT is driven externally by calling
6
+ * `tree.tick(blackboard)` each frame or simulation step.
7
+ *
8
+ * Node types:
9
+ * Composites — Sequence, Selector, Parallel
10
+ * Decorators — Inverter, Repeater, AlwaysSucceed, AlwaysFail, Cooldown
11
+ * Leaves — Task (action), Condition
12
+ *
13
+ * Blackboard:
14
+ * Typed key-value store shared across all nodes in one tick. Nodes read
15
+ * perception data from it and write intermediate results to it.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const bb = new Blackboard({ canSeeTarget: false, ammoCount: 10 });
20
+ *
21
+ * const tree = new Selector([
22
+ * new Sequence([
23
+ * new Condition((bb) => bb.get('canSeeTarget')),
24
+ * new Condition((bb) => bb.get('ammoCount') > 0),
25
+ * new Task((bb) => { shoot(); return 'success'; }),
26
+ * ]),
27
+ * new Task(() => { patrol(); return 'running'; }),
28
+ * ]);
29
+ *
30
+ * // Each frame:
31
+ * tree.tick(bb);
32
+ * ```
33
+ */
34
+ /** Result returned by every node's `tick()`. */
35
+ export type TaskStatus = 'success' | 'failure' | 'running';
36
+ /**
37
+ * Typed key-value store shared across all nodes during a single tick.
38
+ *
39
+ * Initialize it with a plain object; the keys become the allowed set of keys
40
+ * via the generic type parameter.
41
+ */
42
+ export declare class Blackboard<T extends Record<string, unknown> = Record<string, unknown>> {
43
+ private readonly data;
44
+ constructor(initial?: Partial<T>);
45
+ get<K extends keyof T>(key: K): T[K] | undefined;
46
+ set<K extends keyof T>(key: K, value: T[K]): void;
47
+ has(key: keyof T): boolean;
48
+ delete(key: keyof T): void;
49
+ }
50
+ /** Every node in the tree implements this single interface. */
51
+ export interface ITreeNode<TBB extends Blackboard = Blackboard> {
52
+ tick(blackboard: TBB): TaskStatus;
53
+ }
54
+ /**
55
+ * Task (action leaf).
56
+ * Runs an arbitrary callback; the callback returns the status directly.
57
+ */
58
+ export declare class Task<TBB extends Blackboard = Blackboard> implements ITreeNode<TBB> {
59
+ private readonly action;
60
+ constructor(action: (bb: TBB) => TaskStatus);
61
+ tick(bb: TBB): TaskStatus;
62
+ }
63
+ /**
64
+ * Condition (boolean leaf).
65
+ * Returns 'success' when the predicate is true, 'failure' otherwise.
66
+ */
67
+ export declare class Condition<TBB extends Blackboard = Blackboard> implements ITreeNode<TBB> {
68
+ private readonly predicate;
69
+ constructor(predicate: (bb: TBB) => boolean);
70
+ tick(bb: TBB): TaskStatus;
71
+ }
72
+ /**
73
+ * Sequence — AND gate.
74
+ * Ticks children left-to-right. Returns 'failure' on the first failing child,
75
+ * 'running' on the first running child, 'success' when all succeed.
76
+ */
77
+ export declare class Sequence<TBB extends Blackboard = Blackboard> implements ITreeNode<TBB> {
78
+ private readonly children;
79
+ constructor(children: ITreeNode<TBB>[]);
80
+ tick(bb: TBB): TaskStatus;
81
+ }
82
+ /**
83
+ * Selector — OR gate.
84
+ * Ticks children left-to-right. Returns 'success' on the first succeeding
85
+ * child, 'running' on the first running child, 'failure' when all fail.
86
+ */
87
+ export declare class Selector<TBB extends Blackboard = Blackboard> implements ITreeNode<TBB> {
88
+ private readonly children;
89
+ constructor(children: ITreeNode<TBB>[]);
90
+ tick(bb: TBB): TaskStatus;
91
+ }
92
+ /** Policy for the Parallel node. */
93
+ export type ParallelPolicy = 'require-all' | 'require-one';
94
+ /**
95
+ * Parallel — ticks ALL children every tick simultaneously.
96
+ *
97
+ * `require-all` (default — AND semantics):
98
+ * - Success: all children succeed.
99
+ * - Failure: any child fails.
100
+ * - Running: otherwise.
101
+ *
102
+ * `require-one` (OR semantics):
103
+ * - Success: at least one child succeeds.
104
+ * - Failure: all children fail.
105
+ * - Running: otherwise (some running, none succeeded yet).
106
+ */
107
+ export declare class Parallel<TBB extends Blackboard = Blackboard> implements ITreeNode<TBB> {
108
+ private readonly children;
109
+ private readonly successPolicy;
110
+ constructor(children: ITreeNode<TBB>[], successPolicy?: ParallelPolicy);
111
+ tick(bb: TBB): TaskStatus;
112
+ }
113
+ /**
114
+ * Inverter — flips 'success' ↔ 'failure'; passes 'running' unchanged.
115
+ */
116
+ export declare class Inverter<TBB extends Blackboard = Blackboard> implements ITreeNode<TBB> {
117
+ private readonly child;
118
+ constructor(child: ITreeNode<TBB>);
119
+ tick(bb: TBB): TaskStatus;
120
+ }
121
+ /**
122
+ * AlwaysSucceed — maps any child result to 'success'.
123
+ */
124
+ export declare class AlwaysSucceed<TBB extends Blackboard = Blackboard> implements ITreeNode<TBB> {
125
+ private readonly child;
126
+ constructor(child: ITreeNode<TBB>);
127
+ tick(bb: TBB): TaskStatus;
128
+ }
129
+ /**
130
+ * AlwaysFail — maps any child result to 'failure'.
131
+ */
132
+ export declare class AlwaysFail<TBB extends Blackboard = Blackboard> implements ITreeNode<TBB> {
133
+ private readonly child;
134
+ constructor(child: ITreeNode<TBB>);
135
+ tick(bb: TBB): TaskStatus;
136
+ }
137
+ /**
138
+ * Repeater — ticks its child N times, returning 'success' after all iterations.
139
+ * If the child returns 'failure' the repeater short-circuits with 'failure'.
140
+ * Pass `Infinity` for an endless loop (returns 'running' every tick).
141
+ */
142
+ export declare class Repeater<TBB extends Blackboard = Blackboard> implements ITreeNode<TBB> {
143
+ private readonly child;
144
+ private readonly times;
145
+ private remaining;
146
+ constructor(child: ITreeNode<TBB>, times: number);
147
+ tick(bb: TBB): TaskStatus;
148
+ /** Reset the repeat counter to allow reuse. */
149
+ reset(): void;
150
+ }
151
+ /**
152
+ * Cooldown — blocks its child while a cooldown timer is active.
153
+ *
154
+ * When the cooldown is inactive: ticks the child normally. If the child
155
+ * succeeds, starts the cooldown and returns 'success'. While the cooldown
156
+ * is active: immediately returns 'failure' (the action is on cooldown).
157
+ *
158
+ * `now` defaults to `Date.now` — inject a custom clock for deterministic tests.
159
+ */
160
+ export declare class Cooldown<TBB extends Blackboard = Blackboard> implements ITreeNode<TBB> {
161
+ private readonly child;
162
+ private readonly durationMs;
163
+ private readonly clock;
164
+ private readyAt;
165
+ constructor(child: ITreeNode<TBB>, durationMs: number, clock?: () => number);
166
+ tick(bb: TBB): TaskStatus;
167
+ /** Force the cooldown to expire immediately. */
168
+ reset(): void;
169
+ /** `true` while the cooldown timer is active. */
170
+ get isOnCooldown(): boolean;
171
+ }
172
+ //# sourceMappingURL=BehaviorTree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BehaviorTree.d.ts","sourceRoot":"","sources":["../../src/ai/BehaviorTree.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,275 @@
1
+ /**
2
+ * Behavior Tree — hierarchical AI task composition.
3
+ *
4
+ * Pairs well with GOAP: GOAP decides *what* goal to pursue, the BT decides
5
+ * *how* to execute it step by step. The BT is driven externally by calling
6
+ * `tree.tick(blackboard)` each frame or simulation step.
7
+ *
8
+ * Node types:
9
+ * Composites — Sequence, Selector, Parallel
10
+ * Decorators — Inverter, Repeater, AlwaysSucceed, AlwaysFail, Cooldown
11
+ * Leaves — Task (action), Condition
12
+ *
13
+ * Blackboard:
14
+ * Typed key-value store shared across all nodes in one tick. Nodes read
15
+ * perception data from it and write intermediate results to it.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const bb = new Blackboard({ canSeeTarget: false, ammoCount: 10 });
20
+ *
21
+ * const tree = new Selector([
22
+ * new Sequence([
23
+ * new Condition((bb) => bb.get('canSeeTarget')),
24
+ * new Condition((bb) => bb.get('ammoCount') > 0),
25
+ * new Task((bb) => { shoot(); return 'success'; }),
26
+ * ]),
27
+ * new Task(() => { patrol(); return 'running'; }),
28
+ * ]);
29
+ *
30
+ * // Each frame:
31
+ * tree.tick(bb);
32
+ * ```
33
+ */
34
+ // ---------------------------------------------------------------------------
35
+ // Blackboard
36
+ // ---------------------------------------------------------------------------
37
+ /**
38
+ * Typed key-value store shared across all nodes during a single tick.
39
+ *
40
+ * Initialize it with a plain object; the keys become the allowed set of keys
41
+ * via the generic type parameter.
42
+ */
43
+ export class Blackboard {
44
+ constructor(initial = {}) {
45
+ this.data = new Map(Object.entries(initial));
46
+ }
47
+ get(key) {
48
+ return this.data.get(key);
49
+ }
50
+ set(key, value) {
51
+ this.data.set(key, value);
52
+ }
53
+ has(key) {
54
+ return this.data.has(key);
55
+ }
56
+ delete(key) {
57
+ this.data.delete(key);
58
+ }
59
+ }
60
+ // ---------------------------------------------------------------------------
61
+ // Leaf nodes
62
+ // ---------------------------------------------------------------------------
63
+ /**
64
+ * Task (action leaf).
65
+ * Runs an arbitrary callback; the callback returns the status directly.
66
+ */
67
+ export class Task {
68
+ constructor(action) {
69
+ this.action = action;
70
+ }
71
+ tick(bb) {
72
+ return this.action(bb);
73
+ }
74
+ }
75
+ /**
76
+ * Condition (boolean leaf).
77
+ * Returns 'success' when the predicate is true, 'failure' otherwise.
78
+ */
79
+ export class Condition {
80
+ constructor(predicate) {
81
+ this.predicate = predicate;
82
+ }
83
+ tick(bb) {
84
+ return this.predicate(bb) ? 'success' : 'failure';
85
+ }
86
+ }
87
+ // ---------------------------------------------------------------------------
88
+ // Composite nodes
89
+ // ---------------------------------------------------------------------------
90
+ /**
91
+ * Sequence — AND gate.
92
+ * Ticks children left-to-right. Returns 'failure' on the first failing child,
93
+ * 'running' on the first running child, 'success' when all succeed.
94
+ */
95
+ export class Sequence {
96
+ constructor(children) {
97
+ this.children = children;
98
+ }
99
+ tick(bb) {
100
+ for (const child of this.children) {
101
+ const status = child.tick(bb);
102
+ if (status !== 'success')
103
+ return status;
104
+ }
105
+ return 'success';
106
+ }
107
+ }
108
+ /**
109
+ * Selector — OR gate.
110
+ * Ticks children left-to-right. Returns 'success' on the first succeeding
111
+ * child, 'running' on the first running child, 'failure' when all fail.
112
+ */
113
+ export class Selector {
114
+ constructor(children) {
115
+ this.children = children;
116
+ }
117
+ tick(bb) {
118
+ for (const child of this.children) {
119
+ const status = child.tick(bb);
120
+ if (status !== 'failure')
121
+ return status;
122
+ }
123
+ return 'failure';
124
+ }
125
+ }
126
+ /**
127
+ * Parallel — ticks ALL children every tick simultaneously.
128
+ *
129
+ * `require-all` (default — AND semantics):
130
+ * - Success: all children succeed.
131
+ * - Failure: any child fails.
132
+ * - Running: otherwise.
133
+ *
134
+ * `require-one` (OR semantics):
135
+ * - Success: at least one child succeeds.
136
+ * - Failure: all children fail.
137
+ * - Running: otherwise (some running, none succeeded yet).
138
+ */
139
+ export class Parallel {
140
+ constructor(children, successPolicy = 'require-all') {
141
+ this.children = children;
142
+ this.successPolicy = successPolicy;
143
+ }
144
+ tick(bb) {
145
+ let successCount = 0;
146
+ let failureCount = 0;
147
+ for (const child of this.children) {
148
+ const status = child.tick(bb);
149
+ if (status === 'success')
150
+ successCount++;
151
+ else if (status === 'failure')
152
+ failureCount++;
153
+ }
154
+ if (this.successPolicy === 'require-all') {
155
+ if (failureCount > 0)
156
+ return 'failure';
157
+ if (successCount === this.children.length)
158
+ return 'success';
159
+ }
160
+ else {
161
+ if (successCount > 0)
162
+ return 'success';
163
+ if (failureCount === this.children.length)
164
+ return 'failure';
165
+ }
166
+ return 'running';
167
+ }
168
+ }
169
+ // ---------------------------------------------------------------------------
170
+ // Decorator nodes
171
+ // ---------------------------------------------------------------------------
172
+ /**
173
+ * Inverter — flips 'success' ↔ 'failure'; passes 'running' unchanged.
174
+ */
175
+ export class Inverter {
176
+ constructor(child) {
177
+ this.child = child;
178
+ }
179
+ tick(bb) {
180
+ const status = this.child.tick(bb);
181
+ if (status === 'success')
182
+ return 'failure';
183
+ if (status === 'failure')
184
+ return 'success';
185
+ return 'running';
186
+ }
187
+ }
188
+ /**
189
+ * AlwaysSucceed — maps any child result to 'success'.
190
+ */
191
+ export class AlwaysSucceed {
192
+ constructor(child) {
193
+ this.child = child;
194
+ }
195
+ tick(bb) {
196
+ this.child.tick(bb);
197
+ return 'success';
198
+ }
199
+ }
200
+ /**
201
+ * AlwaysFail — maps any child result to 'failure'.
202
+ */
203
+ export class AlwaysFail {
204
+ constructor(child) {
205
+ this.child = child;
206
+ }
207
+ tick(bb) {
208
+ this.child.tick(bb);
209
+ return 'failure';
210
+ }
211
+ }
212
+ /**
213
+ * Repeater — ticks its child N times, returning 'success' after all iterations.
214
+ * If the child returns 'failure' the repeater short-circuits with 'failure'.
215
+ * Pass `Infinity` for an endless loop (returns 'running' every tick).
216
+ */
217
+ export class Repeater {
218
+ constructor(child, times) {
219
+ this.child = child;
220
+ this.times = times;
221
+ this.remaining = times;
222
+ }
223
+ tick(bb) {
224
+ if (this.remaining <= 0)
225
+ return 'success';
226
+ const status = this.child.tick(bb);
227
+ if (status === 'failure')
228
+ return 'failure';
229
+ if (status === 'success') {
230
+ this.remaining--;
231
+ if (this.remaining <= 0)
232
+ return 'success';
233
+ }
234
+ return 'running';
235
+ }
236
+ /** Reset the repeat counter to allow reuse. */
237
+ reset() {
238
+ this.remaining = this.times;
239
+ }
240
+ }
241
+ /**
242
+ * Cooldown — blocks its child while a cooldown timer is active.
243
+ *
244
+ * When the cooldown is inactive: ticks the child normally. If the child
245
+ * succeeds, starts the cooldown and returns 'success'. While the cooldown
246
+ * is active: immediately returns 'failure' (the action is on cooldown).
247
+ *
248
+ * `now` defaults to `Date.now` — inject a custom clock for deterministic tests.
249
+ */
250
+ export class Cooldown {
251
+ constructor(child, durationMs, clock = Date.now) {
252
+ this.child = child;
253
+ this.durationMs = durationMs;
254
+ this.clock = clock;
255
+ this.readyAt = 0;
256
+ }
257
+ tick(bb) {
258
+ if (this.clock() < this.readyAt)
259
+ return 'failure';
260
+ const status = this.child.tick(bb);
261
+ if (status === 'success') {
262
+ this.readyAt = this.clock() + this.durationMs;
263
+ }
264
+ return status;
265
+ }
266
+ /** Force the cooldown to expire immediately. */
267
+ reset() {
268
+ this.readyAt = 0;
269
+ }
270
+ /** `true` while the cooldown timer is active. */
271
+ get isOnCooldown() {
272
+ return this.clock() < this.readyAt;
273
+ }
274
+ }
275
+ //# sourceMappingURL=BehaviorTree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BehaviorTree.js","sourceRoot":"","sources":["../../src/ai/BehaviorTree.ts"],"names":[],"mappings":"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"}
@@ -18,13 +18,51 @@ export type TransitionResult = {
18
18
  readonly success: false;
19
19
  readonly reason: 'not_allowed' | 'exit_guard' | 'enter_guard';
20
20
  };
21
+ export interface StateTransitionEvent {
22
+ readonly from: string;
23
+ readonly to: string;
24
+ readonly timestamp: number;
25
+ }
21
26
  export declare class StateMachine {
22
27
  private currentStateId;
28
+ private previousStateId;
29
+ private stateEnterTime;
23
30
  private readonly registry;
24
31
  private readonly entity;
32
+ private readonly enterListeners;
33
+ private readonly exitListeners;
34
+ private readonly changeListeners;
35
+ private readonly historyLog;
25
36
  constructor(entity: IEntity, registry: AIStateRegistry, initialState: string);
26
37
  /** Current active state identifier. */
27
38
  get state(): string;
39
+ /** Previous state identifier, or `null` if no transition has occurred yet. */
40
+ get previous(): string | null;
41
+ /** Milliseconds elapsed since entering the current state. */
42
+ get currentStateDuration(): number;
43
+ /** Returns `true` if the current state has the given tag. */
44
+ hasTag(tag: string): boolean;
45
+ /** Returns the metadata object of the current state, or `undefined`. */
46
+ get metadata(): Readonly<Record<string, unknown>> | undefined;
47
+ /**
48
+ * Subscribe to the moment the FSM enters `state`.
49
+ * @returns Unsubscribe function.
50
+ */
51
+ onEnter(state: string, callback: (from: string | null) => void): () => void;
52
+ /**
53
+ * Subscribe to the moment the FSM exits `state`.
54
+ * @returns Unsubscribe function.
55
+ */
56
+ onExit(state: string, callback: (to: string) => void): () => void;
57
+ /**
58
+ * Subscribe to any state change.
59
+ * @returns Unsubscribe function.
60
+ */
61
+ onChange(callback: (from: string, to: string) => void): () => void;
62
+ /** Returns a snapshot of the transition history (oldest first). */
63
+ getHistory(): readonly StateTransitionEvent[];
64
+ /** Clears the transition history. */
65
+ clearHistory(): void;
28
66
  /**
29
67
  * Force transition to a new state.
30
68
  *
@@ -1 +1 @@
1
- {"version":3,"file":"StateMachine.d.ts","sourceRoot":"","sources":["../../src/ai/StateMachine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnE,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAA;CAAE,GAC1B;IAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,YAAY,GAAG,aAAa,CAAA;CAAE,CAAC;AAE/F,qBAAa,YAAY;IACvB,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;gBAErB,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM;IAa5E,uCAAuC;IACvC,IAAI,KAAK,IAAI,MAAM,CAElB;IAMD;;;;;;OAMG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB;IAsB9C;;;;;;;;OAQG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAkB3B,iEAAiE;IACjE,OAAO,IAAI,IAAI;CAIhB"}
1
+ {"version":3,"file":"StateMachine.d.ts","sourceRoot":"","sources":["../../src/ai/StateMachine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnE,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAA;CAAE,GAC1B;IAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,YAAY,GAAG,aAAa,CAAA;CAAE,CAAC;AAE/F,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IAEjC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyD;IACxF,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgD;IAC9E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAiD;IACjF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA8B;gBAE7C,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM;IAc5E,uCAAuC;IACvC,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,8EAA8E;IAC9E,IAAI,QAAQ,IAAI,MAAM,GAAG,IAAI,CAE5B;IAED,6DAA6D;IAC7D,IAAI,oBAAoB,IAAI,MAAM,CAEjC;IAMD,6DAA6D;IAC7D,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAK5B,wEAAwE;IACxE,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAE5D;IAMD;;;OAGG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,MAAM,IAAI;IAM3E;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI;IAMjE;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI;IASlE,mEAAmE;IACnE,UAAU,IAAI,SAAS,oBAAoB,EAAE;IAI7C,qCAAqC;IACrC,YAAY,IAAI,IAAI;IAQpB;;;;;;OAMG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB;IAwC9C;;;;;;;;OAQG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAkB3B,iEAAiE;IACjE,OAAO,IAAI,IAAI;CAIhB"}
@@ -12,9 +12,15 @@
12
12
  */
13
13
  export class StateMachine {
14
14
  constructor(entity, registry, initialState) {
15
+ this.previousStateId = null;
16
+ this.enterListeners = new Map();
17
+ this.exitListeners = new Map();
18
+ this.changeListeners = new Set();
19
+ this.historyLog = [];
15
20
  this.entity = entity;
16
21
  this.registry = registry;
17
22
  this.currentStateId = initialState;
23
+ this.stateEnterTime = Date.now();
18
24
  const definition = this.registry.get(this.currentStateId);
19
25
  definition.handler.enter(this.entity);
20
26
  }
@@ -25,6 +31,68 @@ export class StateMachine {
25
31
  get state() {
26
32
  return this.currentStateId;
27
33
  }
34
+ /** Previous state identifier, or `null` if no transition has occurred yet. */
35
+ get previous() {
36
+ return this.previousStateId;
37
+ }
38
+ /** Milliseconds elapsed since entering the current state. */
39
+ get currentStateDuration() {
40
+ return Date.now() - this.stateEnterTime;
41
+ }
42
+ // -----------------------------------------------------------------------
43
+ // Tag queries
44
+ // -----------------------------------------------------------------------
45
+ /** Returns `true` if the current state has the given tag. */
46
+ hasTag(tag) {
47
+ const def = this.registry.tryGet(this.currentStateId);
48
+ return def?.tags?.includes(tag) ?? false;
49
+ }
50
+ /** Returns the metadata object of the current state, or `undefined`. */
51
+ get metadata() {
52
+ return this.registry.tryGet(this.currentStateId)?.metadata;
53
+ }
54
+ // -----------------------------------------------------------------------
55
+ // Event subscriptions
56
+ // -----------------------------------------------------------------------
57
+ /**
58
+ * Subscribe to the moment the FSM enters `state`.
59
+ * @returns Unsubscribe function.
60
+ */
61
+ onEnter(state, callback) {
62
+ if (!this.enterListeners.has(state))
63
+ this.enterListeners.set(state, new Set());
64
+ this.enterListeners.get(state).add(callback);
65
+ return () => this.enterListeners.get(state)?.delete(callback);
66
+ }
67
+ /**
68
+ * Subscribe to the moment the FSM exits `state`.
69
+ * @returns Unsubscribe function.
70
+ */
71
+ onExit(state, callback) {
72
+ if (!this.exitListeners.has(state))
73
+ this.exitListeners.set(state, new Set());
74
+ this.exitListeners.get(state).add(callback);
75
+ return () => this.exitListeners.get(state)?.delete(callback);
76
+ }
77
+ /**
78
+ * Subscribe to any state change.
79
+ * @returns Unsubscribe function.
80
+ */
81
+ onChange(callback) {
82
+ this.changeListeners.add(callback);
83
+ return () => this.changeListeners.delete(callback);
84
+ }
85
+ // -----------------------------------------------------------------------
86
+ // History
87
+ // -----------------------------------------------------------------------
88
+ /** Returns a snapshot of the transition history (oldest first). */
89
+ getHistory() {
90
+ return [...this.historyLog];
91
+ }
92
+ /** Clears the transition history. */
93
+ clearHistory() {
94
+ this.historyLog.length = 0;
95
+ }
28
96
  // -----------------------------------------------------------------------
29
97
  // Transitions
30
98
  // -----------------------------------------------------------------------
@@ -46,9 +114,21 @@ export class StateMachine {
46
114
  return { success: false, reason: 'exit_guard' };
47
115
  if (newDefinition.canEnter?.(this.entity, this.currentStateId) === false)
48
116
  return { success: false, reason: 'enter_guard' };
117
+ const from = this.currentStateId;
118
+ // Exit
49
119
  oldDefinition.handler.exit(this.entity);
120
+ this.exitListeners.get(from)?.forEach(cb => cb(newState));
121
+ // Advance state
122
+ this.previousStateId = from;
50
123
  this.currentStateId = newState;
124
+ this.stateEnterTime = Date.now();
125
+ // Record history
126
+ this.historyLog.push({ from, to: newState, timestamp: this.stateEnterTime });
127
+ // Notify change listeners
128
+ this.changeListeners.forEach(cb => cb(from, newState));
129
+ // Enter
51
130
  newDefinition.handler.enter(this.entity);
131
+ this.enterListeners.get(newState)?.forEach(cb => cb(from));
52
132
  return { success: true };
53
133
  }
54
134
  // -----------------------------------------------------------------------
@@ -1 +1 @@
1
- {"version":3,"file":"StateMachine.js","sourceRoot":"","sources":["../../src/ai/StateMachine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AASH,MAAM,OAAO,YAAY;IAKvB,YAAY,MAAe,EAAE,QAAyB,EAAE,YAAoB;QAC1E,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,cAAc,GAAG,YAAY,CAAC;QAEnC,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC1D,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IAED,0EAA0E;IAC1E,YAAY;IACZ,0EAA0E;IAE1E,uCAAuC;IACvC,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,0EAA0E;IAC1E,cAAc;IACd,0EAA0E;IAE1E;;;;;;OAMG;IACH,UAAU,CAAC,QAAgB;QACzB,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC7D,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAElD,oFAAoF;QACpF,IAAI,aAAa,CAAC,kBAAkB,IAAI,CAAC,aAAa,CAAC,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7F,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;QACnD,CAAC;QAED,IAAI,aAAa,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAK,KAAK;YAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;QAC9G,IAAI,aAAa,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,CAAC,KAAK,KAAK;YAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;QAE3H,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,CAAC,cAAc,GAAG,QAAQ,CAAC;QAC/B,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,0EAA0E;IAC1E,SAAS;IACT,0EAA0E;IAE1E;;;;;;;;OAQG;IACH,MAAM,CAAC,KAAa;QAClB,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC1D,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAE9C,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CACjD,IAAI,CAAC,cAAc,EACnB,IAAI,CAAC,MAAM,CACZ,CAAC;QAEF,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,UAAU;IACV,0EAA0E;IAE1E,iEAAiE;IACjE,OAAO;QACL,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC1D,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;CACF"}
1
+ {"version":3,"file":"StateMachine.js","sourceRoot":"","sources":["../../src/ai/StateMachine.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  export { StateMachine } from './StateMachine';
2
- export type { TransitionResult } from './StateMachine';
2
+ export type { TransitionResult, StateTransitionEvent } from './StateMachine';
3
3
  export { MemoryBank, MemoryChannel } from './MemorySystem';
4
4
  export type { MemoryRecord, IMemoryBankConfig, IMemoryInput } from './MemorySystem';
5
5
  export { DangerManager, DangerType } from './DangerManager';
@@ -7,4 +7,6 @@ export type { IDangerEntry } from './DangerManager';
7
7
  export { WorldState } from './WorldState';
8
8
  export { GOAPPlanner } from './GOAPPlanner';
9
9
  export { GOAPAction, ActionStatus } from './GOAPAction';
10
+ export { Blackboard, Task, Condition, Sequence, Selector, Parallel, Inverter, AlwaysSucceed, AlwaysFail, Repeater, Cooldown } from './BehaviorTree';
11
+ export type { TaskStatus, ITreeNode, ParallelPolicy } from './BehaviorTree';
10
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC3D,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC3D,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACpJ,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/ai/index.js CHANGED
@@ -5,4 +5,5 @@ export { DangerManager, DangerType } from './DangerManager';
5
5
  export { WorldState } from './WorldState';
6
6
  export { GOAPPlanner } from './GOAPPlanner';
7
7
  export { GOAPAction, ActionStatus } from './GOAPAction';
8
+ export { Blackboard, Task, Condition, Sequence, Selector, Parallel, Inverter, AlwaysSucceed, AlwaysFail, Repeater, Cooldown } from './BehaviorTree';
8
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE5D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE5D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * ReactiveQuery — observe when entities enter and exit a filtered set.
3
+ *
4
+ * Instead of polling the entire entity set every frame, a ReactiveQuery
5
+ * maintains a stable "matched" set and fires change notifications only when
6
+ * entities enter or leave the query (i.e. when the predicate result changes).
7
+ *
8
+ * Usage pattern:
9
+ * 1. Create a query with a predicate.
10
+ * 2. Subscribe to `onChange` to react to structural changes.
11
+ * 3. Call `update(allEntities)` each tick to re-evaluate.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const hostileQuery = new ReactiveQuery<IEntity>(
16
+ * (e) => e.isAlive && e.hasComponent('hostile')
17
+ * );
18
+ *
19
+ * hostileQuery.onChange(({ added, removed }) => {
20
+ * added.forEach(e => combatSystem.track(e));
21
+ * removed.forEach(e => combatSystem.untrack(e));
22
+ * });
23
+ *
24
+ * // Each tick:
25
+ * hostileQuery.update(world.entities());
26
+ * ```
27
+ */
28
+ /** Changes detected since the last `update()` call. */
29
+ export interface QueryChanges<T> {
30
+ /** Entities that newly matched the predicate this update. */
31
+ readonly added: readonly T[];
32
+ /** Entities that no longer match the predicate this update. */
33
+ readonly removed: readonly T[];
34
+ /** All entities currently matching the predicate after this update. */
35
+ readonly current: readonly T[];
36
+ }
37
+ /** Callback invoked when any entities are added or removed from the query. */
38
+ export type QueryChangeListener<T> = (changes: QueryChanges<T>) => void;
39
+ /**
40
+ * Tracks which entities satisfy a predicate and fires change events when
41
+ * the matched set changes.
42
+ */
43
+ export declare class ReactiveQuery<T> {
44
+ private readonly predicate;
45
+ private readonly matched;
46
+ private readonly listeners;
47
+ constructor(predicate: (entity: T) => boolean);
48
+ /**
49
+ * Re-evaluate the predicate against `allEntities`.
50
+ *
51
+ * Fires `onChange` listeners if the matched set changed.
52
+ * Call this once per tick from the owning system.
53
+ */
54
+ update(allEntities: Iterable<T>): void;
55
+ /**
56
+ * Subscribe to change events. Called whenever entities enter or exit the
57
+ * matched set.
58
+ *
59
+ * @returns Unsubscribe function.
60
+ */
61
+ onChange(listener: QueryChangeListener<T>): () => void;
62
+ /** All entities currently matching the predicate (stable snapshot). */
63
+ get current(): readonly T[];
64
+ /** Number of currently matched entities. */
65
+ get size(): number;
66
+ /** Return `true` if the entity is currently in the matched set. */
67
+ has(entity: T): boolean;
68
+ /**
69
+ * Manually add an entity to the matched set without re-evaluating the
70
+ * predicate. Fires `onChange` with the single addition.
71
+ *
72
+ * Useful when external code creates entities and knows they should match.
73
+ */
74
+ track(entity: T): void;
75
+ /**
76
+ * Manually remove an entity from the matched set.
77
+ * Fires `onChange` with the single removal.
78
+ *
79
+ * Useful when entities are destroyed mid-tick.
80
+ */
81
+ untrack(entity: T): void;
82
+ /** Remove all entities and clear all listeners. */
83
+ dispose(): void;
84
+ }
85
+ //# sourceMappingURL=ReactiveQuery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReactiveQuery.d.ts","sourceRoot":"","sources":["../../src/core/ReactiveQuery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAMH,uDAAuD;AACvD,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;IAC7B,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;IAC/B,uEAAuE;IACvE,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;CAChC;AAED,8EAA8E;AAC9E,MAAM,MAAM,mBAAmB,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;AAMxE;;;GAGG;AACH,qBAAa,aAAa,CAAC,CAAC;IAId,OAAO,CAAC,QAAQ,CAAC,SAAS;IAHtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqC;gBAElC,SAAS,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO;IAM9D;;;;;OAKG;IACH,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI;IAwCtC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAStD,uEAAuE;IACvE,IAAI,OAAO,IAAI,SAAS,CAAC,EAAE,CAE1B;IAED,4CAA4C;IAC5C,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,mEAAmE;IACnE,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,OAAO;IAIvB;;;;;OAKG;IACH,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI;IAatB;;;;;OAKG;IACH,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI;IAaxB,mDAAmD;IACnD,OAAO,IAAI,IAAI;CAIhB"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * ReactiveQuery — observe when entities enter and exit a filtered set.
3
+ *
4
+ * Instead of polling the entire entity set every frame, a ReactiveQuery
5
+ * maintains a stable "matched" set and fires change notifications only when
6
+ * entities enter or leave the query (i.e. when the predicate result changes).
7
+ *
8
+ * Usage pattern:
9
+ * 1. Create a query with a predicate.
10
+ * 2. Subscribe to `onChange` to react to structural changes.
11
+ * 3. Call `update(allEntities)` each tick to re-evaluate.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const hostileQuery = new ReactiveQuery<IEntity>(
16
+ * (e) => e.isAlive && e.hasComponent('hostile')
17
+ * );
18
+ *
19
+ * hostileQuery.onChange(({ added, removed }) => {
20
+ * added.forEach(e => combatSystem.track(e));
21
+ * removed.forEach(e => combatSystem.untrack(e));
22
+ * });
23
+ *
24
+ * // Each tick:
25
+ * hostileQuery.update(world.entities());
26
+ * ```
27
+ */
28
+ // ---------------------------------------------------------------------------
29
+ // ReactiveQuery
30
+ // ---------------------------------------------------------------------------
31
+ /**
32
+ * Tracks which entities satisfy a predicate and fires change events when
33
+ * the matched set changes.
34
+ */
35
+ export class ReactiveQuery {
36
+ constructor(predicate) {
37
+ this.predicate = predicate;
38
+ this.matched = new Set();
39
+ this.listeners = new Set();
40
+ }
41
+ // -------------------------------------------------------------------------
42
+ // Update
43
+ // -------------------------------------------------------------------------
44
+ /**
45
+ * Re-evaluate the predicate against `allEntities`.
46
+ *
47
+ * Fires `onChange` listeners if the matched set changed.
48
+ * Call this once per tick from the owning system.
49
+ */
50
+ update(allEntities) {
51
+ const added = [];
52
+ const removed = [];
53
+ const nextMatched = new Set();
54
+ for (const entity of allEntities) {
55
+ if (this.predicate(entity)) {
56
+ nextMatched.add(entity);
57
+ if (!this.matched.has(entity)) {
58
+ added.push(entity);
59
+ }
60
+ }
61
+ }
62
+ for (const entity of this.matched) {
63
+ if (!nextMatched.has(entity)) {
64
+ removed.push(entity);
65
+ }
66
+ }
67
+ // Commit new matched set
68
+ this.matched.clear();
69
+ for (const e of nextMatched)
70
+ this.matched.add(e);
71
+ if (added.length > 0 || removed.length > 0) {
72
+ const changes = {
73
+ added,
74
+ removed,
75
+ current: [...this.matched],
76
+ };
77
+ for (const listener of this.listeners) {
78
+ listener(changes);
79
+ }
80
+ }
81
+ }
82
+ // -------------------------------------------------------------------------
83
+ // Subscriptions
84
+ // -------------------------------------------------------------------------
85
+ /**
86
+ * Subscribe to change events. Called whenever entities enter or exit the
87
+ * matched set.
88
+ *
89
+ * @returns Unsubscribe function.
90
+ */
91
+ onChange(listener) {
92
+ this.listeners.add(listener);
93
+ return () => this.listeners.delete(listener);
94
+ }
95
+ // -------------------------------------------------------------------------
96
+ // Accessors
97
+ // -------------------------------------------------------------------------
98
+ /** All entities currently matching the predicate (stable snapshot). */
99
+ get current() {
100
+ return [...this.matched];
101
+ }
102
+ /** Number of currently matched entities. */
103
+ get size() {
104
+ return this.matched.size;
105
+ }
106
+ /** Return `true` if the entity is currently in the matched set. */
107
+ has(entity) {
108
+ return this.matched.has(entity);
109
+ }
110
+ /**
111
+ * Manually add an entity to the matched set without re-evaluating the
112
+ * predicate. Fires `onChange` with the single addition.
113
+ *
114
+ * Useful when external code creates entities and knows they should match.
115
+ */
116
+ track(entity) {
117
+ if (this.matched.has(entity))
118
+ return;
119
+ this.matched.add(entity);
120
+ const changes = {
121
+ added: [entity],
122
+ removed: [],
123
+ current: [...this.matched],
124
+ };
125
+ for (const listener of this.listeners) {
126
+ listener(changes);
127
+ }
128
+ }
129
+ /**
130
+ * Manually remove an entity from the matched set.
131
+ * Fires `onChange` with the single removal.
132
+ *
133
+ * Useful when entities are destroyed mid-tick.
134
+ */
135
+ untrack(entity) {
136
+ if (!this.matched.has(entity))
137
+ return;
138
+ this.matched.delete(entity);
139
+ const changes = {
140
+ added: [],
141
+ removed: [entity],
142
+ current: [...this.matched],
143
+ };
144
+ for (const listener of this.listeners) {
145
+ listener(changes);
146
+ }
147
+ }
148
+ /** Remove all entities and clear all listeners. */
149
+ dispose() {
150
+ this.matched.clear();
151
+ this.listeners.clear();
152
+ }
153
+ }
154
+ //# sourceMappingURL=ReactiveQuery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReactiveQuery.js","sourceRoot":"","sources":["../../src/core/ReactiveQuery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * EntityHandle — versioned entity references with use-after-free protection.
3
+ *
4
+ * Instead of holding raw entity references that can become dangling after an
5
+ * entity is destroyed, systems hold an EntityHandle. The handle encodes both
6
+ * the entity's slot index and a generation counter. When a slot is reused for
7
+ * a new entity the generation is bumped, making all old handles stale.
8
+ *
9
+ * Bit layout (fits in a JavaScript safe integer):
10
+ * [47..20] generation (28 bits, up to ~268 M versions per slot)
11
+ * [19.. 0] index (20 bits, up to ~1 M concurrent slots)
12
+ *
13
+ * Usage:
14
+ * const manager = new EntityHandleManager();
15
+ * const handle = manager.alloc('wolf-1');
16
+ * manager.resolve(handle); // → 'wolf-1'
17
+ * manager.free(handle);
18
+ * manager.resolve(handle); // → null (stale)
19
+ */
20
+ /** Opaque numeric type that encodes (generation, index). */
21
+ export type EntityHandle = number & {
22
+ readonly __brand: 'EntityHandle';
23
+ };
24
+ /** Sentinel value for an absent or invalid handle. */
25
+ export declare const NULL_HANDLE: EntityHandle;
26
+ /** Pack (index, generation) into a single handle. */
27
+ export declare function makeHandle(index: number, generation: number): EntityHandle;
28
+ /** Extract the slot index from a handle. */
29
+ export declare function indexOf(handle: EntityHandle): number;
30
+ /** Extract the generation counter from a handle. */
31
+ export declare function genOf(handle: EntityHandle): number;
32
+ /** Return `true` if the handle is not the null sentinel. */
33
+ export declare function isValidHandle(handle: EntityHandle): boolean;
34
+ /** Human-readable description for logging / debugging. */
35
+ export declare function handleToString(handle: EntityHandle): string;
36
+ /**
37
+ * Central registry that owns the slot → entity-id mapping.
38
+ *
39
+ * Recycles freed slots so slot count stays bounded. Old handles pointing at
40
+ * recycled slots resolve to `null` because their stored generation no longer
41
+ * matches the slot's current generation.
42
+ */
43
+ export declare class EntityHandleManager<TId = string> {
44
+ /** Generation counter per slot (index = slot index). */
45
+ private readonly generations;
46
+ /** Entity ID stored in each live slot. `null` = free. */
47
+ private readonly ids;
48
+ /** Slot indices available for reuse. */
49
+ private readonly freeList;
50
+ /** Next slot to allocate when freeList is empty. */
51
+ private nextSlot;
52
+ /**
53
+ * Allocate a new handle for the given entity id.
54
+ * @throws if the slot limit is exhausted.
55
+ */
56
+ alloc(id: TId): EntityHandle;
57
+ /**
58
+ * Release a handle, incrementing the slot's generation.
59
+ * All existing handles pointing at this slot become stale.
60
+ *
61
+ * Does nothing (and does not throw) if the handle is already stale.
62
+ */
63
+ free(handle: EntityHandle): void;
64
+ /**
65
+ * Resolve a handle to its entity id.
66
+ * Returns `null` if the handle is stale (entity was freed) or null.
67
+ */
68
+ resolve(handle: EntityHandle): TId | null;
69
+ /**
70
+ * Return `true` if the handle points to a currently-live slot.
71
+ */
72
+ isAlive(handle: EntityHandle): boolean;
73
+ /** Number of currently-live slots. */
74
+ get size(): number;
75
+ }
76
+ //# sourceMappingURL=EntityHandle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EntityHandle.d.ts","sourceRoot":"","sources":["../../src/entity/EntityHandle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAgBH,4DAA4D;AAC5D,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAA;CAAE,CAAC;AAEzE,sDAAsD;AACtD,eAAO,MAAM,WAAW,EAAQ,YAAY,CAAC;AAE7C,qDAAqD;AACrD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,YAAY,CAG1E;AAED,4CAA4C;AAC5C,wBAAgB,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAEpD;AAED,oDAAoD;AACpD,wBAAgB,KAAK,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAElD;AAED,4DAA4D;AAC5D,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAE3D;AAED,0DAA0D;AAC1D,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAG3D;AAMD;;;;;;GAMG;AACH,qBAAa,mBAAmB,CAAC,GAAG,GAAG,MAAM;IAC3C,wDAAwD;IACxD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAgB;IAC5C,yDAAyD;IACzD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAsB;IAC1C,wCAAwC;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IACzC,oDAAoD;IACpD,OAAO,CAAC,QAAQ,CAAK;IAErB;;;OAGG;IACH,KAAK,CAAC,EAAE,EAAE,GAAG,GAAG,YAAY;IAiB5B;;;;;OAKG;IACH,IAAI,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAQhC;;;OAGG;IACH,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,GAAG,GAAG,IAAI;IAOzC;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO;IAMtC,sCAAsC;IACtC,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * EntityHandle — versioned entity references with use-after-free protection.
3
+ *
4
+ * Instead of holding raw entity references that can become dangling after an
5
+ * entity is destroyed, systems hold an EntityHandle. The handle encodes both
6
+ * the entity's slot index and a generation counter. When a slot is reused for
7
+ * a new entity the generation is bumped, making all old handles stale.
8
+ *
9
+ * Bit layout (fits in a JavaScript safe integer):
10
+ * [47..20] generation (28 bits, up to ~268 M versions per slot)
11
+ * [19.. 0] index (20 bits, up to ~1 M concurrent slots)
12
+ *
13
+ * Usage:
14
+ * const manager = new EntityHandleManager();
15
+ * const handle = manager.alloc('wolf-1');
16
+ * manager.resolve(handle); // → 'wolf-1'
17
+ * manager.free(handle);
18
+ * manager.resolve(handle); // → null (stale)
19
+ */
20
+ // ---------------------------------------------------------------------------
21
+ // Bit-layout constants
22
+ // ---------------------------------------------------------------------------
23
+ const INDEX_BITS = 20;
24
+ const GEN_BITS = 28;
25
+ const INDEX_MASK = (1 << INDEX_BITS) - 1; // 0x000FFFFF — 1 048 575 max slots
26
+ const GEN_MASK = (1 << GEN_BITS) - 1; // 0x0FFFFFFF — 268 435 455 max gen
27
+ const MAX_SLOTS = 1 << INDEX_BITS;
28
+ /** Sentinel value for an absent or invalid handle. */
29
+ export const NULL_HANDLE = 0;
30
+ /** Pack (index, generation) into a single handle. */
31
+ export function makeHandle(index, generation) {
32
+ // Use multiplication instead of bit-shift to avoid 32-bit truncation.
33
+ return ((generation & GEN_MASK) * MAX_SLOTS + (index & INDEX_MASK));
34
+ }
35
+ /** Extract the slot index from a handle. */
36
+ export function indexOf(handle) {
37
+ return handle & INDEX_MASK;
38
+ }
39
+ /** Extract the generation counter from a handle. */
40
+ export function genOf(handle) {
41
+ return Math.floor(handle / MAX_SLOTS) & GEN_MASK;
42
+ }
43
+ /** Return `true` if the handle is not the null sentinel. */
44
+ export function isValidHandle(handle) {
45
+ return handle !== NULL_HANDLE;
46
+ }
47
+ /** Human-readable description for logging / debugging. */
48
+ export function handleToString(handle) {
49
+ if (!isValidHandle(handle))
50
+ return 'Entity(NULL)';
51
+ return `Entity(idx=${indexOf(handle)}, gen=${genOf(handle)})`;
52
+ }
53
+ // ---------------------------------------------------------------------------
54
+ // EntityHandleManager
55
+ // ---------------------------------------------------------------------------
56
+ /**
57
+ * Central registry that owns the slot → entity-id mapping.
58
+ *
59
+ * Recycles freed slots so slot count stays bounded. Old handles pointing at
60
+ * recycled slots resolve to `null` because their stored generation no longer
61
+ * matches the slot's current generation.
62
+ */
63
+ export class EntityHandleManager {
64
+ constructor() {
65
+ /** Generation counter per slot (index = slot index). */
66
+ this.generations = [];
67
+ /** Entity ID stored in each live slot. `null` = free. */
68
+ this.ids = [];
69
+ /** Slot indices available for reuse. */
70
+ this.freeList = [];
71
+ /** Next slot to allocate when freeList is empty. */
72
+ this.nextSlot = 0;
73
+ }
74
+ /**
75
+ * Allocate a new handle for the given entity id.
76
+ * @throws if the slot limit is exhausted.
77
+ */
78
+ alloc(id) {
79
+ let index;
80
+ if (this.freeList.length > 0) {
81
+ index = this.freeList.pop();
82
+ }
83
+ else {
84
+ if (this.nextSlot >= MAX_SLOTS) {
85
+ throw new Error(`EntityHandleManager: slot limit (${MAX_SLOTS}) reached`);
86
+ }
87
+ index = this.nextSlot++;
88
+ this.generations[index] = 1;
89
+ }
90
+ this.ids[index] = id;
91
+ return makeHandle(index, this.generations[index]);
92
+ }
93
+ /**
94
+ * Release a handle, incrementing the slot's generation.
95
+ * All existing handles pointing at this slot become stale.
96
+ *
97
+ * Does nothing (and does not throw) if the handle is already stale.
98
+ */
99
+ free(handle) {
100
+ if (!this.isAlive(handle))
101
+ return;
102
+ const index = indexOf(handle);
103
+ this.ids[index] = null;
104
+ this.generations[index] = (this.generations[index] + 1) & GEN_MASK || 1; // skip 0
105
+ this.freeList.push(index);
106
+ }
107
+ /**
108
+ * Resolve a handle to its entity id.
109
+ * Returns `null` if the handle is stale (entity was freed) or null.
110
+ */
111
+ resolve(handle) {
112
+ if (!isValidHandle(handle))
113
+ return null;
114
+ const index = indexOf(handle);
115
+ if (this.generations[index] !== genOf(handle))
116
+ return null;
117
+ return this.ids[index] ?? null;
118
+ }
119
+ /**
120
+ * Return `true` if the handle points to a currently-live slot.
121
+ */
122
+ isAlive(handle) {
123
+ if (!isValidHandle(handle))
124
+ return false;
125
+ const index = indexOf(handle);
126
+ return this.generations[index] === genOf(handle) && this.ids[index] !== null;
127
+ }
128
+ /** Number of currently-live slots. */
129
+ get size() {
130
+ return this.nextSlot - this.freeList.length;
131
+ }
132
+ }
133
+ //# sourceMappingURL=EntityHandle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EntityHandle.js","sourceRoot":"","sources":["../../src/entity/EntityHandle.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,5 @@
1
1
  export type { IEntity } from './IEntity';
2
2
  export type { IComponent } from './IComponent';
3
+ export type { EntityHandle } from './EntityHandle';
4
+ export { NULL_HANDLE, makeHandle, indexOf, genOf, isValidHandle, handleToString, EntityHandleManager, } from './EntityHandle';
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/entity/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/entity/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EACL,WAAW,EACX,UAAU,EACV,OAAO,EACP,KAAK,EACL,aAAa,EACb,cAAc,EACd,mBAAmB,GACpB,MAAM,gBAAgB,CAAC"}
@@ -1,2 +1,2 @@
1
- export {};
1
+ export { NULL_HANDLE, makeHandle, indexOf, genOf, isValidHandle, handleToString, EntityHandleManager, } from './EntityHandle';
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/entity/index.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/entity/index.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,WAAW,EACX,UAAU,EACV,OAAO,EACP,KAAK,EACL,aAAa,EACb,cAAc,EACd,mBAAmB,GACpB,MAAM,gBAAgB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -11,6 +11,8 @@ export { Clock } from './core/Clock';
11
11
  export type { IClockConfig, IClockState } from './core/Clock';
12
12
  export { SpatialGrid } from './core/SpatialGrid';
13
13
  export type { IRect } from './core/SpatialGrid';
14
+ export { ReactiveQuery } from './core/ReactiveQuery';
15
+ export type { QueryChanges, QueryChangeListener } from './core/ReactiveQuery';
14
16
  export type { ISerializable } from './core/ISerializable';
15
17
  export * from './core/math/index';
16
18
  export * from './events/index';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACvE,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC1I,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AACnF,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACpE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAChF,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,YAAY,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAK1D,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACvE,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC1I,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AACnF,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACpE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAChF,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,YAAY,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAK1D,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -11,6 +11,7 @@ export { Ports, REQUIRED_PORTS } from './core/PortTokens';
11
11
  export { DiagnosticsCollector, ALifeValidationError } from './core/Diagnostics';
12
12
  export { Clock } from './core/Clock';
13
13
  export { SpatialGrid } from './core/SpatialGrid';
14
+ export { ReactiveQuery } from './core/ReactiveQuery';
14
15
  // ---------------------------------------------------------------------------
15
16
  // Sub-path re-exports
16
17
  // ---------------------------------------------------------------------------
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,sEAAsE;AACtE,+CAA+C;AAE/C,8EAA8E;AAC9E,mCAAmC;AACnC,8EAA8E;AAC9E,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAEvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEpE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAEhF,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAIjD,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAC9E,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,sEAAsE;AACtE,+CAA+C;AAE/C,8EAA8E;AAC9E,mCAAmC;AACnC,8EAA8E;AAC9E,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAEvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEpE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAEhF,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAIrD,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAC9E,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC"}
@@ -30,6 +30,10 @@ export interface IAIStateDefinition {
30
30
  readonly canEnter?: (entity: IEntity, fromState: string) => boolean;
31
31
  /** Guard: return `false` to prevent leaving this state for `toState`. */
32
32
  readonly canExit?: (entity: IEntity, toState: string) => boolean;
33
+ /** Categorical tags for querying state group membership (e.g. 'combat', 'grounded'). */
34
+ readonly tags?: readonly string[];
35
+ /** Arbitrary metadata for tooling/debugging (e.g. animation hints, priority weights). */
36
+ readonly metadata?: Readonly<Record<string, unknown>>;
33
37
  }
34
38
  /** Registry of AI FSM states with built-in transition evaluation. */
35
39
  export declare class AIStateRegistry extends Registry<string, IAIStateDefinition> {
@@ -1 +1 @@
1
- {"version":3,"file":"AIStateRegistry.d.ts","sourceRoot":"","sources":["../../src/registry/AIStateRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD,iDAAiD;AACjD,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7B,0FAA0F;IAC1F,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,8DAA8D;IAC9D,IAAI,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;CAC7B;AAED,+EAA+E;AAC/E,MAAM,WAAW,oBAAoB;IACnC,6DAA6D;IAC7D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,gFAAgF;IAChF,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IACjD,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,8EAA8E;AAC9E,MAAM,WAAW,kBAAkB;IACjC,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,iFAAiF;IACjF,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChD,iFAAiF;IACjF,QAAQ,CAAC,oBAAoB,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAChE,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IACpE,yEAAyE;IACzE,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;CAClE;AAED,qEAAqE;AACrE,qBAAa,eAAgB,SAAQ,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;;IAKvE,8FAA8F;IACrF,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,IAAI;IAQ/D,8HAA8H;IAC9H,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI;CAS1E"}
1
+ {"version":3,"file":"AIStateRegistry.d.ts","sourceRoot":"","sources":["../../src/registry/AIStateRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD,iDAAiD;AACjD,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7B,0FAA0F;IAC1F,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,8DAA8D;IAC9D,IAAI,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;CAC7B;AAED,+EAA+E;AAC/E,MAAM,WAAW,oBAAoB;IACnC,6DAA6D;IAC7D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,gFAAgF;IAChF,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IACjD,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,8EAA8E;AAC9E,MAAM,WAAW,kBAAkB;IACjC,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,iFAAiF;IACjF,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChD,iFAAiF;IACjF,QAAQ,CAAC,oBAAoB,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAChE,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IACpE,yEAAyE;IACzE,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IACjE,wFAAwF;IACxF,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,yFAAyF;IACzF,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvD;AAED,qEAAqE;AACrE,qBAAa,eAAgB,SAAQ,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;;IAKvE,8FAA8F;IACrF,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,IAAI;IAQ/D,8HAA8H;IAC9H,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI;CAS1E"}
@@ -1 +1 @@
1
- {"version":3,"file":"AIStateRegistry.js","sourceRoot":"","sources":["../../src/registry/AIStateRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAqCtC,qEAAqE;AACrE,MAAM,OAAO,eAAgB,SAAQ,QAAoC;IACvE;QACE,KAAK,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,8FAA8F;IACrF,QAAQ,CAAC,EAAU,EAAE,MAA0B;QACtD,MAAM,MAAM,GAAG,MAAM,CAAC,oBAAoB;YACxC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,oBAAoB,EAAE,CAAC,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE;YAC/G,CAAC,CAAC,MAAM,CAAC;QACX,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,8HAA8H;IAC9H,mBAAmB,CAAC,YAAoB,EAAE,MAAe;QACvD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK,EAAE,oBAAoB;YAAE,OAAO,IAAI,CAAC;QAE9C,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,oBAAoB,EAAE,CAAC;YAC5C,IAAI,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC;gBAAE,OAAO,EAAE,CAAC,WAAW,CAAC;QAClD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
1
+ {"version":3,"file":"AIStateRegistry.js","sourceRoot":"","sources":["../../src/registry/AIStateRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAyCtC,qEAAqE;AACrE,MAAM,OAAO,eAAgB,SAAQ,QAAoC;IACvE;QACE,KAAK,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,8FAA8F;IACrF,QAAQ,CAAC,EAAU,EAAE,MAA0B;QACtD,MAAM,MAAM,GAAG,MAAM,CAAC,oBAAoB;YACxC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,oBAAoB,EAAE,CAAC,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE;YAC/G,CAAC,CAAC,MAAM,CAAC;QACX,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,8HAA8H;IAC9H,mBAAmB,CAAC,YAAoB,EAAE,MAAe;QACvD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK,EAAE,oBAAoB;YAAE,OAAO,IAAI,CAAC;QAE9C,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,oBAAoB,EAAE,CAAC;YAC5C,IAAI,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC;gBAAE,OAAO,EAAE,CAAC,WAAW,CAAC;QAClD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alife-sdk/core",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "description": "Framework-agnostic A-Life simulation and AI decision-making system",
5
5
  "type": "module",
6
6
  "sideEffects": false,