@vworlds/vecs 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/.claude/settings.json +12 -0
  2. package/.devcontainer/devcontainer.json +22 -0
  3. package/.github/workflows/publish.yml +32 -0
  4. package/README.md +464 -0
  5. package/dist/component.d.ts +135 -0
  6. package/dist/component.js +101 -0
  7. package/dist/component.js.map +1 -0
  8. package/dist/entity.d.ts +157 -0
  9. package/dist/entity.js +199 -0
  10. package/dist/entity.js.map +1 -0
  11. package/dist/index.d.ts +6 -0
  12. package/dist/index.js +4 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/package.json +25 -0
  15. package/dist/phase.d.ts +47 -0
  16. package/dist/phase.js +23 -0
  17. package/dist/phase.js.map +1 -0
  18. package/dist/system.d.ts +361 -0
  19. package/dist/system.js +396 -0
  20. package/dist/system.js.map +1 -0
  21. package/dist/util/array_map.d.ts +58 -0
  22. package/dist/util/array_map.js +84 -0
  23. package/dist/util/array_map.js.map +1 -0
  24. package/dist/util/bitset.d.ts +117 -0
  25. package/dist/util/bitset.js +177 -0
  26. package/dist/util/bitset.js.map +1 -0
  27. package/dist/util/events.d.ts +27 -0
  28. package/dist/util/events.js +43 -0
  29. package/dist/util/events.js.map +1 -0
  30. package/dist/util/ordered_set.d.ts +17 -0
  31. package/dist/util/ordered_set.js +69 -0
  32. package/dist/util/ordered_set.js.map +1 -0
  33. package/dist/world.d.ts +279 -0
  34. package/dist/world.js +453 -0
  35. package/dist/world.js.map +1 -0
  36. package/package.json +25 -0
  37. package/src/component.ts +180 -0
  38. package/src/entity.ts +276 -0
  39. package/src/index.ts +6 -0
  40. package/src/phase.ts +49 -0
  41. package/src/system.ts +693 -0
  42. package/src/util/array_map.ts +93 -0
  43. package/src/util/bitset.ts +199 -0
  44. package/src/util/events.ts +95 -0
  45. package/src/util/ordered_set.ts +82 -0
  46. package/src/world.ts +534 -0
  47. package/tests/_helpers.ts +30 -0
  48. package/tests/array_map.test.ts +68 -0
  49. package/tests/bitset.test.ts +127 -0
  50. package/tests/component.test.ts +104 -0
  51. package/tests/entity.test.ts +179 -0
  52. package/tests/events.test.ts +48 -0
  53. package/tests/ordered_set.test.ts +153 -0
  54. package/tests/setup.ts +6 -0
  55. package/tests/system.test.ts +800 -0
  56. package/tests/world.test.ts +174 -0
  57. package/tsconfig.json +21 -0
  58. package/vitest.config.ts +9 -0
