@vworlds/vecs 1.0.43 → 1.0.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/component.d.ts +27 -17
- package/dist/component.js +9 -0
- package/dist/component.js.map +1 -1
- package/dist/component_meta.d.ts +40 -13
- package/dist/component_meta.js +22 -6
- package/dist/component_meta.js.map +1 -1
- package/dist/entity/entity.components.d.ts +57 -4
- package/dist/entity/entity.components.js +121 -22
- package/dist/entity/entity.components.js.map +1 -1
- package/dist/entity/entity.d.ts +4 -2
- package/dist/entity/entity.js +4 -2
- package/dist/entity/entity.js.map +1 -1
- package/dist/entity/entity.lifecycle.js +1 -4
- package/dist/entity/entity.lifecycle.js.map +1 -1
- package/dist/entity/entity.relationships.js +3 -0
- package/dist/entity/entity.relationships.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modules/relationship_types.d.ts +18 -0
- package/dist/modules/relationship_types.js +18 -0
- package/dist/modules/relationship_types.js.map +1 -1
- package/dist/modules/relationships.d.ts +8 -2
- package/dist/modules/relationships.js +41 -3
- package/dist/modules/relationships.js.map +1 -1
- package/dist/package.json +1 -1
- package/docs/README.md +6 -6
- package/docs/components.md +77 -13
- package/docs/concepts.md +8 -2
- package/docs/design-guide.md +135 -1
- package/docs/entities.md +62 -6
- package/docs/execution-model.md +8 -4
- package/docs/glossary.md +11 -2
- package/docs/modules.md +7 -7
- package/docs/relationships.md +81 -0
- package/package.json +1 -1
- package/skills/vecs/SKILL.md +81 -0
package/dist/entity/entity.d.ts
CHANGED
|
@@ -20,14 +20,16 @@ export type EntityClass<T extends Entity = Entity> = new (world: World, eid: EID
|
|
|
20
20
|
* ## Deferred semantics
|
|
21
21
|
*
|
|
22
22
|
* Inside a system body or `forEach` iteration the world is in **deferred
|
|
23
|
-
* mode**: `add` / `attach` / `set` / `
|
|
24
|
-
* enqueue commands. The data layer (the components map and
|
|
23
|
+
* mode**: `add` / `attach` / `set` / `ensure` / `ensureTarget` / `modified` / `remove` /
|
|
24
|
+
* `destroy` only enqueue commands. The data layer (the components map and
|
|
25
25
|
* `componentBitmask`) is mutated when the world drains its queue. Concretely,
|
|
26
26
|
* while deferred:
|
|
27
27
|
*
|
|
28
28
|
* - `entity.get(C)` / `entity.getMut(C)` returns `undefined` after `entity.add(C)` (no instance yet).
|
|
29
29
|
* - `entity.get(C)` / `entity.getMut(C)` returns `undefined` after `entity.attach(instance)` if C was absent.
|
|
30
30
|
* - `entity.get(C)` / `entity.getMut(C)` returns the previous value after `entity.set(C, props)`.
|
|
31
|
+
* - `entity.ensure(C)` returns a mutable component immediately, but `entity.get(C)` does not see it until the queue drains.
|
|
32
|
+
* - `entity.ensureTarget(R)` returns its pending target immediately, but `entity.target(R)` does not see it until the queue drains.
|
|
31
33
|
* - `entity.get(C)` / `entity.getMut(C)` still returns the component after `entity.remove(C)`.
|
|
32
34
|
*
|
|
33
35
|
* Outside deferred mode the same calls execute inline and mutations are
|
package/dist/entity/entity.js
CHANGED
|
@@ -16,14 +16,16 @@ import { IdentityEntity } from "./entity.identity.js";
|
|
|
16
16
|
* ## Deferred semantics
|
|
17
17
|
*
|
|
18
18
|
* Inside a system body or `forEach` iteration the world is in **deferred
|
|
19
|
-
* mode**: `add` / `attach` / `set` / `
|
|
20
|
-
* enqueue commands. The data layer (the components map and
|
|
19
|
+
* mode**: `add` / `attach` / `set` / `ensure` / `ensureTarget` / `modified` / `remove` /
|
|
20
|
+
* `destroy` only enqueue commands. The data layer (the components map and
|
|
21
21
|
* `componentBitmask`) is mutated when the world drains its queue. Concretely,
|
|
22
22
|
* while deferred:
|
|
23
23
|
*
|
|
24
24
|
* - `entity.get(C)` / `entity.getMut(C)` returns `undefined` after `entity.add(C)` (no instance yet).
|
|
25
25
|
* - `entity.get(C)` / `entity.getMut(C)` returns `undefined` after `entity.attach(instance)` if C was absent.
|
|
26
26
|
* - `entity.get(C)` / `entity.getMut(C)` returns the previous value after `entity.set(C, props)`.
|
|
27
|
+
* - `entity.ensure(C)` returns a mutable component immediately, but `entity.get(C)` does not see it until the queue drains.
|
|
28
|
+
* - `entity.ensureTarget(R)` returns its pending target immediately, but `entity.target(R)` does not see it until the queue drains.
|
|
27
29
|
* - `entity.get(C)` / `entity.getMut(C)` still returns the component after `entity.remove(C)`.
|
|
28
30
|
*
|
|
29
31
|
* Outside deferred mode the same calls execute inline and mutations are
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity.js","sourceRoot":"","sources":["../../src/entity/entity.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAE3D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAWtD
|
|
1
|
+
{"version":3,"file":"entity.js","sourceRoot":"","sources":["../../src/entity/entity.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAE3D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAWtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,OAAO,MAAO,SAAQ,cAAc;IACxC,kFAAkF;IAC3E,OAAO,CAAC,MAAc;QAC3B,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,wFAAwF;IACxF,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAED,4EAA4E;IAC5E,IAAW,MAAM,CAAC,MAA0B;QAC1C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACvB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,oEAAoE;IACpE,IAAW,SAAS;QAClB,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED,oDAAoD;IACpD,IAAW,KAAK;QACd,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;IAC1B,CAAC;CACF"}
|
|
@@ -50,10 +50,7 @@ export class Lifecycle extends Components {
|
|
|
50
50
|
this.componentBitmask.deleteBit(componentMeta.bitPtr);
|
|
51
51
|
this.world._notifyComponentRemoved(ceid, entity);
|
|
52
52
|
componentMeta._decrementUsage();
|
|
53
|
-
|
|
54
|
-
if (removeHandlers) {
|
|
55
|
-
removeHandlers.forEach((handler) => handler(entity, c));
|
|
56
|
-
}
|
|
53
|
+
componentMeta._onRemove?.(entity, c);
|
|
57
54
|
});
|
|
58
55
|
this._dirtyComponentBitmask.clear();
|
|
59
56
|
this._queries.clear();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity.lifecycle.js","sourceRoot":"","sources":["../../src/entity/entity.lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAIrD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AA4BpD,MAAM,OAAO,SAAU,SAAQ,UAAU;IACvC;;;;OAIG;IACI,QAAQ;QACb,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,OAAO;QACT,CAAC;QACD,yEAAyE;QACzE,4EAA4E;QAC5E,4EAA4E;QAC5E,2EAA2E;QAC3E,kDAAkD;QAClD,MAAM,iBAAiB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC;QACrD,IAAI,iBAAiB,EAAE,CAAC;YACtB,IAAI,CAAC,KAAK,CAAC,cAAc,GAAG,EAAE,CAAC;QACjC,CAAC;QACD,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC;YAC9B,4EAA4E;YAC5E,yEAAyE;YACzE,sDAAsD;YACtD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YACvB,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC/D,IAAI,UAAU,CAAC,UAAU,GAAG,SAAS,EAAE,CAAC;oBACtC,IAAI,UAAU,CAAC,QAAQ,KAAK,aAAa,CAAC,KAAK,EAAE,CAAC;wBAChD,oEAAoE;wBACpE,mEAAmE;wBACnE,gEAAgE;wBAChE,kEAAkE;wBAClE,+CAA+C;wBAC/C,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;wBACxB,OAAO;oBACT,CAAC;oBACD,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC;YAED,MAAM,MAAM,GAAG,IAAyB,CAAC;YACzC,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;YAE1C,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE;gBACnC,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;gBACnD,IAAI,aAAa,CAAC,cAAc,EAAE,CAAC;oBACjC,IAAI,CAAC,eAAe,CAAE,CAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBACzD,CAAC;gBACD,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;gBACtD,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBACjD,aAAa,CAAC,eAAe,EAAE,CAAC;gBAChC,
|
|
1
|
+
{"version":3,"file":"entity.lifecycle.js","sourceRoot":"","sources":["../../src/entity/entity.lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -49,6 +49,9 @@ export class Relationships extends Queries {
|
|
|
49
49
|
}
|
|
50
50
|
this._removeIncoming(oldTarget, meta.eid);
|
|
51
51
|
this._addIncoming(newTarget, meta.eid);
|
|
52
|
+
if (oldTarget && newTarget) {
|
|
53
|
+
meta._onRetarget?.(this, oldTarget, newTarget);
|
|
54
|
+
}
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
57
|
//# sourceMappingURL=entity.relationships.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity.relationships.js","sourceRoot":"","sources":["../../src/entity/entity.relationships.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE9C,MAAM,OAAO,aAAc,SAAQ,OAAO;IACxC,0EAA0E;IACnE,MAAM,CAAC,GAAiB;QAC7B,MAAM,MAAM,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC;QAC1E,OAAQ,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAA8B,EAAE,MAAM,CAAC;IAC5E,CAAC;IAED,qEAAqE;IAC9D,QAAQ,CAAC,GAAiB;QAC/B,MAAM,MAAM,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC;QAC1E,OAAO,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,aAAa,CAAC,cAAc,CAAC;IACrE,CAAC;IAED;;;OAGG;IACI,cAAc,CAAC,MAAW;QAC/B,OAAO,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,gBAAgB;IACN,YAAY,CAAC,MAA0B,EAAE,MAAW;QAC5D,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACjC,OAAO;QACT,CAAC;QACD,IAAI,OAAO,GAAG,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,GAAG,IAAI,QAAQ,EAAU,CAAC;YACjC,CAAC,MAAM,CAAC,SAAS,KAAhB,MAAM,CAAC,SAAS,GAAK,IAAI,gBAAgB,EAAE,EAAC,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACrE,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,IAAyB,CAAC,CAAC;IACzC,CAAC;IAED,gBAAgB;IACN,eAAe,CAAC,MAA0B,EAAE,MAAW;QAC/D,MAAM,OAAO,GAAG,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,IAAyB,CAAC,CAAC;QAC1C,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACvB,MAAO,CAAC,SAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,gBAAgB;IACN,eAAe,CACvB,IAAmB,EACnB,SAA6B,EAC7B,SAA6B;QAE7B,IAAI,CAAC,IAAI,CAAC,cAAc,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YACpD,OAAO;QACT,CAAC;QACD,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"entity.relationships.js","sourceRoot":"","sources":["../../src/entity/entity.relationships.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE9C,MAAM,OAAO,aAAc,SAAQ,OAAO;IACxC,0EAA0E;IACnE,MAAM,CAAC,GAAiB;QAC7B,MAAM,MAAM,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC;QAC1E,OAAQ,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAA8B,EAAE,MAAM,CAAC;IAC5E,CAAC;IAED,qEAAqE;IAC9D,QAAQ,CAAC,GAAiB;QAC/B,MAAM,MAAM,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC;QAC1E,OAAO,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,aAAa,CAAC,cAAc,CAAC;IACrE,CAAC;IAED;;;OAGG;IACI,cAAc,CAAC,MAAW;QAC/B,OAAO,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,gBAAgB;IACN,YAAY,CAAC,MAA0B,EAAE,MAAW;QAC5D,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACjC,OAAO;QACT,CAAC;QACD,IAAI,OAAO,GAAG,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,GAAG,IAAI,QAAQ,EAAU,CAAC;YACjC,CAAC,MAAM,CAAC,SAAS,KAAhB,MAAM,CAAC,SAAS,GAAK,IAAI,gBAAgB,EAAE,EAAC,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACrE,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,IAAyB,CAAC,CAAC;IACzC,CAAC;IAED,gBAAgB;IACN,eAAe,CAAC,MAA0B,EAAE,MAAW;QAC/D,MAAM,OAAO,GAAG,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,IAAyB,CAAC,CAAC;QAC1C,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACvB,MAAO,CAAC,SAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,gBAAgB;IACN,eAAe,CACvB,IAAmB,EACnB,SAA6B,EAC7B,SAA6B;QAE7B,IAAI,CAAC,IAAI,CAAC,cAAc,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YACpD,OAAO;QACT,CAAC;QACD,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,SAAS,IAAI,SAAS,EAAE,CAAC;YAC3B,IAAI,CAAC,WAAW,EAAE,CAAC,IAAyB,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;CACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,8 +5,8 @@ export { Iter } from "./inject.js";
|
|
|
5
5
|
export type { DownInject, FanInjectElement, FanInjectTuple, InjectElement, InjectTuple, MaybeResolvedInjectTuple, RequiredResolvedInjectTuple, TargetInject, } from "./inject.js";
|
|
6
6
|
export { DEFAULT_POOLS, World, type WorldOptions } from "./world/index.js";
|
|
7
7
|
export { Filter } from "./filter.js";
|
|
8
|
-
export { ChildOf, DependsOn, SilenceSource } from "./modules/relationships.js";
|
|
9
|
-
export { CleanupPolicy, Component, Implements, Relationship, type ComponentInstance, type ComponentClass, type ComponentMeta, type ComponentRef, } from "./component.js";
|
|
8
|
+
export { ChildOf, DependsOn, OwnedTarget, SilenceSource } from "./modules/relationships.js";
|
|
9
|
+
export { CleanupPolicy, Component, Implements, Relationship, type ComponentInstance, type ComponentClass, type ComponentMeta, type ComponentRef, type HookHandler, type RetargetHandler, } from "./component.js";
|
|
10
10
|
export { Entity, type EID, type EntityClass, Identity } from "./entity/index.js";
|
|
11
11
|
export { Module, type ModuleConfig } from "./module.js";
|
|
12
12
|
export { IdentityModule } from "./modules/identity.js";
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ export { Query, GroupedQuery, Group } from "./query/index.js";
|
|
|
3
3
|
export { Iter } from "./inject.js";
|
|
4
4
|
export { DEFAULT_POOLS, World } from "./world/index.js";
|
|
5
5
|
export { Filter } from "./filter.js";
|
|
6
|
-
export { ChildOf, DependsOn, SilenceSource } from "./modules/relationships.js";
|
|
6
|
+
export { ChildOf, DependsOn, OwnedTarget, SilenceSource } from "./modules/relationships.js";
|
|
7
7
|
export { CleanupPolicy, Component, Implements, Relationship, } from "./component.js";
|
|
8
8
|
export { Entity, Identity } from "./entity/index.js";
|
|
9
9
|
export { Module } from "./module.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAoB,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9D,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAWnC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAqB,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAoB,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9D,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAWnC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAqB,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC5F,OAAO,EACL,aAAa,EACb,SAAS,EACT,UAAU,EACV,YAAY,GAOb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,MAAM,EAA8B,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAAE,MAAM,EAAqB,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,OAAO,EACP,QAAQ,EACR,SAAS,EACT,WAAW,EACX,SAAS,EACT,WAAW,EACX,SAAS,EACT,UAAU,EACV,KAAK,EACL,cAAc,GACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,IAAI,EAAoC,MAAM,iBAAiB,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAoB,MAAM,YAAY,CAAC;AAClF,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAuC,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAE,4BAA4B,EAAqB,MAAM,mBAAmB,CAAC"}
|
|
@@ -17,6 +17,24 @@ export declare class DependsOn extends Relationship {
|
|
|
17
17
|
*/
|
|
18
18
|
export declare class SilenceSource extends Relationship {
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Marker component that makes every target of a relationship a `ChildOf` child
|
|
22
|
+
* of the relationship source.
|
|
23
|
+
*
|
|
24
|
+
* Add during world setup, before creating relationship instances:
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* world.component(Inventory).add(OwnedTarget);
|
|
28
|
+
* player.add(Inventory); // creates an owned target
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* Adding the relationship creates a target when none was supplied. Retargeting
|
|
32
|
+
* destroys the displaced target, and removing the relationship destroys its
|
|
33
|
+
* current target. Configure owner lifecycle hooks before attaching this trait;
|
|
34
|
+
* the trait wraps them and runs ownership behavior first.
|
|
35
|
+
*/
|
|
36
|
+
export declare class OwnedTarget {
|
|
37
|
+
}
|
|
20
38
|
/**
|
|
21
39
|
* Marker component used to tag a relationship component as traversable.
|
|
22
40
|
*
|
|
@@ -16,6 +16,24 @@ export class DependsOn extends Relationship {
|
|
|
16
16
|
*/
|
|
17
17
|
export class SilenceSource extends Relationship {
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Marker component that makes every target of a relationship a `ChildOf` child
|
|
21
|
+
* of the relationship source.
|
|
22
|
+
*
|
|
23
|
+
* Add during world setup, before creating relationship instances:
|
|
24
|
+
*
|
|
25
|
+
* ```ts
|
|
26
|
+
* world.component(Inventory).add(OwnedTarget);
|
|
27
|
+
* player.add(Inventory); // creates an owned target
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* Adding the relationship creates a target when none was supplied. Retargeting
|
|
31
|
+
* destroys the displaced target, and removing the relationship destroys its
|
|
32
|
+
* current target. Configure owner lifecycle hooks before attaching this trait;
|
|
33
|
+
* the trait wraps them and runs ownership behavior first.
|
|
34
|
+
*/
|
|
35
|
+
export class OwnedTarget {
|
|
36
|
+
}
|
|
19
37
|
/**
|
|
20
38
|
* Marker component used to tag a relationship component as traversable.
|
|
21
39
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relationship_types.js","sourceRoot":"","sources":["../../src/modules/relationship_types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGpD,0CAA0C;AAC1C,MAAM,OAAO,OAAQ,SAAQ,YAAY;CAAG;AAE5C,+CAA+C;AAC/C,MAAM,OAAO,SAAU,SAAQ,YAAY;CAAG;AAE9C;;;;;;;;GAQG;AACH,MAAM,OAAO,aAAc,SAAQ,YAAY;CAAG;AAElD;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,WAAW;IAAxB;QACE,+CAA+C;QAC/C,WAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACrC,CAAC;CAAA"}
|
|
1
|
+
{"version":3,"file":"relationship_types.js","sourceRoot":"","sources":["../../src/modules/relationship_types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGpD,0CAA0C;AAC1C,MAAM,OAAO,OAAQ,SAAQ,YAAY;CAAG;AAE5C,+CAA+C;AAC/C,MAAM,OAAO,SAAU,SAAQ,YAAY;CAAG;AAE9C;;;;;;;;GAQG;AACH,MAAM,OAAO,aAAc,SAAQ,YAAY;CAAG;AAElD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,WAAW;CAAG;AAE3B;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,WAAW;IAAxB;QACE,+CAA+C;QAC/C,WAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACrC,CAAC;CAAA"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Module } from "../module.js";
|
|
2
|
-
export { ChildOf, DependsOn, SilenceSource, Traversable } from "./relationship_types.js";
|
|
2
|
+
export { ChildOf, DependsOn, OwnedTarget, SilenceSource, Traversable, } from "./relationship_types.js";
|
|
3
3
|
/**
|
|
4
4
|
* Built-in world module that registers the `ChildOf` relationship and
|
|
5
|
-
* maintains depth tracking for
|
|
5
|
+
* maintains ownership and depth tracking policies for relationship traits.
|
|
6
6
|
*
|
|
7
7
|
* Registered automatically by every {@link World}. It sets `ChildOf`'s
|
|
8
8
|
* `onDeleteTarget` cleanup policy to {@link CleanupPolicy.Delete}, so
|
|
@@ -14,6 +14,12 @@ export { ChildOf, DependsOn, SilenceSource, Traversable } from "./relationship_t
|
|
|
14
14
|
* every entity's depth is updated when the relationship is added, retargeted,
|
|
15
15
|
* or removed.
|
|
16
16
|
*
|
|
17
|
+
* When a relationship component entity has `OwnedTarget` attached, the module
|
|
18
|
+
* wraps its hooks so adding the relationship creates a target when needed,
|
|
19
|
+
* every target becomes a `ChildOf` child of its source, and targets are
|
|
20
|
+
* destroyed when displaced or removed. Configure this trait after the
|
|
21
|
+
* relationship's owner hooks and before creating relationship instances.
|
|
22
|
+
*
|
|
17
23
|
* Depth is computed by walking `entity.target(relEid)` to the root. When an
|
|
18
24
|
* entity's depth changes, every descendant is recursively recomputed.
|
|
19
25
|
*/
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { CleanupPolicy } from "../component_meta.js";
|
|
2
2
|
import { Module } from "../module.js";
|
|
3
|
-
import { ChildOf, Traversable } from "./relationship_types.js";
|
|
4
|
-
export { ChildOf, DependsOn, SilenceSource, Traversable } from "./relationship_types.js";
|
|
3
|
+
import { ChildOf, OwnedTarget, Traversable } from "./relationship_types.js";
|
|
4
|
+
export { ChildOf, DependsOn, OwnedTarget, SilenceSource, Traversable, } from "./relationship_types.js";
|
|
5
5
|
/**
|
|
6
6
|
* Built-in world module that registers the `ChildOf` relationship and
|
|
7
|
-
* maintains depth tracking for
|
|
7
|
+
* maintains ownership and depth tracking policies for relationship traits.
|
|
8
8
|
*
|
|
9
9
|
* Registered automatically by every {@link World}. It sets `ChildOf`'s
|
|
10
10
|
* `onDeleteTarget` cleanup policy to {@link CleanupPolicy.Delete}, so
|
|
@@ -16,6 +16,12 @@ export { ChildOf, DependsOn, SilenceSource, Traversable } from "./relationship_t
|
|
|
16
16
|
* every entity's depth is updated when the relationship is added, retargeted,
|
|
17
17
|
* or removed.
|
|
18
18
|
*
|
|
19
|
+
* When a relationship component entity has `OwnedTarget` attached, the module
|
|
20
|
+
* wraps its hooks so adding the relationship creates a target when needed,
|
|
21
|
+
* every target becomes a `ChildOf` child of its source, and targets are
|
|
22
|
+
* destroyed when displaced or removed. Configure this trait after the
|
|
23
|
+
* relationship's owner hooks and before creating relationship instances.
|
|
24
|
+
*
|
|
19
25
|
* Depth is computed by walking `entity.target(relEid)` to the root. When an
|
|
20
26
|
* entity's depth changes, every descendant is recursively recomputed.
|
|
21
27
|
*/
|
|
@@ -23,8 +29,40 @@ export class RelationshipsModule extends Module {
|
|
|
23
29
|
init() {
|
|
24
30
|
const world = this.world;
|
|
25
31
|
const childOf = world.component(ChildOf);
|
|
32
|
+
const ownedTarget = world.component(OwnedTarget);
|
|
26
33
|
const traversable = world.component(Traversable);
|
|
27
34
|
childOf.meta.onDeleteTarget = CleanupPolicy.Delete;
|
|
35
|
+
ownedTarget.onAdd((rel) => {
|
|
36
|
+
if (!rel.meta.isRelationship) {
|
|
37
|
+
throw new Error("OwnedTarget can only be added to a Relationship component");
|
|
38
|
+
}
|
|
39
|
+
if (rel === childOf) {
|
|
40
|
+
throw new Error("OwnedTarget cannot be added to ChildOf");
|
|
41
|
+
}
|
|
42
|
+
const onAdd = rel.onAdd();
|
|
43
|
+
const onSet = rel.onSet();
|
|
44
|
+
const onRetarget = rel.onRetarget();
|
|
45
|
+
const onRemove = rel.onRemove();
|
|
46
|
+
rel
|
|
47
|
+
.onAdd((source, component) => {
|
|
48
|
+
const relationship = component;
|
|
49
|
+
relationship.target ?? (relationship.target = world.entity());
|
|
50
|
+
relationship.target.childOf(source);
|
|
51
|
+
onAdd?.(source, component);
|
|
52
|
+
})
|
|
53
|
+
.onSet((source, relationship) => {
|
|
54
|
+
relationship.target.childOf(source);
|
|
55
|
+
onSet?.(source, relationship);
|
|
56
|
+
})
|
|
57
|
+
.onRetarget((source, oldTarget, newTarget) => {
|
|
58
|
+
oldTarget.destroy();
|
|
59
|
+
onRetarget?.(source, oldTarget, newTarget);
|
|
60
|
+
})
|
|
61
|
+
.onRemove((source, relationship) => {
|
|
62
|
+
relationship.target.destroy();
|
|
63
|
+
onRemove?.(source, relationship);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
28
66
|
traversable.onAdd((rel, traversable) => {
|
|
29
67
|
const relEid = rel.eid;
|
|
30
68
|
rel
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relationships.js","sourceRoot":"","sources":["../../src/modules/relationships.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"relationships.js","sourceRoot":"","sources":["../../src/modules/relationships.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAgB,MAAM,sBAAsB,CAAC;AAEnE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE5E,OAAO,EACL,OAAO,EACP,SAAS,EACT,WAAW,EACX,aAAa,EACb,WAAW,GACZ,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,OAAO,mBAAoB,SAAQ,MAAM;IACtC,IAAI;QACT,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACzC,MAAM,WAAW,GAAG,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QACjD,MAAM,WAAW,GAAG,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAEjD,OAAO,CAAC,IAAI,CAAC,cAAc,GAAG,aAAa,CAAC,MAAM,CAAC;QAEnD,WAAW,CAAC,KAAK,CAAC,CAAC,GAAG,EAAQ,EAAE;YAC9B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;gBAC7B,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;YAC/E,CAAC;YACD,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;YAC5D,CAAC;YAED,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC;YAC1B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC;YAC1B,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC;YACpC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;YAEhC,GAAG;iBACA,KAAK,CAAC,CAAC,MAAc,EAAE,SAAS,EAAQ,EAAE;gBACzC,MAAM,YAAY,GAAG,SAAyB,CAAC;gBAC/C,YAAY,CAAC,MAAM,KAAnB,YAAY,CAAC,MAAM,GAAK,KAAK,CAAC,MAAM,EAAE,EAAC;gBACvC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBACpC,KAAK,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YAC7B,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,MAAc,EAAE,YAAY,EAAQ,EAAE;gBAC3C,YAA6B,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBACtD,KAAK,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YAChC,CAAC,CAAC;iBACD,UAAU,CAAC,CAAC,MAAc,EAAE,SAAiB,EAAE,SAAiB,EAAQ,EAAE;gBACzE,SAAS,CAAC,OAAO,EAAE,CAAC;gBACpB,UAAU,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;YAC7C,CAAC,CAAC;iBACD,QAAQ,CAAC,CAAC,MAAc,EAAE,YAAY,EAAQ,EAAE;gBAC9C,YAA6B,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBAChD,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YACnC,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QAEH,WAAW,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,WAAW,EAAQ,EAAE;YAC3C,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC;YAEvB,GAAG;iBACA,KAAK,CAAC,CAAC,MAAc,EAAE,EAAE;gBACxB,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;YACnD,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,MAAc,EAAE,EAAE;gBACxB,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;YACnD,CAAC,CAAC;iBACD,QAAQ,CAAC,CAAC,MAAc,EAAE,EAAE;gBAC3B,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAElC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;oBACxD,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;gBAClD,CAAC;YACH,CAAC,CAAC,CAAC;YAEL,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;gBAChC,IAAI,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;oBACvB,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;gBACnD,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC3B,CAAC;IAEO,cAAc,CACpB,MAAc,EACd,MAAW,EACX,WAAwB,EACxB,UAAU,IAAI,GAAG,EAAU;QAE3B,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACxB,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAEpB,IAAI,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACvB,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;QACxF,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpC,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;YACxD,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAEO,QAAQ,CACd,MAAc,EACd,MAAW,EACX,WAAwB,EACxB,OAAoB;QAEpB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/C,OAAO,CAAC,CAAC;QACX,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAEpB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACnD,IAAI,WAAW,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACtD,OAAO,WAAW,GAAG,CAAC,CAAC;QACzB,CAAC;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IACjE,CAAC;CACF"}
|
package/dist/package.json
CHANGED
package/docs/README.md
CHANGED
|
@@ -14,13 +14,13 @@ Read in this order the first time through:
|
|
|
14
14
|
3. [Execution model](./execution-model.md) — phases, the pipeline, deferred mutation, reactive
|
|
15
15
|
routing. Read this before designing anything non-trivial.
|
|
16
16
|
4. Subsystem guides, in any order:
|
|
17
|
-
- [Components](./components.md) — registration, hooks, exclusivity, cleanup policies,
|
|
17
|
+
- [Components](./components.md) — registration, hooks, traits, exclusivity, cleanup policies,
|
|
18
18
|
interfaces, singletons.
|
|
19
|
-
- [Entities](./entities.md) — creation, lookup, the component API, lifecycle.
|
|
19
|
+
- [Entities](./entities.md) — creation, lookup, the component API, relationship targets, lifecycle.
|
|
20
20
|
- [Systems](./systems.md) — membership, reactive callbacks, callback options, `each`/`run`, cadence, injection.
|
|
21
21
|
- [Queries and filters](./queries-and-filters.md) — the query DSL, live queries, one-shot
|
|
22
22
|
filters, grouped queries, `Bitset`.
|
|
23
|
-
- [Relationships](./relationships.md) —
|
|
23
|
+
- [Relationships](./relationships.md) — links, target creation and ownership, hierarchy, cleanup cascades.
|
|
24
24
|
- [Modules](./modules.md) — packaging features, composition, the built-in modules.
|
|
25
25
|
5. [Design guide](./design-guide.md) — opinionated patterns and anti-patterns distilled from real
|
|
26
26
|
designs. Read it once you know the machinery.
|
|
@@ -36,11 +36,11 @@ Keep the [Glossary](./glossary.md) at hand for terminology.
|
|
|
36
36
|
| [getting-started.md](./getting-started.md) | A runnable tutorial from `npm install` to a ticking world. |
|
|
37
37
|
| [concepts.md](./concepts.md) | The core vocabulary and how the pieces relate. |
|
|
38
38
|
| [execution-model.md](./execution-model.md) | `world.progress`, the 8 built-in phases, deferred commands, flush boundaries, event routing. |
|
|
39
|
-
| [components.md](./components.md) |
|
|
40
|
-
| [entities.md](./entities.md) |
|
|
39
|
+
| [components.md](./components.md) | Component registration, hooks, traits, exclusivity, cleanup, aliases, and singletons. |
|
|
40
|
+
| [entities.md](./entities.md) | Entity creation, component mutation, relationship targets, lifecycle, deferred reads. |
|
|
41
41
|
| [systems.md](./systems.md) | `world.system`, `with`/`without`, `enter`/`update`/`exit`, callback options, tick sources. |
|
|
42
42
|
| [queries-and-filters.md](./queries-and-filters.md) | `QueryDSL`, `Query`, `Filter`, `groupBy`, `ignoreSource`. |
|
|
43
|
-
| [relationships.md](./relationships.md) |
|
|
43
|
+
| [relationships.md](./relationships.md) | Relationships, target creation and ownership, hierarchy, traversal, and cleanup cascades. |
|
|
44
44
|
| [modules.md](./modules.md) | `Module<Config>`, `world.module`, composition, built-in modules. |
|
|
45
45
|
| [design-guide.md](./design-guide.md) | Patterns, anti-patterns, and a Phaser render-layer case study. |
|
|
46
46
|
| [utilities.md](./utilities.md) | Public helper classes: `Events`, `ArrayMap`, `IterableArrayMap`, plus `Bitset` cross-ref. |
|
package/docs/components.md
CHANGED
|
@@ -71,7 +71,7 @@ Pass `idPools` to the `World` constructor to change ranges (each entry is an `Id
|
|
|
71
71
|
released this frame is not immediately recycled. `world.peekNextEid(poolName)` returns the next id
|
|
72
72
|
a pool would allocate without reserving it. Id 0 is reserved.
|
|
73
73
|
|
|
74
|
-
## Hooks: `onAdd`, `onSet`, `onRemove`
|
|
74
|
+
## Hooks: `onAdd`, `onSet`, `onRemove`, `onRetarget`
|
|
75
75
|
|
|
76
76
|
The `Component` entity exposes lifecycle hooks fired for every entity carrying the component:
|
|
77
77
|
|
|
@@ -83,11 +83,15 @@ world
|
|
|
83
83
|
.onRemove((entity, sprite) => sprite.destroy(scene, entity));
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
| Hook | Fires when…
|
|
87
|
-
| ---------- |
|
|
88
|
-
| `onAdd` | The component is first attached (`add`, or `set` on an entity that lacked it).
|
|
89
|
-
| `onSet` | `entity.set(C, props)` applies data, `entity.attach(instance)` stores an instance, `entity.modified(C)` is called, or `getMut` marks it dirty. |
|
|
90
|
-
| `onRemove` | The component is detached (`entity.remove(C)`), or the owning entity is destroyed.
|
|
86
|
+
| Hook | Fires when… |
|
|
87
|
+
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
88
|
+
| `onAdd` | The component is first attached (`add`, or `set` on an entity that lacked it). |
|
|
89
|
+
| `onSet` | `entity.set(C, props)` applies data, `entity.attach(instance)` stores an instance, `entity.modified(C)` is called, or `getMut` / `ensure` marks it dirty. |
|
|
90
|
+
| `onRemove` | The component is detached (`entity.remove(C)`), or the owning entity is destroyed. |
|
|
91
|
+
|
|
92
|
+
Relationship component entities additionally expose `onRetarget`. It fires after an existing
|
|
93
|
+
relationship changes to a different target, once `target` and `children` already reflect the new
|
|
94
|
+
reverse-index state. Initial assignment, same-target `set`, and removal do not fire it.
|
|
91
95
|
|
|
92
96
|
Handlers receive `(entity, componentInstance)` — component instances do not carry entity
|
|
93
97
|
references, so the entity is passed explicitly. Hooks fire synchronously when the corresponding
|
|
@@ -95,6 +99,65 @@ command is applied (see [Execution model](./execution-model.md#reactive-routing)
|
|
|
95
99
|
resource management and cross-cutting reactions that aren't worth a system; use systems when the
|
|
96
100
|
reaction belongs to a phase.
|
|
97
101
|
|
|
102
|
+
Each lifecycle event has one handler slot per component. Calling `onAdd(handler)`,
|
|
103
|
+
`onSet(handler)`, `onRemove(handler)`, or `onRetarget(handler)` replaces the current handler and
|
|
104
|
+
returns the component entity for chaining. Call the method without an argument to read the current
|
|
105
|
+
handler, or pass `undefined` to remove it.
|
|
106
|
+
|
|
107
|
+
## Component traits: policy on component entities
|
|
108
|
+
|
|
109
|
+
Registered components are themselves entities. Attach a configuration component to a component
|
|
110
|
+
entity to change policy for every use of that component type. vecs calls these configuration
|
|
111
|
+
components **component traits**:
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
world.component(Gravity).add(Singleton);
|
|
115
|
+
world.component(Inventory).add(OwnedTarget);
|
|
116
|
+
world.component(ChildOf).add(Traversable);
|
|
117
|
+
world.component(Orange).set(Implements, { interfaces: [Fruit] });
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
| Trait/declaration | Applies to | Effect |
|
|
121
|
+
| ----------------- | ---------------------------------- | -------------------------------------------------------------------- |
|
|
122
|
+
| `Singleton` | Concrete components | Allows at most one carrier entity |
|
|
123
|
+
| `Implements` | Non-relationship components | Exposes concrete data through abstract aliases |
|
|
124
|
+
| `Traversable` | Relationships | Maintains hierarchy depth for cascade ordering |
|
|
125
|
+
| `OwnedTarget` | Relationships other than `ChildOf` | Owns the active target through `ChildOf` and destructive replacement |
|
|
126
|
+
|
|
127
|
+
Traits declare policy; their built-in modules install the hooks and maintain the metadata that
|
|
128
|
+
enforce it. Configure traits in feature-module setup rather than opportunistically inside systems.
|
|
129
|
+
Do not assume all traits have the same lifecycle:
|
|
130
|
+
|
|
131
|
+
- Add `Singleton` before component instances exist.
|
|
132
|
+
- Configure owner hooks, then add `OwnedTarget`, before relationship instances exist; it wraps the
|
|
133
|
+
current hooks and does not backfill.
|
|
134
|
+
- `Traversable` backfills existing relationship instances.
|
|
135
|
+
- Setting or removing `Implements` recomputes interface aliases.
|
|
136
|
+
|
|
137
|
+
Treat traits as setup policy unless their documentation explicitly supports runtime changes. Before
|
|
138
|
+
writing custom component-type bookkeeping, check whether an existing trait already expresses the
|
|
139
|
+
invariant.
|
|
140
|
+
|
|
141
|
+
Custom traits use the same mechanism. Keep the trait class as data and put its behavior in a module:
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
class Audited {}
|
|
145
|
+
|
|
146
|
+
class AuditModule extends Module {
|
|
147
|
+
public init(): void {
|
|
148
|
+
this.world.component(Audited).onAdd((component) => {
|
|
149
|
+
component.onSet((entity) => console.log("changed", component.meta.Class.name, entity.eid));
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
world.module(AuditModule);
|
|
155
|
+
world.component(Position).add(Audited);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Create a custom trait only when several component types need the same reusable, declarative policy.
|
|
159
|
+
For one component type, register hooks directly in its owning module.
|
|
160
|
+
|
|
98
161
|
## Exclusive component groups
|
|
99
162
|
|
|
100
163
|
`world.setExclusiveComponents(A, B, C)` declares a mutually exclusive group: setting one
|
|
@@ -183,7 +246,7 @@ Rules (enforced by `ImplementsModule`, `lib/vecs/src/modules/implements.ts`):
|
|
|
183
246
|
|
|
184
247
|
- **Aliases are read/query only.** `get`, `has`, `with`, `filter`, and injection accept an
|
|
185
248
|
interface type; mutation must go through the concrete component. `add`, `set`, `remove`,
|
|
186
|
-
`modified`, `getMut`, and `attach` on an interface throw at runtime (and `add`/`set` are
|
|
249
|
+
`modified`, `getMut`, `ensure`, and `attach` on an interface throw at runtime (and `add`/`set` are
|
|
187
250
|
rejected by TypeScript for abstract classes).
|
|
188
251
|
- **Declarations are transitive.** `Orange` implements `Fruit`, `Fruit` implements `Food`, so an
|
|
189
252
|
entity with `Orange` matches `with(Food)`. Cyclic declarations throw.
|
|
@@ -249,12 +312,13 @@ interface markers for polymorphic dispatch — is in the
|
|
|
249
312
|
A `Component<T>` is an `Entity` subclass, so the full [entity API](./entities.md#reference)
|
|
250
313
|
applies. On top of it:
|
|
251
314
|
|
|
252
|
-
| Member
|
|
253
|
-
|
|
|
254
|
-
| `onAdd(handler)`
|
|
255
|
-
| `onRemove(handler)`
|
|
256
|
-
| `
|
|
257
|
-
| `
|
|
315
|
+
| Member | Description |
|
|
316
|
+
| ---------------------- | -------------------------------------------------------------------------- |
|
|
317
|
+
| `onAdd(handler?)` | Get, set, or remove the single add hook. Setter returns the component. |
|
|
318
|
+
| `onRemove(handler?)` | Get, set, or remove the single remove hook. |
|
|
319
|
+
| `onRetarget(handler?)` | Get, set, or remove the relationship retarget hook. Rejects non-relations. |
|
|
320
|
+
| `onSet(handler?)` | Get, set, or remove the single set/modified hook. |
|
|
321
|
+
| `meta` | The `ComponentMeta` bookkeeping record. |
|
|
258
322
|
|
|
259
323
|
### `ComponentMeta` (`lib/vecs/src/component_meta.ts`)
|
|
260
324
|
|
package/docs/concepts.md
CHANGED
|
@@ -20,9 +20,10 @@ every idiom in the [Design guide](./design-guide.md) is a consequence of taking
|
|
|
20
20
|
| **System** | A `Query` plus per-tick logic (`update`, `each`, `run`), assigned to one pipeline phase. |
|
|
21
21
|
| **Query** | A reactive, always-up-to-date set of entities matching a predicate, with `enter`/`exit`/`update` callbacks. |
|
|
22
22
|
| **Filter** | A non-reactive, one-shot scan: walks all world entities on each `forEach` call. |
|
|
23
|
-
| **Hook** | Lightweight `onAdd` / `
|
|
23
|
+
| **Hook** | Lightweight component callbacks (`onAdd` / `onSet` / `onRemove`, plus relationship `onRetarget`). |
|
|
24
24
|
| **Phase** | Marker component for entities used as pipeline ordering anchors. |
|
|
25
25
|
| **Relationship** | A component whose `target` field points at another entity, with reverse lookup and cleanup cascades. |
|
|
26
|
+
| **Component trait** | Policy attached to a component entity, configuring every use of that component type. |
|
|
26
27
|
| **Module** | A unit of packaging: a class whose `init()` registers components, systems, phases, and policy. |
|
|
27
28
|
| **Exclusive components** | A group of components where at most one may exist on any entity at a time. |
|
|
28
29
|
| **Implements** | Declares abstract/interface component aliases for a concrete component, for polymorphic queries. |
|
|
@@ -43,6 +44,11 @@ own. All behavior lives in systems (and, for small cross-cutting reactions, in h
|
|
|
43
44
|
is what makes composition work: any system can operate on any entity that happens to carry the
|
|
44
45
|
right components, and adding a capability to an entity is just adding a component.
|
|
45
46
|
|
|
47
|
+
Because a registered component is also an entity, it can itself carry components. Built-in
|
|
48
|
+
**component traits** use that meta-ECS layer to declare reusable policy: `Singleton` constrains a
|
|
49
|
+
component, `Implements` declares aliases, and `Traversable` / `OwnedTarget` configure relationships.
|
|
50
|
+
The trait remains data; a module owns the hooks and metadata behavior it activates.
|
|
51
|
+
|
|
46
52
|
Prefer many small, single-purpose components over one large one. An entity that never rotates
|
|
47
53
|
simply omits `Rotation`; absence encodes "not applicable". See
|
|
48
54
|
[Components](./components.md).
|
|
@@ -77,7 +83,7 @@ on component combinations. The canonical example is the companion-component patt
|
|
|
77
83
|
|
|
78
84
|
## Where each topic lives
|
|
79
85
|
|
|
80
|
-
- Registering, configuring, and
|
|
86
|
+
- Registering, configuring, hooking, and applying traits to components → [Components](./components.md)
|
|
81
87
|
- Creating, mutating, and destroying entities → [Entities](./entities.md)
|
|
82
88
|
- System membership, callbacks, and cadence → [Systems](./systems.md)
|
|
83
89
|
- The query DSL, live queries, filters, grouping → [Queries and filters](./queries-and-filters.md)
|