@vworlds/vecs 1.0.5 → 1.0.7
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/.prettierrc +7 -0
- package/README.md +100 -78
- package/dist/component.d.ts +9 -7
- package/dist/component.js +7 -8
- package/dist/component.js.map +1 -1
- package/dist/dsl.d.ts +4 -1
- package/dist/dsl.js +1 -2
- package/dist/dsl.js.map +1 -1
- package/dist/entity.d.ts +49 -15
- package/dist/entity.js +37 -13
- package/dist/entity.js.map +1 -1
- package/dist/filter.js +5 -3
- package/dist/filter.js.map +1 -1
- package/dist/package.json +16 -2
- package/dist/query.js +11 -6
- package/dist/query.js.map +1 -1
- package/dist/system.js +14 -7
- package/dist/system.js.map +1 -1
- package/dist/util/bitset.d.ts +2 -1
- package/dist/util/bitset.js +18 -17
- package/dist/util/bitset.js.map +1 -1
- package/dist/util/events.js.map +1 -1
- package/dist/world.d.ts +5 -4
- package/dist/world.js +58 -39
- package/dist/world.js.map +1 -1
- package/eslint.config.js +17 -0
- package/package.json +16 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
npx lint-staged
|
package/.prettierrc
ADDED
package/README.md
CHANGED
|
@@ -12,14 +12,14 @@ yarn add @vworlds/vecs
|
|
|
12
12
|
|
|
13
13
|
## Concepts
|
|
14
14
|
|
|
15
|
-
| Concept
|
|
16
|
-
|
|
17
|
-
| **World**
|
|
18
|
-
| **Component**
|
|
19
|
-
| **Entity**
|
|
20
|
-
| **Query**
|
|
21
|
-
| **System**
|
|
22
|
-
| **Filter**
|
|
15
|
+
| Concept | What it is |
|
|
16
|
+
| ------------------------ | ------------------------------------------------------------------------------- |
|
|
17
|
+
| **World** | Central container. Owns all entities, runs all systems and queries. |
|
|
18
|
+
| **Component** | A plain data class. Extend `Component` and attach instances to entities. |
|
|
19
|
+
| **Entity** | An integer id with a set of components. Create via the world. |
|
|
20
|
+
| **Query** | A reactive, always-updated set of entities that match a predicate. |
|
|
21
|
+
| **System** | A `Query` with per-tick runtime logic (phases, `update`, `each`, `run`). |
|
|
22
|
+
| **Filter** | A non-reactive, one-shot scan: walks all world entities on each `forEach` call. |
|
|
23
23
|
| **Exclusive components** | A group of components where at most one may be present on any entity at a time. |
|
|
24
24
|
|
|
25
25
|
### Lifecycle in brief
|
|
@@ -117,11 +117,9 @@ world.start(); // freeze registration, sort systems into phases
|
|
|
117
117
|
const bullet = world.createEntity();
|
|
118
118
|
bullet.set(Position, { x: 0, y: 0 });
|
|
119
119
|
|
|
120
|
-
const vel = bullet.set(Velocity, { vx: 5, vy: 0 })
|
|
121
|
-
vel.modified(); // first update: notify Move system
|
|
120
|
+
const vel = bullet.set(Velocity, { vx: 5, vy: 0 }).get(Velocity)!;
|
|
122
121
|
|
|
123
|
-
const hp = bullet.set(Health, { hp: 3 })
|
|
124
|
-
hp.modified();
|
|
122
|
+
const hp = bullet.set(Health, { hp: 3 }).get(Health)!;
|
|
125
123
|
|
|
126
124
|
// ─── Game loop ─────────────────────────────────────────────────────────────
|
|
127
125
|
|
|
@@ -220,10 +218,11 @@ world.start(); // distributes systems to phases, freezes component registration
|
|
|
220
218
|
A standalone `Query` is a reactive entity set without a phase or per-tick callbacks. Use it when you need the matched set kept up-to-date automatically — for example to enumerate scene nodes or find the nearest enemy.
|
|
221
219
|
|
|
222
220
|
```ts
|
|
223
|
-
const enemies = world
|
|
221
|
+
const enemies = world
|
|
222
|
+
.query("Enemies")
|
|
224
223
|
.requires(Enemy, Health)
|
|
225
224
|
.enter((e) => console.log("enemy spawned", e.eid))
|
|
226
|
-
.exit((e)
|
|
225
|
+
.exit((e) => console.log("enemy died", e.eid));
|
|
227
226
|
|
|
228
227
|
world.start();
|
|
229
228
|
// enemies.entities is kept up-to-date automatically
|
|
@@ -242,20 +241,19 @@ A `Filter` is a non-reactive, one-shot scan. It holds no tracked entity set —
|
|
|
242
241
|
world.filter([Position]).forEach((e) => console.log(e.eid));
|
|
243
242
|
|
|
244
243
|
// With component injection:
|
|
245
|
-
world.filter([Position, Velocity])
|
|
246
|
-
.
|
|
247
|
-
|
|
248
|
-
});
|
|
244
|
+
world.filter([Position, Velocity]).forEach([Position, Velocity], (e, [pos, vel]) => {
|
|
245
|
+
pos.x += vel.vx;
|
|
246
|
+
});
|
|
249
247
|
|
|
250
248
|
// Full DSL, with auto-deduced required components:
|
|
251
|
-
world
|
|
249
|
+
world
|
|
250
|
+
.filter({ AND: [{ HAS: Position }, { HAS: Velocity }] })
|
|
252
251
|
.forEach([Position, Velocity], (e, [pos, vel]) => {
|
|
253
252
|
pos.x += vel.vx; // pos and vel are non-null — deduced from AND of HAS
|
|
254
253
|
});
|
|
255
254
|
|
|
256
255
|
// Manual type hint for queries the extractor can't see through:
|
|
257
|
-
world.filter({ OR: [Position, Velocity] }, [Position])
|
|
258
|
-
.forEach([Position], (e, [pos]) => pos.x);
|
|
256
|
+
world.filter({ OR: [Position, Velocity] }, [Position]).forEach([Position], (e, [pos]) => pos.x);
|
|
259
257
|
```
|
|
260
258
|
|
|
261
259
|
Unlike `Query`, a `Filter` requires no name, no `world.start()`, and no `destroy()` — create it anywhere and discard it freely.
|
|
@@ -265,16 +263,16 @@ Unlike `Query`, a `Filter` requires no name, no `world.start()`, and no `destroy
|
|
|
265
263
|
```ts
|
|
266
264
|
// Declare phases in the order they should run each frame:
|
|
267
265
|
const preUpdate = world.addPhase("preupdate");
|
|
268
|
-
const update
|
|
269
|
-
const send
|
|
266
|
+
const update = world.addPhase("update");
|
|
267
|
+
const send = world.addPhase("send");
|
|
270
268
|
|
|
271
269
|
// Each frame, run all phases in registration order:
|
|
272
270
|
world.progress(Date.now(), deltaMs);
|
|
273
271
|
|
|
274
272
|
// Or drive individual phases manually:
|
|
275
273
|
world.runPhase(preUpdate, Date.now(), deltaMs);
|
|
276
|
-
world.runPhase(update,
|
|
277
|
-
world.runPhase(send,
|
|
274
|
+
world.runPhase(update, Date.now(), deltaMs);
|
|
275
|
+
world.runPhase(send, Date.now(), deltaMs);
|
|
278
276
|
```
|
|
279
277
|
|
|
280
278
|
Systems with no explicit phase go into a built-in `"update"` phase.
|
|
@@ -284,10 +282,11 @@ Systems with no explicit phase go into a built-in `"update"` phase.
|
|
|
284
282
|
A hook is a shorthand for reacting to a single component's lifecycle without writing a full system:
|
|
285
283
|
|
|
286
284
|
```ts
|
|
287
|
-
world
|
|
288
|
-
.
|
|
285
|
+
world
|
|
286
|
+
.hook(Sprite)
|
|
287
|
+
.onAdd((sprite) => sprite.initialize(scene))
|
|
289
288
|
.onRemove((sprite) => sprite.destroy())
|
|
290
|
-
.onSet((sprite)
|
|
289
|
+
.onSet((sprite) => sprite.syncToScene());
|
|
291
290
|
```
|
|
292
291
|
|
|
293
292
|
`onSet` fires whenever `component.modified()` is called.
|
|
@@ -308,19 +307,23 @@ class Position extends Component {
|
|
|
308
307
|
|
|
309
308
|
world.registerComponent(Position);
|
|
310
309
|
|
|
311
|
-
|
|
310
|
+
entity.add(Position);
|
|
311
|
+
const pos = entity.get(Position)!;
|
|
312
312
|
pos.x = 100;
|
|
313
313
|
pos.modified(); // tell the world this component changed
|
|
314
|
+
|
|
315
|
+
// Alternatively:
|
|
316
|
+
entity.set(Position, { x: 100 });
|
|
314
317
|
```
|
|
315
318
|
|
|
316
319
|
Every component instance exposes:
|
|
317
320
|
|
|
318
|
-
| Property / Method | Description
|
|
319
|
-
|
|
320
|
-
| `entity`
|
|
321
|
-
| `meta`
|
|
322
|
-
| `type`
|
|
323
|
-
| `modified()`
|
|
321
|
+
| Property / Method | Description |
|
|
322
|
+
| ----------------- | --------------------------------------------------------------------- |
|
|
323
|
+
| `entity` | The `Entity` this component belongs to. |
|
|
324
|
+
| `meta` | `ComponentMeta` — holds the type id, name, and bitset pointer. |
|
|
325
|
+
| `type` | Numeric type id (shorthand for `meta.type`). |
|
|
326
|
+
| `modified()` | Queue an `onSet` / `update` notification. Call after mutating fields. |
|
|
324
327
|
|
|
325
328
|
---
|
|
326
329
|
|
|
@@ -330,21 +333,34 @@ Every component instance exposes:
|
|
|
330
333
|
const e = world.createEntity();
|
|
331
334
|
```
|
|
332
335
|
|
|
333
|
-
| Property / Method
|
|
334
|
-
|
|
335
|
-
| `eid`
|
|
336
|
-
| `world`
|
|
337
|
-
| `add(Class)`
|
|
338
|
-
| `set(Class, props)`
|
|
339
|
-
| `
|
|
340
|
-
| `
|
|
341
|
-
| `
|
|
342
|
-
| `
|
|
343
|
-
| `
|
|
344
|
-
| `
|
|
345
|
-
| `
|
|
346
|
-
| `
|
|
347
|
-
| `
|
|
336
|
+
| Property / Method | Description |
|
|
337
|
+
| ---------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
338
|
+
| `eid` | Unique numeric entity id. |
|
|
339
|
+
| `world` | The `World` that owns this entity. |
|
|
340
|
+
| `add(Class)` | Attach a component and return the entity for chaining. Idempotent. |
|
|
341
|
+
| `set(Class, props)` | Like `add`, but also assigns the given partial properties onto the instance. Returns the entity for chaining. |
|
|
342
|
+
| `modified(component)` | Queue an `onSet` / `update` notification for the component. Returns the entity for chaining. |
|
|
343
|
+
| `get(Class)` | Return the component instance, or `undefined` if not present. |
|
|
344
|
+
| `remove(Class)` | Detach a component (triggers `onRemove` hooks and `exit` callbacks). |
|
|
345
|
+
| `destroy()` | Remove all components and unregister the entity. Recurses to children. |
|
|
346
|
+
| `empty` | `true` when no components are attached. |
|
|
347
|
+
| `forEachComponent(cb)` | Iterate over all attached components. |
|
|
348
|
+
| `parent` | Parent entity in the scene hierarchy, or `undefined`. |
|
|
349
|
+
| `children` | `Set<Entity>` of direct children (lazy, created on first access). |
|
|
350
|
+
| `events` | Typed event emitter. Currently emits `"destroy"` before teardown. |
|
|
351
|
+
| `properties` | `Map<string, any>` free-form bag for module-level bookkeeping. |
|
|
352
|
+
|
|
353
|
+
`entity.modified(c)` is equivalent to `c.modified()` but returns the entity, making it usable in a method chain:
|
|
354
|
+
|
|
355
|
+
```ts
|
|
356
|
+
// Mutate fields then signal the change inline:
|
|
357
|
+
const vel = entity.get(Velocity)!;
|
|
358
|
+
vel.vx += accel;
|
|
359
|
+
entity.modified(vel); // same effect as vel.modified(), returns entity
|
|
360
|
+
|
|
361
|
+
// Or in a chain — add without initial notification, then notify later:
|
|
362
|
+
entity.add(Position, false).modified(entity.get(Position)!);
|
|
363
|
+
```
|
|
348
364
|
|
|
349
365
|
#### Parent–child hierarchy
|
|
350
366
|
|
|
@@ -385,15 +401,15 @@ Declare which entities the system should track:
|
|
|
385
401
|
|
|
386
402
|
**Query operators:**
|
|
387
403
|
|
|
388
|
-
| Operator
|
|
389
|
-
|
|
390
|
-
| `{ HAS: [A, B] }`
|
|
404
|
+
| Operator | Meaning |
|
|
405
|
+
| ---------------------- | ---------------------------------------- |
|
|
406
|
+
| `{ HAS: [A, B] }` | Entity has all of A and B |
|
|
391
407
|
| `{ HAS_ONLY: [A, B] }` | Entity has exactly A and B, nothing else |
|
|
392
|
-
| `{ AND: [q1, q2] }`
|
|
393
|
-
| `{ OR: [q1, q2] }`
|
|
394
|
-
| `{ NOT: q }`
|
|
395
|
-
| `{ PARENT: q }`
|
|
396
|
-
| An array `[A, B]`
|
|
408
|
+
| `{ AND: [q1, q2] }` | Both sub-queries must match |
|
|
409
|
+
| `{ OR: [q1, q2] }` | Either sub-query matches |
|
|
410
|
+
| `{ NOT: q }` | Sub-query must not match |
|
|
411
|
+
| `{ PARENT: q }` | Entity's parent matches q |
|
|
412
|
+
| An array `[A, B]` | Shorthand for `HAS: [A, B]` |
|
|
397
413
|
|
|
398
414
|
**Type inference:** `requires()` records the listed classes as a type parameter on the system. Callbacks in `.sort()`, `.each()`, and `.update()` inject then treat those components as non-nullable — no `!` needed. For complex `query()` expressions the type system cannot introspect, pass a second argument as an explicit hint:
|
|
399
415
|
|
|
@@ -485,7 +501,8 @@ Enable sorted entity tracking. Matched entities are stored in an ordered set who
|
|
|
485
501
|
Components declared via `requires()` are non-null in the compare callback.
|
|
486
502
|
|
|
487
503
|
```ts
|
|
488
|
-
world
|
|
504
|
+
world
|
|
505
|
+
.system("Render")
|
|
489
506
|
.requires(Position, Sprite)
|
|
490
507
|
.sort([Position], ([posA], [posB]) => posA.z - posB.z)
|
|
491
508
|
.each([Position, Sprite], (e, [pos, sprite]) => {
|
|
@@ -518,31 +535,36 @@ Called every tick when the system's phase runs, regardless of entity state. Use
|
|
|
518
535
|
A standalone query is created via `world.query(name)` and configured through the same fluent builder API as `System` (`requires`, `query`, `enter`, `exit`, `sort`, `track`, `forEach`, `entities`). It has no phase and no per-tick callbacks.
|
|
519
536
|
|
|
520
537
|
```ts
|
|
521
|
-
const projectiles = world
|
|
538
|
+
const projectiles = world
|
|
539
|
+
.query("Projectiles")
|
|
522
540
|
.requires(Position, Velocity)
|
|
523
541
|
.sort([Position], ([a], [b]) => a.z - b.z)
|
|
524
|
-
.enter([Position], (e, [pos]) => {
|
|
542
|
+
.enter([Position], (e, [pos]) => {
|
|
543
|
+
pos.x = spawnX;
|
|
544
|
+
});
|
|
525
545
|
|
|
526
546
|
world.start();
|
|
527
547
|
|
|
528
548
|
// Anywhere in game code:
|
|
529
|
-
projectiles.forEach((e) => {
|
|
549
|
+
projectiles.forEach((e) => {
|
|
550
|
+
/* ... */
|
|
551
|
+
});
|
|
530
552
|
console.log(projectiles.entities.size, "active projectiles");
|
|
531
553
|
```
|
|
532
554
|
|
|
533
|
-
| Method
|
|
534
|
-
|
|
535
|
-
| `.requires(...components)`
|
|
536
|
-
| `.query(expr)`
|
|
537
|
-
| `.enter(callback)` / `.enter(inject, callback)` | Fires when an entity joins the query.
|
|
538
|
-
| `.exit(callback)` / `.exit(inject, callback)`
|
|
539
|
-
| `.sort(components, compare)`
|
|
540
|
-
| `.track()`
|
|
541
|
-
| `.belongs(e)`
|
|
542
|
-
| `.forEach(callback)`
|
|
543
|
-
| `.forEach(components, callback)`
|
|
544
|
-
| `.entities`
|
|
545
|
-
| `.destroy()`
|
|
555
|
+
| Method | Description |
|
|
556
|
+
| ----------------------------------------------- | ------------------------------------------------------------------------- |
|
|
557
|
+
| `.requires(...components)` | Set the membership predicate and start tracking. |
|
|
558
|
+
| `.query(expr)` | Set the membership predicate using the {@link SystemQuery} DSL. |
|
|
559
|
+
| `.enter(callback)` / `.enter(inject, callback)` | Fires when an entity joins the query. |
|
|
560
|
+
| `.exit(callback)` / `.exit(inject, callback)` | Fires when an entity leaves the query. |
|
|
561
|
+
| `.sort(components, compare)` | Store matched entities in sorted order. |
|
|
562
|
+
| `.track()` | Enable tracking (implied by `sort`; backfills when called after `start`). |
|
|
563
|
+
| `.belongs(e)` | Returns `true` if the entity satisfies the predicate. |
|
|
564
|
+
| `.forEach(callback)` | Iterate all currently tracked entities (entity only). |
|
|
565
|
+
| `.forEach(components, callback)` | Iterate with component injection — same signature as `Filter.forEach`. |
|
|
566
|
+
| `.entities` | `ReadonlySet<Entity>` of all currently tracked entities. |
|
|
567
|
+
| `.destroy()` | Remove the query from the world and all entities. See below. |
|
|
546
568
|
|
|
547
569
|
#### `.destroy()`
|
|
548
570
|
|
|
@@ -568,9 +590,9 @@ A `Filter` is created via `world.filter(dsl)` and provides a non-reactive `forEa
|
|
|
568
590
|
const f = world.filter([Position, Velocity]);
|
|
569
591
|
```
|
|
570
592
|
|
|
571
|
-
| Method
|
|
572
|
-
|
|
573
|
-
| `.forEach(callback)`
|
|
593
|
+
| Method | Description |
|
|
594
|
+
| -------------------------------- | -------------------------------------------------------------------------- |
|
|
595
|
+
| `.forEach(callback)` | Walk all world entities; invoke callback for each matching one. |
|
|
574
596
|
| `.forEach(components, callback)` | Same, with component injection and non-null types for required components. |
|
|
575
597
|
|
|
576
598
|
**Type inference** works the same way as for `requires()` on systems/queries: component classes extractable from the DSL (`HAS`, `HAS_ONLY`, plain arrays, and `AND` of those) are non-nullable in the callback tuple. Pass a `_guaranteed` second argument to `world.filter()` as a manual override when inference can't reach:
|
package/dist/component.d.ts
CHANGED
|
@@ -65,9 +65,12 @@ export declare class ComponentMeta implements Hook<Component> {
|
|
|
65
65
|
readonly componentName: string;
|
|
66
66
|
/** Pre-computed bit-pointer into the entity archetype {@link Bitset}. */
|
|
67
67
|
readonly bitPtr: BitPtr;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
/** @internal */
|
|
69
|
+
_onAddHandler: ((c: Component) => void) | undefined;
|
|
70
|
+
/** @internal */
|
|
71
|
+
_onRemoveHandler: ((c: Component) => void) | undefined;
|
|
72
|
+
/** @internal */
|
|
73
|
+
_onSetHandler: ((c: Component) => void) | undefined;
|
|
71
74
|
/**
|
|
72
75
|
* Type ids of components that cannot coexist with this one on the same entity.
|
|
73
76
|
* Set via {@link World.setExclusiveComponents}. `undefined` means no restrictions.
|
|
@@ -97,9 +100,7 @@ export type ComponentClassArray = ComponentClassOrType[];
|
|
|
97
100
|
* }
|
|
98
101
|
*
|
|
99
102
|
* world.registerComponent(Position);
|
|
100
|
-
*
|
|
101
|
-
* pos.x = 100;
|
|
102
|
-
* pos.modified(); // notify watching systems
|
|
103
|
+
* entity.set(Position, { x: 100 });
|
|
103
104
|
* ```
|
|
104
105
|
*
|
|
105
106
|
* A component instance is always bound to a single entity and is created by
|
|
@@ -110,7 +111,8 @@ export declare class Component {
|
|
|
110
111
|
readonly entity: Entity;
|
|
111
112
|
/** Registration metadata (type id, name, bit-pointer). */
|
|
112
113
|
readonly meta: ComponentMeta;
|
|
113
|
-
|
|
114
|
+
/** @internal */
|
|
115
|
+
_dirty: boolean;
|
|
114
116
|
constructor(
|
|
115
117
|
/** The entity this component belongs to. */
|
|
116
118
|
entity: Entity,
|
package/dist/component.js
CHANGED
|
@@ -23,17 +23,17 @@ export class ComponentMeta {
|
|
|
23
23
|
}
|
|
24
24
|
/** @inheritdoc */
|
|
25
25
|
onAdd(handler) {
|
|
26
|
-
this.
|
|
26
|
+
this._onAddHandler = handler;
|
|
27
27
|
return this;
|
|
28
28
|
}
|
|
29
29
|
/** @inheritdoc */
|
|
30
30
|
onRemove(handler) {
|
|
31
|
-
this.
|
|
31
|
+
this._onRemoveHandler = handler;
|
|
32
32
|
return this;
|
|
33
33
|
}
|
|
34
34
|
/** @inheritdoc */
|
|
35
35
|
onSet(handler) {
|
|
36
|
-
this.
|
|
36
|
+
this._onSetHandler = handler;
|
|
37
37
|
return this;
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -49,9 +49,7 @@ export class ComponentMeta {
|
|
|
49
49
|
* }
|
|
50
50
|
*
|
|
51
51
|
* world.registerComponent(Position);
|
|
52
|
-
*
|
|
53
|
-
* pos.x = 100;
|
|
54
|
-
* pos.modified(); // notify watching systems
|
|
52
|
+
* entity.set(Position, { x: 100 });
|
|
55
53
|
* ```
|
|
56
54
|
*
|
|
57
55
|
* A component instance is always bound to a single entity and is created by
|
|
@@ -65,7 +63,8 @@ export class Component {
|
|
|
65
63
|
meta) {
|
|
66
64
|
this.entity = entity;
|
|
67
65
|
this.meta = meta;
|
|
68
|
-
|
|
66
|
+
/** @internal */
|
|
67
|
+
this._dirty = false;
|
|
69
68
|
}
|
|
70
69
|
/** Numeric type id — shorthand for `this.meta.type`. */
|
|
71
70
|
get type() {
|
|
@@ -83,7 +82,7 @@ export class Component {
|
|
|
83
82
|
* fields to ensure systems react to the new values.
|
|
84
83
|
*/
|
|
85
84
|
modified() {
|
|
86
|
-
this.entity.
|
|
85
|
+
this.entity.modified(this);
|
|
87
86
|
}
|
|
88
87
|
/** Returns the component's registered name, e.g. `"Position"`. */
|
|
89
88
|
toString() {
|
package/dist/component.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.js","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAoDlD;;;;;;;;;GASG;AACH,MAAM,OAAO,aAAa;
|
|
1
|
+
{"version":3,"file":"component.js","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAoDlD;;;;;;;;;GASG;AACH,MAAM,OAAO,aAAa;IAqBxB,YAAY,KAAuB,EAAE,IAAY,EAAE,aAAqB;QANxE;;;WAGG;QACI,cAAS,GAAyB,SAAS,CAAC;QAGjD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,kBAAkB;IACX,KAAK,CAAC,OAA+B;QAC1C,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kBAAkB;IACX,QAAQ,CAAC,OAA+B;QAC7C,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kBAAkB;IACX,KAAK,CAAC,OAA+B;QAC1C,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAQD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,SAAS;IAIpB;IACE,4CAA4C;IAC5B,MAAc;IAC9B,0DAA0D;IAC1C,IAAmB;QAFnB,WAAM,GAAN,MAAM,CAAQ;QAEd,SAAI,GAAJ,IAAI,CAAe;QAPrC,gBAAgB;QACT,WAAM,GAAY,KAAK,CAAC;IAO5B,CAAC;IAEJ,wDAAwD;IACxD,IAAW,IAAI;QACb,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACxB,CAAC;IAED,mEAAmE;IACnE,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAC1B,CAAC;IAED;;;;;;OAMG;IACI,QAAQ;QACb,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,kEAAkE;IAC3D,QAAQ;QACb,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;IACjC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAA4B,EAAE,KAAY;IAClF,MAAM,OAAO,GAAG,IAAI,MAAM,EAAE,CAAC;IAC7B,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/dsl.d.ts
CHANGED
|
@@ -65,7 +65,10 @@ export type ExtractRequired<Q> = Q extends typeof Component ? [Q] : Q extends re
|
|
|
65
65
|
} ? ExtractRequired<H> : Q extends {
|
|
66
66
|
AND: infer A extends readonly QueryDSL[];
|
|
67
67
|
} ? ExtractAndChain<A> : [];
|
|
68
|
-
type ExtractAndChain<A extends readonly QueryDSL[]> = A extends readonly [
|
|
68
|
+
type ExtractAndChain<A extends readonly QueryDSL[]> = A extends readonly [
|
|
69
|
+
infer First,
|
|
70
|
+
...infer Rest extends readonly QueryDSL[]
|
|
71
|
+
] ? [...ExtractRequired<First>, ...ExtractAndChain<Rest>] : [];
|
|
69
72
|
/** Convert a {@link QueryDSL} expression into a runtime entity-test predicate. */
|
|
70
73
|
export declare function buildEntityTest(world: World, q: QueryDSL): EntityTestFunc;
|
|
71
74
|
export {};
|
package/dist/dsl.js
CHANGED
|
@@ -21,8 +21,7 @@ function PARENT(func) {
|
|
|
21
21
|
}
|
|
22
22
|
/** Convert a {@link QueryDSL} expression into a runtime entity-test predicate. */
|
|
23
23
|
export function buildEntityTest(world, q) {
|
|
24
|
-
if (typeof q === "number" ||
|
|
25
|
-
(typeof q === "function" && q.prototype instanceof Component)) {
|
|
24
|
+
if (typeof q === "number" || (typeof q === "function" && q.prototype instanceof Component)) {
|
|
26
25
|
return HAS(world, q);
|
|
27
26
|
}
|
|
28
27
|
else if (typeof q === "function") {
|
package/dist/dsl.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dsl.js","sourceRoot":"","sources":["../src/dsl.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EAGT,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AAyCxB,MAAM,UAAU,GAAG,CAAC,KAAY,EAAE,GAAG,UAA+B;IAClE,MAAM,WAAW,GAAG,yBAAyB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IACjE,OAAO,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,QAAQ,CAAC,KAAY,EAAE,GAAG,UAA+B;IAChE,MAAM,WAAW,GAAG,yBAAyB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IACjE,OAAO,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,GAAG,CAAC,IAAoB;IAC/B,OAAO,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,GAAG,CAAC,GAAG,KAAuB;IACrC,OAAO,CAAC,CAAS,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,EAAE,CAAC,GAAG,KAAuB;IACpC,OAAO,CAAC,CAAS,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,MAAM,CAAC,IAAoB;IAClC,OAAO,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,CAAC;AAC9D,CAAC;AA4CD,kFAAkF;AAClF,MAAM,UAAU,eAAe,CAAC,KAAY,EAAE,CAAW;IACvD,
|
|
1
|
+
{"version":3,"file":"dsl.js","sourceRoot":"","sources":["../src/dsl.ts"],"names":[],"mappings":"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"}
|
package/dist/entity.d.ts
CHANGED
|
@@ -16,9 +16,7 @@ type EntityEvents = Events<{
|
|
|
16
16
|
*
|
|
17
17
|
* ```ts
|
|
18
18
|
* const e = world.createEntity();
|
|
19
|
-
*
|
|
20
|
-
* pos.x = 100;
|
|
21
|
-
* pos.modified();
|
|
19
|
+
* e.set(Position, { x: 100 });
|
|
22
20
|
* ```
|
|
23
21
|
*
|
|
24
22
|
* Entities support a parent–child hierarchy. When a parent is destroyed its
|
|
@@ -47,7 +45,8 @@ export declare class Entity {
|
|
|
47
45
|
_events: EntityEvents;
|
|
48
46
|
/** Parent entity in the scene hierarchy, or `undefined` if root. */
|
|
49
47
|
parent: Entity | undefined;
|
|
50
|
-
|
|
48
|
+
/** @internal */
|
|
49
|
+
_children: Set<Entity> | undefined;
|
|
51
50
|
_archetypeChanged: boolean;
|
|
52
51
|
private destroyed;
|
|
53
52
|
constructor(
|
|
@@ -64,6 +63,17 @@ export declare class Entity {
|
|
|
64
63
|
*/
|
|
65
64
|
get children(): Set<Entity>;
|
|
66
65
|
private getComponentInstance;
|
|
66
|
+
/**
|
|
67
|
+
* Queue an `onSet` / `update` notification for the given component and
|
|
68
|
+
* return the entity for chaining.
|
|
69
|
+
*
|
|
70
|
+
* Equivalent to `component.modified()`, but usable inside an entity method
|
|
71
|
+
* chain (e.g. after `add` or `set`).
|
|
72
|
+
*
|
|
73
|
+
* @param c - The component instance whose data changed.
|
|
74
|
+
* @returns This entity, for chaining.
|
|
75
|
+
*/
|
|
76
|
+
modified<C extends typeof Component>(c: InstanceType<C>): Entity;
|
|
67
77
|
/**
|
|
68
78
|
* Add a component of type `Class` to this entity and return the instance.
|
|
69
79
|
*
|
|
@@ -78,7 +88,29 @@ export declare class Entity {
|
|
|
78
88
|
* @returns The new (or existing) component instance, typed as
|
|
79
89
|
* `InstanceType<Class>`.
|
|
80
90
|
*/
|
|
81
|
-
|
|
91
|
+
_add<C extends typeof Component>(Class: C, markAsModified?: boolean): InstanceType<C>;
|
|
92
|
+
/**
|
|
93
|
+
* Add a component by its numeric type id.
|
|
94
|
+
*
|
|
95
|
+
* @param type - Numeric component type id (as returned by
|
|
96
|
+
* {@link World.getComponentType}).
|
|
97
|
+
* @param markAsModified - Whether to queue an update notification.
|
|
98
|
+
*/
|
|
99
|
+
_add(type: number, markAsModified?: boolean): Component;
|
|
100
|
+
/**
|
|
101
|
+
* Add a component of type `Class` to this entity and return the entity.
|
|
102
|
+
*
|
|
103
|
+
* If the component is already present the existing instance is returned and
|
|
104
|
+
* no callback is fired. Pass `markAsModified = false` to suppress the
|
|
105
|
+
* initial `onSet` / `update` notification (useful when bulk-loading
|
|
106
|
+
* network snapshots before systems are running).
|
|
107
|
+
*
|
|
108
|
+
* @param Class - The component class to instantiate.
|
|
109
|
+
* @param markAsModified - Whether to immediately queue an `update`
|
|
110
|
+
* notification. Defaults to `true`.
|
|
111
|
+
* @returns This entity, for chaining.
|
|
112
|
+
*/
|
|
113
|
+
add<C extends typeof Component>(Class: C, markAsModified?: boolean): Entity;
|
|
82
114
|
/**
|
|
83
115
|
* Add a component by its numeric type id.
|
|
84
116
|
*
|
|
@@ -86,23 +118,24 @@ export declare class Entity {
|
|
|
86
118
|
* {@link World.getComponentType}).
|
|
87
119
|
* @param markAsModified - Whether to queue an update notification.
|
|
88
120
|
*/
|
|
89
|
-
add(type: number, markAsModified?: boolean):
|
|
121
|
+
add(type: number, markAsModified?: boolean): Entity;
|
|
90
122
|
/**
|
|
91
|
-
* Add a component of type `Class` (if not already present)
|
|
92
|
-
* provided properties onto the instance,
|
|
123
|
+
* Add a component of type `Class` (if not already present), assign the
|
|
124
|
+
* provided properties onto the instance, and return the entity for chaining.
|
|
93
125
|
*
|
|
94
126
|
* @param Class - The component class to instantiate.
|
|
95
|
-
* @param props -
|
|
96
|
-
* @returns
|
|
127
|
+
* @param props - Properties to assign onto the component instance.
|
|
128
|
+
* @returns This entity, for chaining.
|
|
97
129
|
*/
|
|
98
|
-
set<C extends typeof Component>(Class: C, props: Partial<InstanceType<C>>):
|
|
130
|
+
set<C extends typeof Component>(Class: C, props: Partial<InstanceType<C>>): Entity;
|
|
99
131
|
/**
|
|
100
|
-
* Add a component by its numeric type id
|
|
132
|
+
* Add a component by its numeric type id, assign the provided properties,
|
|
133
|
+
* and return the entity for chaining.
|
|
101
134
|
*
|
|
102
135
|
* @param type - Numeric component type id.
|
|
103
|
-
* @param props -
|
|
136
|
+
* @param props - Properties to assign onto the component instance.
|
|
104
137
|
*/
|
|
105
|
-
set(type: number, props: Partial<Component>):
|
|
138
|
+
set(type: number, props: Partial<Component>): Entity;
|
|
106
139
|
/**
|
|
107
140
|
* Remove the component of the given class from this entity.
|
|
108
141
|
*
|
|
@@ -152,7 +185,8 @@ export declare class Entity {
|
|
|
152
185
|
_updateQueries(): void;
|
|
153
186
|
/** `true` when the entity has no components attached. */
|
|
154
187
|
get empty(): boolean;
|
|
155
|
-
|
|
188
|
+
/** @internal */
|
|
189
|
+
_destroy(): void;
|
|
156
190
|
/**
|
|
157
191
|
* Destroy this entity and recursively destroy all of its children.
|
|
158
192
|
*
|