package/dist/system.js ADDED
@@ -0,0 +1,396 @@
1
+ import { ArrayMap } from "./util/array_map.js";
2
+ import { Bitset } from "./util/bitset.js";
3
+ import { OrderedSet } from "./util/ordered_set.js";
4
+ import { Component, calculateComponentBitmask, } from "./component.js";
5
+ import { Phase } from "./phase.js";
6
+ function HAS(world, ...components) {
7
+ const testBitmask = calculateComponentBitmask(components, world);
8
+ return (e) => e.componentBitmask.hasBitset(testBitmask);
9
+ }
10
+ function HAS_ONLY(world, ...components) {
11
+ const testBitmask = calculateComponentBitmask(components, world);
12
+ return (e) => e.componentBitmask.equal(testBitmask);
13
+ }
14
+ function NOT(func) {
15
+ return (e) => !func(e);
16
+ }
17
+ function AND(...funcs) {
18
+ return (e) => funcs.every((f) => f(e));
19
+ }
20
+ function OR(...funcs) {
21
+ return (e) => funcs.some((f) => f(e));
22
+ }
23
+ function PARENT(func) {
24
+ return (e) => (e.parent && func(e.parent)) || false;
25
+ }
26
+ const EMPTY_ENTITIES = new Set();
27
+ export class System {
28
+ constructor(
29
+ /** Unique name for this system, used in logs and pipeline output. */
30
+ name,
31
+ /** The world that owns this system. */
32
+ world) {
33
+ this.name = name;
34
+ this.world = world;
35
+ this.componentUpdateCallbacks = new ArrayMap();
36
+ this._enterCallback = [];
37
+ this._exitCallback = [];
38
+ this._belongs = (e) => false;
39
+ this.updateQueue = [];
40
+ this.hasQuery = false;
41
+ this.watchlistBitmask = new Bitset();
42
+ }
43
+ /** Returns the system name. */
44
+ toString() {
45
+ return this.name;
46
+ }
47
+ /**
48
+ * Read-only view of the entities currently tracked by this system.
49
+ *
50
+ * Empty unless {@link track} (or {@link each}, which implies it) was
51
+ * called during system configuration.
52
+ */
53
+ get entities() {
54
+ return this._entities ?? EMPTY_ENTITIES;
55
+ }
56
+ /**
57
+ * Assign this system to a pipeline phase.
58
+ *
59
+ * The phase can be specified by name (the world will resolve it at
60
+ * {@link World.start | start} time) or by an {@link IPhase} reference
61
+ * returned from {@link World.addPhase}. Systems without an explicit phase
62
+ * are placed in the built-in `"update"` phase.
63
+ *
64
+ * @param p - Phase name or `IPhase` reference.
65
+ * @returns `this` for chaining.
66
+ */
67
+ phase(p) {
68
+ if (typeof p !== "string") {
69
+ if (!(p instanceof Phase))
70
+ throw "Invalid Phase object";
71
+ if (p.world !== this.world)
72
+ throw "Phase does not belong to this system's world";
73
+ }
74
+ this._phase = p;
75
+ return this;
76
+ }
77
+ /** @internal Delivers a component-modified notification to this system. */
78
+ notifyModified(c) {
79
+ if (!this.watchlistBitmask.hasBit(c.bitPtr))
80
+ return;
81
+ this.updateQueue.push(c);
82
+ }
83
+ /** Returns `true` if the entity satisfies this system's query. */
84
+ belongs(e) {
85
+ return this._belongs(e);
86
+ }
87
+ /** @internal Fires `enter` callbacks for a newly matched entity. */
88
+ _enter(e) {
89
+ this._enterCallback.forEach((callback) => callback(e));
90
+ e.forEachComponent((c) => this.notifyModified(c));
91
+ this._entities?.add(e);
92
+ }
93
+ /** @internal Fires `exit` callbacks when an entity leaves the system. */
94
+ _exit(e) {
95
+ this._exitCallback.forEach((callback) => callback(e));
96
+ this._entities?.delete(e);
97
+ // remove queued updates for components of the exiting entity:
98
+ this.updateQueue.forEach((c, i) => {
99
+ if (!c)
100
+ return;
101
+ if (c.entity === e)
102
+ this.updateQueue[i] = undefined;
103
+ });
104
+ }
105
+ /** @internal Execute one tick: run `run`, fire `each`, then drain the update queue. */
106
+ _run(now, delta) {
107
+ if (this._runCallback)
108
+ this._runCallback(now, delta);
109
+ if (this.eachCallback) {
110
+ const cb = this.eachCallback;
111
+ this._entities?.forEach((e) => cb(e));
112
+ }
113
+ this.updateQueue.forEach((c) => {
114
+ if (!c)
115
+ return;
116
+ const callback = this.componentUpdateCallbacks.get(c.type);
117
+ if (callback) {
118
+ callback(c);
119
+ }
120
+ });
121
+ this.updateQueue.length = 0;
122
+ }
123
+ getComponent(e, C, considerDeleted) {
124
+ let c;
125
+ if (typeof C === "number") {
126
+ c = e.get(C, considerDeleted); // obtain an instance of C
127
+ }
128
+ else {
129
+ c = e.parent && e.parent.get(C.parent, considerDeleted);
130
+ }
131
+ return c;
132
+ }
133
+ getInjected(e, inject, considerDeleted = false) {
134
+ const injected = [];
135
+ inject.forEach((C) => {
136
+ const c = this.getComponent(e, C, considerDeleted);
137
+ if (!c)
138
+ throw "system does not contain component";
139
+ injected.push(c);
140
+ });
141
+ return injected;
142
+ }
143
+ mapInjectedClassToTypes(inject) {
144
+ //map injected class constructors to type numbers which are faster to search for later
145
+ return inject.map((C) => {
146
+ if (typeof C === "function")
147
+ return this.world.getComponentType(C);
148
+ return { parent: this.world.getComponentType(C.parent) };
149
+ });
150
+ }
151
+ // Implement the overloaded function
152
+ enter(injectOrCallback, callback) {
153
+ if (typeof injectOrCallback === "function") {
154
+ // It is the second signature
155
+ this._enterCallback.push(injectOrCallback);
156
+ }
157
+ else {
158
+ // It is the first signature
159
+ const inject = this.mapInjectedClassToTypes(injectOrCallback);
160
+ this._enterCallback.push((e) => {
161
+ callback(e, this.getInjected(e, inject));
162
+ });
163
+ }
164
+ return this;
165
+ }
166
+ // Implement the overloaded function
167
+ exit(injectOrCallback, callback) {
168
+ if (typeof injectOrCallback === "function") {
169
+ // It is the second signature
170
+ this._exitCallback.push(injectOrCallback);
171
+ }
172
+ else {
173
+ // It is the first signature
174
+ const inject = this.mapInjectedClassToTypes(injectOrCallback);
175
+ this._exitCallback.push((e) => {
176
+ callback(e, this.getInjected(e, inject, true));
177
+ });
178
+ }
179
+ return this;
180
+ }
181
+ /**
182
+ * Register a per-tick callback that runs every time this system's phase
183
+ * executes, regardless of entity membership.
184
+ *
185
+ * Use this for logic that is not driven by component updates — polling,
186
+ * network flushing, global timers, etc.
187
+ *
188
+ * @param callback - Receives `now` (absolute timestamp in ms) and `delta`
189
+ * (ms since the last tick).
190
+ * @returns `this` for chaining.
191
+ */
192
+ run(callback) {
193
+ this._runCallback = callback;
194
+ return this;
195
+ }
196
+ update(ComponentClass, injectOrCallback, callback) {
197
+ const type = this.world.getComponentType(ComponentClass);
198
+ if (typeof injectOrCallback === "function") {
199
+ // Only ComponentClass and callback are passed
200
+ callback = injectOrCallback;
201
+ this.componentUpdateCallbacks.set(type, callback);
202
+ }
203
+ else {
204
+ // ComponentClass, inject, and callback are passed
205
+ const inject = injectOrCallback;
206
+ //map injected class constructors to component type numbers which are faster to search for later
207
+ const injectedComponentTypes = inject.map((C) => this.world.getComponentType(C));
208
+ const cb = (c) => {
209
+ const injected = [];
210
+ injectedComponentTypes.forEach((InjectedComponentType) => {
211
+ injected.push(c.entity.get(InjectedComponentType));
212
+ });
213
+ if (callback) {
214
+ callback(c, injected);
215
+ }
216
+ };
217
+ this.componentUpdateCallbacks.set(type, cb);
218
+ }
219
+ this.watchlistBitmask.add(type);
220
+ if (!this.hasQuery) {
221
+ const watchlist = this.watchlistBitmask.indices();
222
+ this._belongs = HAS(this.world, ...watchlist);
223
+ }
224
+ return this;
225
+ }
226
+ /**
227
+ * Register a callback that fires **every tick** for every entity currently
228
+ * tracked by this system, with the listed components resolved from each
229
+ * entity.
230
+ *
231
+ * Unlike {@link update} (which only fires when `component.modified()` is
232
+ * called), `each` fires unconditionally on every tick the system runs,
233
+ * once per tracked entity. Components declared via {@link requires} are
234
+ * guaranteed non-null in the resolved tuple; any other component class
235
+ * may be `undefined` if the entity lacks it.
236
+ *
237
+ * `each` does **not** modify the system's query — define membership with
238
+ * {@link requires} or {@link query} as usual. It does, however, implicitly
239
+ * enable {@link track}, so matched entities are exposed via {@link entities}.
240
+ *
241
+ * Only a single `each` callback may be registered per system; calling
242
+ * `each` a second time throws.
243
+ *
244
+ * @param components - Component classes to resolve from each entity.
245
+ * @param callback - Receives the entity and a tuple of resolved component
246
+ * instances (`undefined` for components not covered by {@link requires}).
247
+ * @returns `this` for chaining.
248
+ * @throws If `each` has already been registered on this system.
249
+ *
250
+ * @example
251
+ * ```ts
252
+ * world.system("Move")
253
+ * .requires(Position, Velocity)
254
+ * .each([Position, Velocity], (e, [pos, vel]) => {
255
+ * pos.x += vel.vx;
256
+ * pos.y += vel.vy;
257
+ * });
258
+ * ```
259
+ */
260
+ each(components, callback) {
261
+ if (this.eachCallback) {
262
+ throw `each already registered for system '${this.name}'`;
263
+ }
264
+ this.track();
265
+ const types = components.map((C) => this.world.getComponentType(C));
266
+ this.eachCallback = (e) => {
267
+ const resolved = types.map((t) => e.get(t));
268
+ callback(e, resolved);
269
+ };
270
+ return this;
271
+ }
272
+ /**
273
+ * Enable entity tracking: matched entities are inserted into
274
+ * {@link entities} as they enter the system and removed as they exit.
275
+ *
276
+ * Idempotent. Intended to be called during system configuration before
277
+ * `world.start()`; entities already matched when `track` is called late
278
+ * will not be backfilled.
279
+ *
280
+ * {@link each} implies `track` — call this directly only when you want
281
+ * the tracked set without an `each` callback.
282
+ *
283
+ * @returns `this` for chaining.
284
+ */
285
+ track() {
286
+ this._entities ?? (this._entities = new Set());
287
+ return this;
288
+ }
289
+ /**
290
+ * Enable sorted entity tracking: matched entities are stored in insertion
291
+ * order determined by `compare`, which receives a tuple of resolved
292
+ * component instances for each pair of entities being ordered.
293
+ *
294
+ * Implies {@link track}.
295
+ *
296
+ * @param components - Component classes to resolve and pass to `compare`.
297
+ * @param compare - Returns a negative number, zero, or positive number when
298
+ * `a` should sort before, equal to, or after `b`.
299
+ * @returns `this` for chaining.
300
+ *
301
+ * @example
302
+ * ```ts
303
+ * world.system("Render")
304
+ * .requires(Position, Sprite)
305
+ * .sort([Position], ([posA], [posB]) => posA.z - posB.z);
306
+ * ```
307
+ */
308
+ sort(components, compare) {
309
+ const types = components.map((C) => this.world.getComponentType(C));
310
+ this._entities = new OrderedSet((a, b) => compare(types.map((t) => a.get(t, true)), types.map((t) => b.get(t, true))));
311
+ return this;
312
+ }
313
+ queryBuilder(q) {
314
+ if (typeof q === "number" ||
315
+ (typeof q === "function" && q.prototype instanceof Component)) {
316
+ return HAS(this.world, q);
317
+ }
318
+ else if (typeof q === "function") {
319
+ return q;
320
+ }
321
+ if (q instanceof Array) {
322
+ return HAS(this.world, ...q);
323
+ }
324
+ if ("HAS" in q) {
325
+ return this.queryBuilder(q.HAS);
326
+ }
327
+ if ("HAS_ONLY" in q) {
328
+ const v = q.HAS_ONLY;
329
+ if (v instanceof Array) {
330
+ return HAS_ONLY(this.world, ...v);
331
+ }
332
+ return HAS_ONLY(this.world, v);
333
+ }
334
+ if ("AND" in q) {
335
+ return AND(...q.AND.map((sq) => this.queryBuilder(sq)));
336
+ }
337
+ if ("OR" in q) {
338
+ return OR(...q.OR.map((sq) => this.queryBuilder(sq)));
339
+ }
340
+ if ("NOT" in q) {
341
+ return NOT(this.queryBuilder(q.NOT));
342
+ }
343
+ if ("PARENT" in q) {
344
+ return PARENT(this.queryBuilder(q.PARENT));
345
+ }
346
+ throw "Unrecognized query term";
347
+ }
348
+ /**
349
+ * Set the entity membership predicate using the {@link SystemQuery} DSL.
350
+ *
351
+ * Replaces any implicit query derived from `update` watchlists and any
352
+ * previous `requires` call. After calling `query`, auto-expanding of
353
+ * `update` watchlists is disabled.
354
+ *
355
+ * The optional `guaranteed` tuple is a pure type-level hint: it tells
356
+ * `sort`, `each`, and `update` callbacks which components are guaranteed
357
+ * to be present on every matched entity, eliminating `| undefined` from
358
+ * those positions. It has no effect at runtime.
359
+ *
360
+ * @param q - A {@link SystemQuery} expression.
361
+ * @param _guaranteed - Component classes guaranteed present on every matched
362
+ * entity (type hint only — not validated at runtime).
363
+ * @returns `this` for chaining.
364
+ *
365
+ * @example
366
+ * ```ts
367
+ * world.system("Move")
368
+ * .query({ AND: [{ HAS: Position }, { HAS: Velocity }] }, [Position, Velocity])
369
+ * .each([Position, Velocity], (e, [pos, vel]) => {
370
+ * pos.x += vel.vx; // no ! needed
371
+ * });
372
+ * ```
373
+ */
374
+ query(q, _guaranteed) {
375
+ this._belongs = this.queryBuilder(q);
376
+ this.hasQuery = true;
377
+ return this;
378
+ }
379
+ /**
380
+ * Shorthand for `query([...components])` — the system tracks entities that
381
+ * have **all** of the listed component types.
382
+ *
383
+ * Equivalent to `query({ HAS: components })`. Unlike `query`, passing
384
+ * component classes here also informs the types of {@link sort} and
385
+ * {@link each} callbacks: listed components will be non-nullable in those
386
+ * tuples.
387
+ *
388
+ * @param components - One or more component classes.
389
+ * @returns `this` for chaining.
390
+ */
391
+ requires(...components) {
392
+ this.query(components);
393
+ return this;
394
+ }
395
+ }
396
+ //# sourceMappingURL=system.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system.js","sourceRoot":"","sources":["../src/system.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * A `Map<number, T>` backed by a sparse JavaScript array.
3
+ *
4
+ * For small, dense integer key spaces this is significantly faster than
5
+ * `Map` because array index access avoids the hash-table overhead. Used
6
+ * internally to store per-entity component instances and per-type component
7
+ * metadata.
8
+ *
9
+ * Keys must be non-negative integers. Gaps in the key space are represented
10
+ * as `undefined` slots and do not count toward `size`.
11
+ *
12
+ * @typeParam T - The value type stored in the map.
13
+ */
14
+ export declare class ArrayMap<T> {
15
+ private backend;
16
+ private _size;
17
+ constructor();
18
+ /**
19
+ * Store `value` at `key`, replacing any existing value.
20
+ *
21
+ * @param key - Non-negative integer key.
22
+ * @param value - Value to store.
23
+ */
24
+ set(key: number, value: T): void;
25
+ /**
26
+ * Return the value stored at `key`, or `undefined` if not present.
27
+ *
28
+ * @param key - Non-negative integer key.
29
+ */
30
+ get(key: number): T | undefined;
31
+ /**
32
+ * Remove the entry at `key`. Does nothing if `key` is not present.
33
+ *
34
+ * @param key - Non-negative integer key.
35
+ */
36
+ delete(key: number): void;
37
+ /**
38
+ * Return `true` if an entry exists at `key`.
39
+ *
40
+ * @param key - Non-negative integer key.
41
+ */
42
+ has(key: number): boolean;
43
+ /**
44
+ * Iterate over all present entries.
45
+ *
46
+ * Undefined slots are skipped; the callback is only called for keys that
47
+ * have an associated value.
48
+ *
49
+ * @param callback - Called with `(value, key, map)` for each entry.
50
+ */
51
+ forEach(callback: (value: T, key: number, map: ArrayMap<T>) => void): void;
52
+ /**
53
+ * Remove all entries and reset the size to zero.
54
+ */
55
+ clear(): void;
56
+ /** The number of entries currently in the map. */
57
+ get size(): number;
58
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * A `Map<number, T>` backed by a sparse JavaScript array.
3
+ *
4
+ * For small, dense integer key spaces this is significantly faster than
5
+ * `Map` because array index access avoids the hash-table overhead. Used
6
+ * internally to store per-entity component instances and per-type component
7
+ * metadata.
8
+ *
9
+ * Keys must be non-negative integers. Gaps in the key space are represented
10
+ * as `undefined` slots and do not count toward `size`.
11
+ *
12
+ * @typeParam T - The value type stored in the map.
13
+ */
14
+ export class ArrayMap {
15
+ constructor() {
16
+ this.backend = [];
17
+ this._size = 0;
18
+ }
19
+ /**
20
+ * Store `value` at `key`, replacing any existing value.
21
+ *
22
+ * @param key - Non-negative integer key.
23
+ * @param value - Value to store.
24
+ */
25
+ set(key, value) {
26
+ if (this.backend[key] === undefined) {
27
+ this._size++;
28
+ }
29
+ this.backend[key] = value;
30
+ }
31
+ /**
32
+ * Return the value stored at `key`, or `undefined` if not present.
33
+ *
34
+ * @param key - Non-negative integer key.
35
+ */
36
+ get(key) {
37
+ return this.backend[key];
38
+ }
39
+ /**
40
+ * Remove the entry at `key`. Does nothing if `key` is not present.
41
+ *
42
+ * @param key - Non-negative integer key.
43
+ */
44
+ delete(key) {
45
+ if (this.backend[key] !== undefined) {
46
+ this.backend[key] = undefined;
47
+ this._size--;
48
+ }
49
+ }
50
+ /**
51
+ * Return `true` if an entry exists at `key`.
52
+ *
53
+ * @param key - Non-negative integer key.
54
+ */
55
+ has(key) {
56
+ return this.backend[key] !== undefined;
57
+ }
58
+ /**
59
+ * Iterate over all present entries.
60
+ *
61
+ * Undefined slots are skipped; the callback is only called for keys that
62
+ * have an associated value.
63
+ *
64
+ * @param callback - Called with `(value, key, map)` for each entry.
65
+ */
66
+ forEach(callback) {
67
+ this.backend.forEach((value, index) => {
68
+ if (value !== undefined) {
69
+ callback(value, index, this);
70
+ }
71
+ });
72
+ }
73
+ /**
74
+ * Remove all entries and reset the size to zero.
75
+ */
76
+ clear() {
77
+ this.backend.length = 0;
78
+ }
79
+ /** The number of entries currently in the map. */
80
+ get size() {
81
+ return this._size;
82
+ }
83
+ }
84
+ //# sourceMappingURL=array_map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"array_map.js","sourceRoot":"","sources":["../../src/util/array_map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,QAAQ;IAInB;QACE,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IACjB,CAAC;IAED;;;;;OAKG;IACH,GAAG,CAAC,GAAW,EAAE,KAAQ;QACvB,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE;YACnC,IAAI,CAAC,KAAK,EAAE,CAAC;SACd;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACH,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,GAAW;QAChB,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE;YACnC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;YAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;SACd;IACH,CAAC;IAED;;;;OAIG;IACH,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC;IACzC,CAAC;IAED;;;;;;;OAOG;IACH,OAAO,CAAC,QAA2D;QACjE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YACpC,IAAI,KAAK,KAAK,SAAS,EAAE;gBACvB,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;aAC9B;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,kDAAkD;IAClD,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;CACF"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * A compact, growable set of non-negative integers backed by an array of
3
+ * 32-bit words.
4
+ *
5
+ * Used internally to represent entity archetypes (the set of component type
6
+ * ids attached to an entity) and system watchlists. Exposed in the public API
7
+ * so that component data can use it for bit-flag fields:
8
+ *
9
+ * ```ts
10
+ * class Tags extends Component {
11
+ * tags = new Bitset();
12
+ * oldTags = new Bitset();
13
+ * }
14
+ *
15
+ * // Check a specific tag bit:
16
+ * if (tags.tags.has(TAG_VISIBLE)) { ... }
17
+ * ```
18
+ */
19
+ export declare class Bitset {
20
+ private bits;
21
+ constructor();
22
+ /**
23
+ * Return `true` if this bitset and `other` have exactly the same bits set.
24
+ */
25
+ equal(other: Bitset): boolean;
26
+ /**
27
+ * OR the given `bitmask` word into the word at position `arrayIndex`.
28
+ *
29
+ * @internal Low-level bulk operation; prefer {@link add} for single bits.
30
+ */
31
+ addIndexBitmask(arrayIndex: number, bitmask: number): void;
32
+ /**
33
+ * Replace the word at position `arrayIndex` with `bitmask`.
34
+ *
35
+ * @internal Used by network deserialization to set a whole word at once.
36
+ */
37
+ setIndexBitmask(arrayIndex: number, bitmask: number): void;
38
+ /**
39
+ * Set the bit described by `bptr` (fast path using a pre-computed
40
+ * {@link BitPtr}).
41
+ */
42
+ addBit(bptr: BitPtr): void;
43
+ /**
44
+ * Set bit `n`.
45
+ *
46
+ * @param n - Non-negative integer bit index.
47
+ */
48
+ add(n: number): void;
49
+ /**
50
+ * Clear bit `n`.
51
+ *
52
+ * Trailing zero words are trimmed so that the internal array stays compact.
53
+ *
54
+ * @param n - Non-negative integer bit index.
55
+ */
56
+ delete(n: number): void;
57
+ /**
58
+ * Return `true` if the bit described by `bptr` is set (fast path).
59
+ */
60
+ hasBit(bptr: BitPtr): boolean;
61
+ /**
62
+ * Return `true` if bit `n` is set.
63
+ *
64
+ * @param n - Non-negative integer bit index.
65
+ */
66
+ has(n: number): boolean;
67
+ /**
68
+ * Return `true` if the given word-level bitmask is fully set at `arrayIndex`.
69
+ *
70
+ * @internal
71
+ */
72
+ hasIndexBitmask(arrayIndex: number, bitmask: number): boolean;
73
+ /**
74
+ * Return `true` if every bit set in `other` is also set in `this` (i.e.
75
+ * `other` is a subset of `this`).
76
+ *
77
+ * Used by the world to test whether an entity's archetype satisfies a
78
+ * system's `HAS` query.
79
+ */
80
+ hasBitset(other: Bitset): boolean;
81
+ /**
82
+ * Iterate over every set bit index in ascending order.
83
+ *
84
+ * @param callback - Called with each set bit index.
85
+ */
86
+ forEach(callback: (n: number) => void): void;
87
+ /**
88
+ * Return an array of all set bit indices in ascending order.
89
+ *
90
+ * @returns `number[]` of set bit positions.
91
+ */
92
+ indices(): number[];
93
+ }
94
+ /**
95
+ * A pre-computed pointer into a {@link Bitset}'s internal word array.
96
+ *
97
+ * Computing `arrayIndex` and `bitmask` from a raw bit index requires a floor
98
+ * division and a bitshift. `BitPtr` caches those values so that hot-path
99
+ * archetype checks ({@link Bitset.hasBit}, {@link Bitset.addBit}) avoid
100
+ * repeating the arithmetic on every entity update.
101
+ *
102
+ * A `BitPtr` is created once per component type and stored on
103
+ * {@link ComponentMeta.bitPtr}.
104
+ */
105
+ export declare class BitPtr {
106
+ /** The raw bit index this pointer refers to. */
107
+ readonly value: number;
108
+ /** Index of the 32-bit word that contains this bit. */
109
+ readonly arrayIndex: number;
110
+ /** Single-bit mask within that word. */
111
+ readonly bitmask: number;
112
+ constructor(
113
+ /** The raw bit index this pointer refers to. */
114
+ value: number);
115
+ /** Return `true` if both pointers refer to the same bit position. */
116
+ equals(other: BitPtr): boolean;
117
+ }