@vworlds/vecs 1.0.8 → 1.0.10
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/.husky/pre-commit +1 -0
- package/dist/command.d.ts +46 -0
- package/dist/command.js +2 -0
- package/dist/command.js.map +1 -0
- package/dist/entity.d.ts +65 -72
- package/dist/entity.js +198 -110
- package/dist/entity.js.map +1 -1
- package/dist/filter.js +19 -17
- package/dist/filter.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/query.d.ts +89 -18
- package/dist/query.js +125 -47
- package/dist/query.js.map +1 -1
- package/dist/system.d.ts +16 -52
- package/dist/system.js +74 -67
- package/dist/system.js.map +1 -1
- package/dist/world.d.ts +59 -26
- package/dist/world.js +132 -99
- package/dist/world.js.map +1 -1
- package/package.json +1 -1
package/dist/query.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { ArrayMap } from "./util/array_map.js";
|
|
2
|
+
import { Bitset } from "./util/bitset.js";
|
|
1
3
|
import { Component } from "./component.js";
|
|
2
4
|
import type { Entity } from "./entity.js";
|
|
3
5
|
import { type World } from "./world.js";
|
|
4
6
|
import { type EntityTestFunc, type QueryDSL, type MaybeRequired } from "./dsl.js";
|
|
5
7
|
export type { EntityTestFunc, QueryDSL, MaybeRequired };
|
|
6
|
-
type EntityCallback = (e: Entity) => void;
|
|
8
|
+
type EntityCallback = (e: Entity, snapshot?: Map<number, Component>) => void;
|
|
9
|
+
type ComponentCallback = (c: Component) => void;
|
|
7
10
|
type ComponentOrParent = typeof Component | {
|
|
8
11
|
parent: typeof Component;
|
|
9
12
|
};
|
|
@@ -15,18 +18,18 @@ type ComponentInstance<T> = T extends {
|
|
|
15
18
|
* expression.
|
|
16
19
|
*
|
|
17
20
|
* `Query` tracks every entity whose component set satisfies the predicate set
|
|
18
|
-
* via {@link requires} or {@link query}. Entry and
|
|
19
|
-
* automatically
|
|
20
|
-
* is exposed via {@link entities} and {@link forEach}.
|
|
21
|
+
* via {@link requires} or {@link query}. Entry, exit, and update callbacks
|
|
22
|
+
* fire automatically when the world's command queue is processed. The tracked
|
|
23
|
+
* set is exposed via {@link entities} and {@link forEach}.
|
|
21
24
|
*
|
|
22
|
-
* {@link System} extends `Query` and
|
|
23
|
-
*
|
|
24
|
-
* reactive
|
|
25
|
+
* {@link System} extends `Query` and queues callbacks for its next `_run`
|
|
26
|
+
* rather than firing them immediately. Use `Query` directly when you want
|
|
27
|
+
* synchronous reactive callbacks without pipeline integration.
|
|
25
28
|
*
|
|
26
29
|
* ### Type parameter `R`
|
|
27
30
|
* Tracks which component classes are "required" (declared via {@link requires}
|
|
28
31
|
* or the `_guaranteed` hint of {@link query}). Those components appear as
|
|
29
|
-
* non-nullable in {@link sort} callbacks.
|
|
32
|
+
* non-nullable in {@link sort}, {@link forEach}, and {@link update} callbacks.
|
|
30
33
|
*/
|
|
31
34
|
export declare class Query<R extends (typeof Component)[] = []> {
|
|
32
35
|
/** Unique name for this query, used in logs and debug output. */
|
|
@@ -34,10 +37,16 @@ export declare class Query<R extends (typeof Component)[] = []> {
|
|
|
34
37
|
/** The world that owns this query. */
|
|
35
38
|
readonly world: World;
|
|
36
39
|
protected _entities: Set<Entity> | undefined;
|
|
37
|
-
protected _enterCallback: EntityCallback
|
|
38
|
-
protected _exitCallback: EntityCallback
|
|
40
|
+
protected _enterCallback: EntityCallback | undefined;
|
|
41
|
+
protected _exitCallback: EntityCallback | undefined;
|
|
42
|
+
/** @internal Direct component type ids that the exit callback injects; undefined when no injection. */
|
|
43
|
+
protected _exitSnapshotTypes: number[] | undefined;
|
|
39
44
|
protected _belongs: EntityTestFunc;
|
|
40
45
|
protected hasQuery: boolean;
|
|
46
|
+
/** @internal Per-component-type update callbacks. */
|
|
47
|
+
protected componentUpdateCallbacks: ArrayMap<ComponentCallback>;
|
|
48
|
+
/** @internal Bitmask of component types this query is watching for updates. */
|
|
49
|
+
protected watchlistBitmask: Bitset;
|
|
41
50
|
constructor(
|
|
42
51
|
/** Unique name for this query, used in logs and debug output. */
|
|
43
52
|
name: string,
|
|
@@ -67,6 +76,11 @@ export declare class Query<R extends (typeof Component)[] = []> {
|
|
|
67
76
|
/**
|
|
68
77
|
* Iterate over every entity currently tracked by this query.
|
|
69
78
|
*
|
|
79
|
+
* Mutations made by `callback` are buffered into the world command queue
|
|
80
|
+
* (deferred mode) and only become visible after iteration finishes. Nested
|
|
81
|
+
* iteration inside an already-deferred context (a system, another forEach)
|
|
82
|
+
* inherits the outer deferred scope and does not drain on exit.
|
|
83
|
+
*
|
|
70
84
|
* @param callback - Called once per tracked entity, in insertion order
|
|
71
85
|
* (or sort order when {@link sort} is configured).
|
|
72
86
|
*/
|
|
@@ -88,11 +102,26 @@ export declare class Query<R extends (typeof Component)[] = []> {
|
|
|
88
102
|
}) => void): void;
|
|
89
103
|
/** Returns `true` if the entity satisfies this query's predicate. */
|
|
90
104
|
belongs(e: Entity): boolean;
|
|
91
|
-
/**
|
|
92
|
-
|
|
93
|
-
|
|
105
|
+
/**
|
|
106
|
+
* @internal Called by the world during command-queue routing when a Set
|
|
107
|
+
* command targets an entity that this query currently tracks. Default:
|
|
108
|
+
* fires the user-registered `update` callback for the component's type.
|
|
109
|
+
* `System` overrides this to push into its inbox instead.
|
|
110
|
+
*/
|
|
111
|
+
notifyModified(c: Component): void;
|
|
112
|
+
/**
|
|
113
|
+
* @internal Adds the entity to the tracked set, registers query membership
|
|
114
|
+
* on the entity, fires registered enter callbacks, then bridges any
|
|
115
|
+
* already-attached watched components through `notifyModified` so that
|
|
116
|
+
* `update` callbacks see the entity once on entry. `System` overrides this
|
|
117
|
+
* to push inbox events (events fire later in `_run`).
|
|
118
|
+
*/
|
|
94
119
|
_enter(e: Entity): void;
|
|
95
|
-
/**
|
|
120
|
+
/**
|
|
121
|
+
* @internal Removes the entity from the tracked set, deregisters query
|
|
122
|
+
* membership, and fires registered exit callbacks. `System` overrides this
|
|
123
|
+
* to also push an inbox event.
|
|
124
|
+
*/
|
|
96
125
|
_exit(e: Entity): void;
|
|
97
126
|
/**
|
|
98
127
|
* Register a callback that fires when an entity **enters** this query
|
|
@@ -126,10 +155,6 @@ export declare class Query<R extends (typeof Component)[] = []> {
|
|
|
126
155
|
* (its components no longer satisfy the predicate, or it was destroyed) with
|
|
127
156
|
* injected components.
|
|
128
157
|
*
|
|
129
|
-
* Components that were just removed are still accessible via `get_deleted`
|
|
130
|
-
* semantics — the injected tuple includes them even though they are no
|
|
131
|
-
* longer in the entity's active component set.
|
|
132
|
-
*
|
|
133
158
|
* @param inject - Component classes to resolve and inject.
|
|
134
159
|
* @param callback - Receives the entity and the resolved component tuple.
|
|
135
160
|
* @returns `this` for chaining.
|
|
@@ -144,6 +169,52 @@ export declare class Query<R extends (typeof Component)[] = []> {
|
|
|
144
169
|
* @returns `this` for chaining.
|
|
145
170
|
*/
|
|
146
171
|
exit(callback: (e: Entity) => void): this;
|
|
172
|
+
/**
|
|
173
|
+
* Register a callback that fires when a component of type `ComponentClass`
|
|
174
|
+
* is modified on any entity tracked by this query.
|
|
175
|
+
*
|
|
176
|
+
* On a {@link Query}, callbacks fire **immediately** when the world's
|
|
177
|
+
* command queue routes the corresponding `Set` command. On a {@link System},
|
|
178
|
+
* the event is buffered in the system's inbox and the callback fires during
|
|
179
|
+
* the system's next `_run`.
|
|
180
|
+
*
|
|
181
|
+
* If no other predicate has been set on this query, the watchlist
|
|
182
|
+
* automatically expands to require `ComponentClass` (equivalent to adding
|
|
183
|
+
* it to a `requires` / `HAS` query).
|
|
184
|
+
*
|
|
185
|
+
* @param ComponentClass - The component class to watch.
|
|
186
|
+
* @param callback - Receives the modified component instance.
|
|
187
|
+
* @returns `this` for chaining.
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```ts
|
|
191
|
+
* world.system("RenderPosition")
|
|
192
|
+
* .update(Position, (pos) => {
|
|
193
|
+
* sprite.setPosition(pos.x, pos.y);
|
|
194
|
+
* });
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
update<C extends typeof Component>(ComponentClass: C, callback: (c: InstanceType<C>) => void): this;
|
|
198
|
+
/**
|
|
199
|
+
* Register a callback that fires when `ComponentClass` is modified, with
|
|
200
|
+
* additional components injected from the same entity.
|
|
201
|
+
*
|
|
202
|
+
* @param ComponentClass - The component class to watch.
|
|
203
|
+
* @param inject - Additional component classes to resolve from the entity.
|
|
204
|
+
* @param callback - Receives the modified component and the injected tuple.
|
|
205
|
+
* @returns `this` for chaining.
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```ts
|
|
209
|
+
* world.system("SyncSprite")
|
|
210
|
+
* .update(Position, [Sprite], (pos, [sprite]) => {
|
|
211
|
+
* sprite.sprite.setPosition(pos.x, pos.y);
|
|
212
|
+
* });
|
|
213
|
+
* ```
|
|
214
|
+
*/
|
|
215
|
+
update<C extends typeof Component, J extends (typeof Component)[]>(ComponentClass: C, inject: readonly [...J], callback: (c: InstanceType<C>, injected: {
|
|
216
|
+
[K in keyof J]: MaybeRequired<J[K], R>;
|
|
217
|
+
}) => void): this;
|
|
147
218
|
/**
|
|
148
219
|
* Enable sorted entity tracking: matched entities are stored in insertion
|
|
149
220
|
* order determined by `compare`, which receives a tuple of resolved
|
package/dist/query.js
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
import { OrderedSet } from "./util/ordered_set.js";
|
|
2
|
-
import {
|
|
2
|
+
import { ArrayMap } from "./util/array_map.js";
|
|
3
|
+
import { Bitset } from "./util/bitset.js";
|
|
4
|
+
import { HAS, buildEntityTest, } from "./dsl.js";
|
|
3
5
|
const EMPTY_ENTITIES = new Set();
|
|
4
6
|
/**
|
|
5
7
|
* A reactive, always-updated list of entities that match a given query
|
|
6
8
|
* expression.
|
|
7
9
|
*
|
|
8
10
|
* `Query` tracks every entity whose component set satisfies the predicate set
|
|
9
|
-
* via {@link requires} or {@link query}. Entry and
|
|
10
|
-
* automatically
|
|
11
|
-
* is exposed via {@link entities} and {@link forEach}.
|
|
11
|
+
* via {@link requires} or {@link query}. Entry, exit, and update callbacks
|
|
12
|
+
* fire automatically when the world's command queue is processed. The tracked
|
|
13
|
+
* set is exposed via {@link entities} and {@link forEach}.
|
|
12
14
|
*
|
|
13
|
-
* {@link System} extends `Query` and
|
|
14
|
-
*
|
|
15
|
-
* reactive
|
|
15
|
+
* {@link System} extends `Query` and queues callbacks for its next `_run`
|
|
16
|
+
* rather than firing them immediately. Use `Query` directly when you want
|
|
17
|
+
* synchronous reactive callbacks without pipeline integration.
|
|
16
18
|
*
|
|
17
19
|
* ### Type parameter `R`
|
|
18
20
|
* Tracks which component classes are "required" (declared via {@link requires}
|
|
19
21
|
* or the `_guaranteed` hint of {@link query}). Those components appear as
|
|
20
|
-
* non-nullable in {@link sort} callbacks.
|
|
22
|
+
* non-nullable in {@link sort}, {@link forEach}, and {@link update} callbacks.
|
|
21
23
|
*/
|
|
22
24
|
export class Query {
|
|
23
25
|
constructor(
|
|
@@ -27,10 +29,16 @@ export class Query {
|
|
|
27
29
|
world, track = true) {
|
|
28
30
|
this.name = name;
|
|
29
31
|
this.world = world;
|
|
30
|
-
this._enterCallback =
|
|
31
|
-
this._exitCallback =
|
|
32
|
+
this._enterCallback = undefined;
|
|
33
|
+
this._exitCallback = undefined;
|
|
34
|
+
/** @internal Direct component type ids that the exit callback injects; undefined when no injection. */
|
|
35
|
+
this._exitSnapshotTypes = undefined;
|
|
32
36
|
this._belongs = (_e) => false;
|
|
33
37
|
this.hasQuery = false;
|
|
38
|
+
/** @internal Per-component-type update callbacks. */
|
|
39
|
+
this.componentUpdateCallbacks = new ArrayMap();
|
|
40
|
+
/** @internal Bitmask of component types this query is watching for updates. */
|
|
41
|
+
this.watchlistBitmask = new Bitset();
|
|
34
42
|
world._addQuery(this);
|
|
35
43
|
if (track) {
|
|
36
44
|
this.track();
|
|
@@ -58,11 +66,12 @@ export class Query {
|
|
|
58
66
|
if (this._entities === undefined) {
|
|
59
67
|
return;
|
|
60
68
|
}
|
|
61
|
-
this.world.
|
|
62
|
-
|
|
63
|
-
e.
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
this.world.defer(() => {
|
|
70
|
+
this.world.entities.forEach((e) => {
|
|
71
|
+
if (this.belongs(e) && !e.isInQuery(this)) {
|
|
72
|
+
this._enter(e);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
66
75
|
});
|
|
67
76
|
}
|
|
68
77
|
/**
|
|
@@ -76,57 +85,128 @@ export class Query {
|
|
|
76
85
|
return this._entities ?? EMPTY_ENTITIES;
|
|
77
86
|
}
|
|
78
87
|
forEach(componentsOrCallback, callback) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (!this._entities || !this.world) {
|
|
84
|
-
return;
|
|
88
|
+
this.world.beginDefer();
|
|
89
|
+
try {
|
|
90
|
+
if (typeof componentsOrCallback === "function") {
|
|
91
|
+
this._entities?.forEach(componentsOrCallback);
|
|
85
92
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
93
|
+
else {
|
|
94
|
+
if (!this._entities || !this.world) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const types = componentsOrCallback.map((C) => this.world.getComponentType(C));
|
|
98
|
+
this._entities.forEach((e) => {
|
|
99
|
+
const resolved = types.map((t) => e.get(t));
|
|
100
|
+
callback(e, resolved);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
this.world.endDefer();
|
|
91
106
|
}
|
|
92
107
|
}
|
|
93
108
|
/** Returns `true` if the entity satisfies this query's predicate. */
|
|
94
109
|
belongs(e) {
|
|
95
110
|
return this._belongs(e);
|
|
96
111
|
}
|
|
97
|
-
/**
|
|
98
|
-
|
|
99
|
-
|
|
112
|
+
/**
|
|
113
|
+
* @internal Called by the world during command-queue routing when a Set
|
|
114
|
+
* command targets an entity that this query currently tracks. Default:
|
|
115
|
+
* fires the user-registered `update` callback for the component's type.
|
|
116
|
+
* `System` overrides this to push into its inbox instead.
|
|
117
|
+
*/
|
|
118
|
+
notifyModified(c) {
|
|
119
|
+
if (!this.watchlistBitmask.hasBit(c.bitPtr)) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const callback = this.componentUpdateCallbacks.get(c.type);
|
|
123
|
+
if (callback) {
|
|
124
|
+
callback(c);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* @internal Adds the entity to the tracked set, registers query membership
|
|
129
|
+
* on the entity, fires registered enter callbacks, then bridges any
|
|
130
|
+
* already-attached watched components through `notifyModified` so that
|
|
131
|
+
* `update` callbacks see the entity once on entry. `System` overrides this
|
|
132
|
+
* to push inbox events (events fire later in `_run`).
|
|
133
|
+
*/
|
|
100
134
|
_enter(e) {
|
|
101
|
-
this._enterCallback.forEach((cb) => cb(e));
|
|
102
135
|
this._entities?.add(e);
|
|
136
|
+
e._addQueryMembership(this);
|
|
137
|
+
this._enterCallback?.(e);
|
|
138
|
+
// Bridge: surface the entity's already-attached watched components as
|
|
139
|
+
// update events so `update` handlers fire once on entry without the user
|
|
140
|
+
// having to call `modified()` explicitly.
|
|
141
|
+
e.forEachComponent((c) => {
|
|
142
|
+
if (this.watchlistBitmask.hasBit(c.bitPtr)) {
|
|
143
|
+
this.notifyModified(c);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
103
146
|
}
|
|
104
|
-
/**
|
|
147
|
+
/**
|
|
148
|
+
* @internal Removes the entity from the tracked set, deregisters query
|
|
149
|
+
* membership, and fires registered exit callbacks. `System` overrides this
|
|
150
|
+
* to also push an inbox event.
|
|
151
|
+
*/
|
|
105
152
|
_exit(e) {
|
|
106
|
-
this._exitCallback
|
|
153
|
+
this._exitCallback?.(e);
|
|
107
154
|
this._entities?.delete(e);
|
|
155
|
+
e._removeQueryMembership(this);
|
|
108
156
|
}
|
|
109
157
|
enter(injectOrCallback, callback) {
|
|
110
158
|
if (typeof injectOrCallback === "function") {
|
|
111
|
-
this._enterCallback
|
|
159
|
+
this._enterCallback = injectOrCallback;
|
|
112
160
|
}
|
|
113
161
|
else {
|
|
114
162
|
const inject = this.mapInjectedClassToTypes(injectOrCallback);
|
|
115
|
-
this._enterCallback
|
|
163
|
+
this._enterCallback = (e) => {
|
|
116
164
|
callback(e, this.getInjected(e, inject));
|
|
117
|
-
}
|
|
165
|
+
};
|
|
118
166
|
}
|
|
119
167
|
return this;
|
|
120
168
|
}
|
|
121
169
|
exit(injectOrCallback, callback) {
|
|
122
170
|
if (typeof injectOrCallback === "function") {
|
|
123
|
-
this._exitCallback
|
|
171
|
+
this._exitCallback = injectOrCallback;
|
|
172
|
+
this._exitSnapshotTypes = undefined;
|
|
124
173
|
}
|
|
125
174
|
else {
|
|
126
175
|
const inject = this.mapInjectedClassToTypes(injectOrCallback);
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
176
|
+
// Only direct (non-parent) types need snapshotting; parent refs are read
|
|
177
|
+
// from e.parent at callback time, which is still alive.
|
|
178
|
+
this._exitSnapshotTypes = inject.filter((t) => typeof t === "number");
|
|
179
|
+
this._exitCallback = (e, exitSnapshot) => {
|
|
180
|
+
callback(e, this.getInjected(e, inject, exitSnapshot));
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
return this;
|
|
184
|
+
}
|
|
185
|
+
update(ComponentClass, injectOrCallback, callback) {
|
|
186
|
+
const type = this.world.getComponentType(ComponentClass);
|
|
187
|
+
if (typeof injectOrCallback === "function") {
|
|
188
|
+
callback = injectOrCallback;
|
|
189
|
+
this.componentUpdateCallbacks.set(type, callback);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
const inject = injectOrCallback;
|
|
193
|
+
const injectedComponentTypes = inject.map((C) => this.world.getComponentType(C));
|
|
194
|
+
const cb = (c) => {
|
|
195
|
+
const injected = [];
|
|
196
|
+
injectedComponentTypes.forEach((InjectedComponentType) => {
|
|
197
|
+
injected.push(c.entity.get(InjectedComponentType));
|
|
198
|
+
});
|
|
199
|
+
if (callback) {
|
|
200
|
+
callback(c, injected);
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
this.componentUpdateCallbacks.set(type, cb);
|
|
204
|
+
}
|
|
205
|
+
this.watchlistBitmask.add(type);
|
|
206
|
+
if (!this.hasQuery) {
|
|
207
|
+
const watchlist = this.watchlistBitmask.indices();
|
|
208
|
+
this._belongs = HAS(this.world, ...watchlist);
|
|
209
|
+
this.backfill();
|
|
130
210
|
}
|
|
131
211
|
return this;
|
|
132
212
|
}
|
|
@@ -149,7 +229,7 @@ export class Query {
|
|
|
149
229
|
*/
|
|
150
230
|
sort(components, compare) {
|
|
151
231
|
const types = components.map((C) => this.world.getComponentType(C));
|
|
152
|
-
this._entities = new OrderedSet((a, b) => compare(types.map((t) => a.get(t
|
|
232
|
+
this._entities = new OrderedSet((a, b) => compare(types.map((t) => a.get(t)), types.map((t) => b.get(t))));
|
|
153
233
|
this.backfill();
|
|
154
234
|
return this;
|
|
155
235
|
}
|
|
@@ -210,20 +290,18 @@ export class Query {
|
|
|
210
290
|
this.query(components);
|
|
211
291
|
return this;
|
|
212
292
|
}
|
|
213
|
-
getComponent(e, C,
|
|
214
|
-
let c;
|
|
293
|
+
getComponent(e, C, exitSnapshot) {
|
|
215
294
|
if (typeof C === "number") {
|
|
216
|
-
|
|
295
|
+
return exitSnapshot?.get(C) ?? e.get(C);
|
|
217
296
|
}
|
|
218
297
|
else {
|
|
219
|
-
|
|
298
|
+
return e.parent?.get(C.parent);
|
|
220
299
|
}
|
|
221
|
-
return c;
|
|
222
300
|
}
|
|
223
|
-
getInjected(e, inject,
|
|
301
|
+
getInjected(e, inject, exitSnapshot) {
|
|
224
302
|
const injected = [];
|
|
225
303
|
inject.forEach((C) => {
|
|
226
|
-
const c = this.getComponent(e, C,
|
|
304
|
+
const c = this.getComponent(e, C, exitSnapshot);
|
|
227
305
|
if (!c) {
|
|
228
306
|
throw "query does not contain component";
|
|
229
307
|
}
|
package/dist/query.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
|
package/dist/system.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { ArrayMap } from "./util/array_map.js";
|
|
2
|
-
import { Bitset } from "./util/bitset.js";
|
|
3
1
|
import { Component } from "./component.js";
|
|
4
2
|
import { Query } from "./query.js";
|
|
5
3
|
import { type QueryDSL, type MaybeRequired } from "./dsl.js";
|
|
@@ -7,7 +5,6 @@ import type { Entity } from "./entity.js";
|
|
|
7
5
|
import { Phase, type IPhase } from "./phase.js";
|
|
8
6
|
import { type World } from "./world.js";
|
|
9
7
|
export type { QueryDSL as SystemQuery, EntityTestFunc } from "./dsl.js";
|
|
10
|
-
type ComponentCallback = (c: Component) => void;
|
|
11
8
|
type RunCallback = (now: number, delta: number) => void;
|
|
12
9
|
/**
|
|
13
10
|
* A reactive processor that operates on a filtered subset of world entities.
|
|
@@ -27,6 +24,11 @@ type RunCallback = (now: number, delta: number) => void;
|
|
|
27
24
|
* once all systems are registered; after that, drive the loop with
|
|
28
25
|
* {@link World.runPhase}.
|
|
29
26
|
*
|
|
27
|
+
* Internally each system holds a single ordered **inbox** of routed events
|
|
28
|
+
* (`enter`, `exit`, `update`). The world appends to it during command-queue
|
|
29
|
+
* routing; the system replays the inbox at the top of every `_run` so
|
|
30
|
+
* callbacks observe events in arrival order.
|
|
31
|
+
*
|
|
30
32
|
* ### Component injection and type inference
|
|
31
33
|
*
|
|
32
34
|
* `enter`, `exit`, `update`, `each`, and `sort` all accept an array of
|
|
@@ -40,13 +42,11 @@ type RunCallback = (now: number, delta: number) => void;
|
|
|
40
42
|
* non-nullable; any component not in `R` remains `Type | undefined`.
|
|
41
43
|
*/
|
|
42
44
|
export declare class System<R extends (typeof Component)[] = []> extends Query<R> {
|
|
43
|
-
protected componentUpdateCallbacks: ArrayMap<ComponentCallback>;
|
|
44
45
|
protected eachCallback: ((e: Entity) => void) | undefined;
|
|
45
46
|
private _runCallback;
|
|
46
|
-
private readonly
|
|
47
|
+
private readonly inbox;
|
|
47
48
|
/** @internal */
|
|
48
49
|
_phase: string | Phase | undefined;
|
|
49
|
-
protected watchlistBitmask: Bitset;
|
|
50
50
|
constructor(name: string, world: World);
|
|
51
51
|
/**
|
|
52
52
|
* Assign this system to a pipeline phase.
|
|
@@ -60,13 +60,18 @@ export declare class System<R extends (typeof Component)[] = []> extends Query<R
|
|
|
60
60
|
* @returns `this` for chaining.
|
|
61
61
|
*/
|
|
62
62
|
phase(p: string | IPhase): this;
|
|
63
|
-
/** @internal
|
|
64
|
-
notifyModified(c: Component): void;
|
|
65
|
-
/** @internal Fires enter callbacks, adds entity to tracked set, queues component updates. */
|
|
63
|
+
/** @internal Routing entry: register membership and enqueue an enter event. */
|
|
66
64
|
_enter(e: Entity): void;
|
|
67
|
-
/** @internal
|
|
65
|
+
/** @internal Routing entry: deregister membership and enqueue an exit event. */
|
|
68
66
|
_exit(e: Entity): void;
|
|
69
|
-
/** @internal
|
|
67
|
+
/** @internal Routing entry: enqueue an update event if the watchlist matches. */
|
|
68
|
+
notifyModified(c: Component): void;
|
|
69
|
+
/**
|
|
70
|
+
* @internal Execute one tick: drain the inbox in arrival order, then run
|
|
71
|
+
* `runCallback` and `eachCallback`. The whole body runs in a deferred
|
|
72
|
+
* scope; any mutations made by callbacks land in the world queue and are
|
|
73
|
+
* processed by the world after `_run` returns.
|
|
74
|
+
*/
|
|
70
75
|
_run(now: number, delta: number): void;
|
|
71
76
|
/**
|
|
72
77
|
* Register a per-tick callback that runs every time this system's phase
|
|
@@ -80,47 +85,6 @@ export declare class System<R extends (typeof Component)[] = []> extends Query<R
|
|
|
80
85
|
* @returns `this` for chaining.
|
|
81
86
|
*/
|
|
82
87
|
run(callback: RunCallback): this;
|
|
83
|
-
/**
|
|
84
|
-
* Register a callback that fires when a component of type `ComponentClass`
|
|
85
|
-
* is modified on any entity in this system.
|
|
86
|
-
*
|
|
87
|
-
* The system will automatically begin tracking entities that have this
|
|
88
|
-
* component type (equivalent to adding it to a `requires` / `HAS` query)
|
|
89
|
-
* unless a custom {@link query} was already set.
|
|
90
|
-
*
|
|
91
|
-
* @param ComponentClass - The component class to watch.
|
|
92
|
-
* @param callback - Receives the modified component instance.
|
|
93
|
-
* @returns `this` for chaining.
|
|
94
|
-
*
|
|
95
|
-
* @example
|
|
96
|
-
* ```ts
|
|
97
|
-
* world.system("RenderPosition")
|
|
98
|
-
* .update(Position, (pos) => {
|
|
99
|
-
* sprite.setPosition(pos.x, pos.y);
|
|
100
|
-
* });
|
|
101
|
-
* ```
|
|
102
|
-
*/
|
|
103
|
-
update<C extends typeof Component>(ComponentClass: C, callback: (c: InstanceType<C>) => void): this;
|
|
104
|
-
/**
|
|
105
|
-
* Register a callback that fires when `ComponentClass` is modified, with
|
|
106
|
-
* additional components injected from the same entity.
|
|
107
|
-
*
|
|
108
|
-
* @param ComponentClass - The component class to watch.
|
|
109
|
-
* @param inject - Additional component classes to resolve from the entity.
|
|
110
|
-
* @param callback - Receives the modified component and the injected tuple.
|
|
111
|
-
* @returns `this` for chaining.
|
|
112
|
-
*
|
|
113
|
-
* @example
|
|
114
|
-
* ```ts
|
|
115
|
-
* world.system("SyncSprite")
|
|
116
|
-
* .update(Position, [Sprite], (pos, [sprite]) => {
|
|
117
|
-
* sprite.sprite.setPosition(pos.x, pos.y);
|
|
118
|
-
* });
|
|
119
|
-
* ```
|
|
120
|
-
*/
|
|
121
|
-
update<C extends typeof Component, J extends (typeof Component)[]>(ComponentClass: C, inject: readonly [...J], callback: (c: InstanceType<C>, injected: {
|
|
122
|
-
[K in keyof J]: MaybeRequired<J[K], R>;
|
|
123
|
-
}) => void): this;
|
|
124
88
|
/**
|
|
125
89
|
* Register a callback that fires **every tick** for every entity currently
|
|
126
90
|
* tracked by this system, with the listed components resolved from each
|