@vworlds/vecs 1.0.39 → 1.0.41
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/dist/filter.d.ts +3 -3
- package/dist/package.json +1 -1
- package/dist/query/group.d.ts +3 -3
- package/dist/query/query.d.ts +16 -16
- package/dist/system.d.ts +3 -3
- package/docs/README.md +1 -1
- package/docs/design-guide.md +26 -20
- package/docs/glossary.md +1 -2
- package/docs/relationships.md +6 -2
- package/package.json +1 -1
package/dist/filter.d.ts
CHANGED
|
@@ -70,12 +70,12 @@ export declare class Filter<R extends ComponentType[] = []> {
|
|
|
70
70
|
* @param callback - Receives the entity and a tuple of resolved component
|
|
71
71
|
* instances.
|
|
72
72
|
*/
|
|
73
|
-
forEach<J extends FanInjectTuple>(components: readonly [...J], callback: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
73
|
+
forEach<const J extends FanInjectTuple>(components: readonly [...J], callback: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
74
74
|
/**
|
|
75
75
|
* As above, but pass `{ cursor: Entity, inject: [...] }` to make the
|
|
76
76
|
* entity-first signature explicit. Identical behavior to the array form.
|
|
77
77
|
*/
|
|
78
|
-
forEach<J extends FanInjectTuple>(options: EntityCursorOption & FanInjectCallbackOptions<J>, callback: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
78
|
+
forEach<const J extends FanInjectTuple>(options: EntityCursorOption & FanInjectCallbackOptions<J>, callback: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
79
79
|
/**
|
|
80
80
|
* As above, but pass `{ cursor: Iter, inject: [...] }` to receive a reused
|
|
81
81
|
* {@link Iter} cursor instead of the bare entity. The cursor exposes the
|
|
@@ -83,6 +83,6 @@ export declare class Filter<R extends ComponentType[] = []> {
|
|
|
83
83
|
* resolved component was read from (the visited entity for direct components,
|
|
84
84
|
* the relationship's target entity for ones injected via `target`).
|
|
85
85
|
*/
|
|
86
|
-
forEach<J extends FanInjectTuple>(options: IterCursorOption & FanInjectCallbackOptions<J>, callback: (it: Iter, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
86
|
+
forEach<const J extends FanInjectTuple>(options: IterCursorOption & FanInjectCallbackOptions<J>, callback: (it: Iter, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
87
87
|
private _forEachMatch;
|
|
88
88
|
}
|
package/dist/package.json
CHANGED
package/dist/query/group.d.ts
CHANGED
|
@@ -11,8 +11,8 @@ export declare class Group<K = unknown, R extends ComponentType[] = []> {
|
|
|
11
11
|
get count(): number;
|
|
12
12
|
[Symbol.iterator](): IterableIterator<Entity>;
|
|
13
13
|
forEach(callback: (e: Entity) => void): this;
|
|
14
|
-
forEach<J extends FanInjectTuple>(components: readonly [...J], callback: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
15
|
-
forEach<J extends FanInjectTuple>(options: EntityCursorOption & FanInjectCallbackOptions<J>, callback: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
16
|
-
forEach<J extends FanInjectTuple>(options: IterCursorOption & FanInjectCallbackOptions<J>, callback: (it: Iter, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
14
|
+
forEach<const J extends FanInjectTuple>(components: readonly [...J], callback: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
15
|
+
forEach<const J extends FanInjectTuple>(options: EntityCursorOption & FanInjectCallbackOptions<J>, callback: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
16
|
+
forEach<const J extends FanInjectTuple>(options: IterCursorOption & FanInjectCallbackOptions<J>, callback: (it: Iter, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
17
17
|
has(e: Entity): boolean;
|
|
18
18
|
}
|
package/dist/query/query.d.ts
CHANGED
|
@@ -48,22 +48,22 @@ export declare class Query<R extends ComponentType[] = []> implements TermConsum
|
|
|
48
48
|
belongs(e: Entity): boolean;
|
|
49
49
|
has(e: Entity): boolean;
|
|
50
50
|
forEach(callback: (e: Entity) => void): this;
|
|
51
|
-
forEach<J extends FanInjectTuple>(components: readonly [...J], callback: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
52
|
-
forEach<J extends FanInjectTuple>(options: EntityCursorOption & FanInjectCallbackOptions<J>, callback: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
53
|
-
forEach<J extends FanInjectTuple>(options: IterCursorOption & FanInjectCallbackOptions<J>, callback: (it: Iter, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
51
|
+
forEach<const J extends FanInjectTuple>(components: readonly [...J], callback: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
52
|
+
forEach<const J extends FanInjectTuple>(options: EntityCursorOption & FanInjectCallbackOptions<J>, callback: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
53
|
+
forEach<const J extends FanInjectTuple>(options: IterCursorOption & FanInjectCallbackOptions<J>, callback: (it: Iter, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
54
54
|
toString(): string;
|
|
55
55
|
with<const S extends readonly QuerySpec[]>(...specs: [...S]): Query<[...R, ...ExtractSpecsRequired<S>]>;
|
|
56
56
|
without(dsl: QueryDSL): this;
|
|
57
57
|
track(): this;
|
|
58
|
-
orderBy<J extends InjectTuple>(components: readonly [...J], compare: (entityA: Entity, a: MaybeResolvedInjectTuple<J, R>, entityB: Entity, b: MaybeResolvedInjectTuple<J, R>) => number): this;
|
|
59
|
-
orderBy<J extends InjectTuple>(options: EntityCursorOption & OrderByOptions<J>, compare: (entityA: Entity, a: MaybeResolvedInjectTuple<J, R>, entityB: Entity, b: MaybeResolvedInjectTuple<J, R>) => number): this;
|
|
60
|
-
orderBy<J extends InjectTuple>(options: IterCursorOption & OrderByOptions<J>, compare: (a: Iter, aResolved: MaybeResolvedInjectTuple<J, R>, b: Iter, bResolved: MaybeResolvedInjectTuple<J, R>) => number): this;
|
|
58
|
+
orderBy<const J extends InjectTuple>(components: readonly [...J], compare: (entityA: Entity, a: MaybeResolvedInjectTuple<J, R>, entityB: Entity, b: MaybeResolvedInjectTuple<J, R>) => number): this;
|
|
59
|
+
orderBy<const J extends InjectTuple>(options: EntityCursorOption & OrderByOptions<J>, compare: (entityA: Entity, a: MaybeResolvedInjectTuple<J, R>, entityB: Entity, b: MaybeResolvedInjectTuple<J, R>) => number): this;
|
|
60
|
+
orderBy<const J extends InjectTuple>(options: IterCursorOption & OrderByOptions<J>, compare: (a: Iter, aResolved: MaybeResolvedInjectTuple<J, R>, b: Iter, bResolved: MaybeResolvedInjectTuple<J, R>) => number): this;
|
|
61
61
|
cascade(rel: ComponentRef): this;
|
|
62
62
|
cascade(options: CascadeOptions): this;
|
|
63
63
|
cascade(rel: ComponentRef, compare: (a: Entity, b: Entity) => number): this;
|
|
64
64
|
cascade(options: CascadeOptions, compare: (a: Entity, b: Entity) => number): this;
|
|
65
|
-
groupBy<K, J extends FanInjectTuple>(components: readonly [...J], key: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => K): GroupedQuery<K, R>;
|
|
66
|
-
groupBy<K, J extends FanInjectTuple>(options: GroupByOptions<J>, key: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => K): GroupedQuery<K, R>;
|
|
65
|
+
groupBy<K, const J extends FanInjectTuple>(components: readonly [...J], key: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => K): GroupedQuery<K, R>;
|
|
66
|
+
groupBy<K, const J extends FanInjectTuple>(options: GroupByOptions<J>, key: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => K): GroupedQuery<K, R>;
|
|
67
67
|
groupBy(relationship: ComponentRef): GroupedQuery<Entity, R>;
|
|
68
68
|
groupBy(options: {
|
|
69
69
|
relationship: ComponentRef;
|
|
@@ -78,13 +78,13 @@ export declare class Query<R extends ComponentType[] = []> implements TermConsum
|
|
|
78
78
|
set<C extends ComponentClass>(Class: C, props: Partial<InstanceType<C>>): this;
|
|
79
79
|
set(ceid: EID, props: Partial<ComponentInstance>): this;
|
|
80
80
|
set(entity: Entity, props: Partial<ComponentInstance>): this;
|
|
81
|
-
enter<J extends InjectTuple>(inject: readonly [...J], callback: (e: Entity, injected: RequiredResolvedInjectTuple<J>) => void): this;
|
|
82
|
-
enter<J extends InjectTuple>(options: EntityCursorOption & InjectCallbackOptions<J>, callback: (e: Entity, injected: RequiredResolvedInjectTuple<J>) => void): this;
|
|
83
|
-
enter<J extends InjectTuple>(options: IterCursorOption & InjectCallbackOptions<J>, callback: (it: Iter, injected: RequiredResolvedInjectTuple<J>) => void): this;
|
|
81
|
+
enter<const J extends InjectTuple>(inject: readonly [...J], callback: (e: Entity, injected: RequiredResolvedInjectTuple<J>) => void): this;
|
|
82
|
+
enter<const J extends InjectTuple>(options: EntityCursorOption & InjectCallbackOptions<J>, callback: (e: Entity, injected: RequiredResolvedInjectTuple<J>) => void): this;
|
|
83
|
+
enter<const J extends InjectTuple>(options: IterCursorOption & InjectCallbackOptions<J>, callback: (it: Iter, injected: RequiredResolvedInjectTuple<J>) => void): this;
|
|
84
84
|
enter(callback: (e: Entity) => void): this;
|
|
85
|
-
exit<J extends InjectTuple>(inject: readonly [...J], callback: (e: Entity, injected: RequiredResolvedInjectTuple<J>) => void): this;
|
|
86
|
-
exit<J extends InjectTuple>(options: EntityCursorOption & InjectCallbackOptions<J>, callback: (e: Entity, injected: RequiredResolvedInjectTuple<J>) => void): this;
|
|
87
|
-
exit<J extends InjectTuple>(options: IterCursorOption & InjectCallbackOptions<J>, callback: (it: Iter, injected: RequiredResolvedInjectTuple<J>) => void): this;
|
|
85
|
+
exit<const J extends InjectTuple>(inject: readonly [...J], callback: (e: Entity, injected: RequiredResolvedInjectTuple<J>) => void): this;
|
|
86
|
+
exit<const J extends InjectTuple>(options: EntityCursorOption & InjectCallbackOptions<J>, callback: (e: Entity, injected: RequiredResolvedInjectTuple<J>) => void): this;
|
|
87
|
+
exit<const J extends InjectTuple>(options: IterCursorOption & InjectCallbackOptions<J>, callback: (it: Iter, injected: RequiredResolvedInjectTuple<J>) => void): this;
|
|
88
88
|
exit(callback: (e: Entity) => void): this;
|
|
89
89
|
/**
|
|
90
90
|
* Register one update callback for a watched component.
|
|
@@ -105,10 +105,10 @@ export declare class Query<R extends ComponentType[] = []> implements TermConsum
|
|
|
105
105
|
* already has an update callback on this query.
|
|
106
106
|
*/
|
|
107
107
|
update<C extends ComponentType>(ComponentClass: C, callback: (e: Entity, c: InstanceType<C>) => void): this;
|
|
108
|
-
update<C extends ComponentType, J extends InjectTuple>(options: EntityCursorOption & UpdateCallbackOptions<C, J> & {
|
|
108
|
+
update<C extends ComponentType, const J extends InjectTuple>(options: EntityCursorOption & UpdateCallbackOptions<C, J> & {
|
|
109
109
|
inject: readonly [...J];
|
|
110
110
|
}, callback: (e: Entity, c: InstanceType<C>, injected: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
111
|
-
update<C extends ComponentType, J extends InjectTuple>(options: IterCursorOption & UpdateCallbackOptions<C, J> & {
|
|
111
|
+
update<C extends ComponentType, const J extends InjectTuple>(options: IterCursorOption & UpdateCallbackOptions<C, J> & {
|
|
112
112
|
inject: readonly [...J];
|
|
113
113
|
}, callback: (it: Iter, c: InstanceType<C>, injected: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
114
114
|
update<C extends ComponentType>(options: EntityCursorOption & UpdateCallbackOptions<C, []>, callback: (e: Entity, c: InstanceType<C>) => void): this;
|
package/dist/system.d.ts
CHANGED
|
@@ -165,12 +165,12 @@ export declare class System<R extends ComponentType[] = []> extends Query<R> imp
|
|
|
165
165
|
* });
|
|
166
166
|
* ```
|
|
167
167
|
*/
|
|
168
|
-
each<J extends FanInjectTuple>(components: readonly [...J], callback: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
168
|
+
each<const J extends FanInjectTuple>(components: readonly [...J], callback: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
169
169
|
/**
|
|
170
170
|
* As above, but pass `{ cursor: Entity, inject: [...] }` to make the
|
|
171
171
|
* entity-first signature explicit. Identical behavior to the array form.
|
|
172
172
|
*/
|
|
173
|
-
each<J extends FanInjectTuple>(options: EntityCursorOption & FanInjectCallbackOptions<J>, callback: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
173
|
+
each<const J extends FanInjectTuple>(options: EntityCursorOption & FanInjectCallbackOptions<J>, callback: (e: Entity, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
174
174
|
/**
|
|
175
175
|
* As above, but pass `{ cursor: Iter, inject: [...] }` to receive a reused
|
|
176
176
|
* {@link Iter} cursor instead of the bare entity. The cursor exposes the
|
|
@@ -178,7 +178,7 @@ export declare class System<R extends ComponentType[] = []> extends Query<R> imp
|
|
|
178
178
|
* resolved component was read from (the visited entity for direct components,
|
|
179
179
|
* the relationship target for `target`-injected ones).
|
|
180
180
|
*/
|
|
181
|
-
each<J extends FanInjectTuple>(options: IterCursorOption & FanInjectCallbackOptions<J>, callback: (it: Iter, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
181
|
+
each<const J extends FanInjectTuple>(options: IterCursorOption & FanInjectCallbackOptions<J>, callback: (it: Iter, resolved: MaybeResolvedInjectTuple<J, R>) => void): this;
|
|
182
182
|
/**
|
|
183
183
|
* Add entity-membership predicates using {@link QuerySpec} expressions.
|
|
184
184
|
*
|
package/docs/README.md
CHANGED
|
@@ -46,5 +46,5 @@ Keep the [Glossary](./glossary.md) at hand for terminology.
|
|
|
46
46
|
| [utilities.md](./utilities.md) | Public helper classes: `Events`, `ArrayMap`, `IterableArrayMap`, plus `Bitset` cross-ref. |
|
|
47
47
|
| [glossary.md](./glossary.md) | ECS and vecs terminology. |
|
|
48
48
|
|
|
49
|
-
Networking (wire encoding with `@
|
|
49
|
+
Networking (wire encoding with `@wireType`, protocol component ordering, replication) lives in the
|
|
50
50
|
`@vworlds/vecs-wire` and `@vworlds/vecs-protocol` packages and is only cross-referenced here.
|
package/docs/design-guide.md
CHANGED
|
@@ -102,9 +102,8 @@ export class Rotation {
|
|
|
102
102
|
|
|
103
103
|
### Networked components
|
|
104
104
|
|
|
105
|
-
Mark wire fields with `@
|
|
106
|
-
`
|
|
107
|
-
**order** you pass components in `networkComponents` _is the wire protocol_ (type id = index + 1).
|
|
105
|
+
Mark wire fields with `@wireType` from `@vworlds/vecs-wire` (`import { wireType }`). The
|
|
106
|
+
**order** you pass components in `networkComponents` _is the wire protocol_ (wire type id = index + 1).
|
|
108
107
|
Reordering is a breaking protocol change — snapshot-test the order.
|
|
109
108
|
|
|
110
109
|
```ts
|
|
@@ -114,7 +113,7 @@ class Arc {
|
|
|
114
113
|
new ServerWorld({ networkComponents: [Position, Rotation, /* … */ Arc] });
|
|
115
114
|
```
|
|
116
115
|
|
|
117
|
-
> **Decorator gotcha.** `@
|
|
116
|
+
> **Decorator gotcha.** `@wireType` must work under both _legacy_ (`experimentalDecorators`, used by
|
|
118
117
|
> `tsc`) and _standard_ TC39 decorators (what esbuild — `tsx`/Vite — emits for source files).
|
|
119
118
|
> If you load decorated component classes from **source** through an esbuild-based runtime and
|
|
120
119
|
> their fields silently fail to register, that's the standard-vs-legacy mismatch. vecs-wire
|
|
@@ -179,8 +178,12 @@ entity.target(InCell); // the target entity
|
|
|
179
178
|
world.query("ByCell").with(Networked, Position).groupBy(InCell); // index by target
|
|
180
179
|
```
|
|
181
180
|
|
|
182
|
-
- **`Relationship.target` is an `Entity` — not
|
|
183
|
-
|
|
181
|
+
- **`Relationship.target` is an `Entity` — not directly serialisable, but
|
|
182
|
+
relationships can be networked** when listed in `networkComponents`.
|
|
183
|
+
`vecs-protocol` registers `Relationship.prototype.target` as an `"entity"`
|
|
184
|
+
wire field (u32 eid), so subclasses like `ChildOf` serialise their target
|
|
185
|
+
as a raw entity id. The client resolves the id to a live entity (creating a
|
|
186
|
+
ghost placeholder if the parent hasn't arrived yet).
|
|
184
187
|
- **Retargeting is a plain data change** (no archetype churn). Prefer retargeting a relationship
|
|
185
188
|
over swapping marker components to express "which bucket this entity is in."
|
|
186
189
|
|
|
@@ -547,18 +550,18 @@ system after whatever produces the entity/companion.
|
|
|
547
550
|
|
|
548
551
|
## 8. Anti-patterns (keep ECS semantics)
|
|
549
552
|
|
|
550
|
-
| Smell | Do instead
|
|
551
|
-
| ---------------------------------------------------------------------- |
|
|
552
|
-
| A side `Map<eid, resource>` | Store the resource in a **companion component**; let queries drive its lifecycle; release in `onRemove`.
|
|
553
|
-
| An imperative runtime object with `start()/stop()/track/enable` | A **module** + the world's own lifecycle (`clearAllEntities()`, closing the world). Systems live on the world; they don't need a wrapper to turn on.
|
|
554
|
-
| Builder/factory helpers that _create entities_ (`createArc(world, …)`) | Let callers `world.entity().add(Networked).set(Arc, …).set(FillStyle, …)`. Components are small and optional; the caller adds exactly what it wants.
|
|
555
|
-
| A god component with many optional fields | Split into small single-purpose components; absence encodes "not applicable."
|
|
556
|
-
| Duplicated `enter` + `update` doing the same thing | One `update({ watch: C, onEnter: true })` when update owns initialization.
|
|
557
|
-
| One system trying to act in two phases | Split into two systems, one per phase.
|
|
558
|
-
| Custom phases for app/render logic | Use the standard taxonomy; only engine modules insert phases.
|
|
559
|
-
| `.each` scanning every entity to detect change | Reactive `.update(C)` — fires only on change.
|
|
560
|
-
| Networking a relationship |
|
|
561
|
-
| A `registerFooSystem(world)` wrapper per system | Declare the system inline in the module's `init`.
|
|
553
|
+
| Smell | Do instead |
|
|
554
|
+
| ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
555
|
+
| A side `Map<eid, resource>` | Store the resource in a **companion component**; let queries drive its lifecycle; release in `onRemove`. |
|
|
556
|
+
| An imperative runtime object with `start()/stop()/track/enable` | A **module** + the world's own lifecycle (`clearAllEntities()`, closing the world). Systems live on the world; they don't need a wrapper to turn on. |
|
|
557
|
+
| Builder/factory helpers that _create entities_ (`createArc(world, …)`) | Let callers `world.entity().add(Networked).set(Arc, …).set(FillStyle, …)`. Components are small and optional; the caller adds exactly what it wants. |
|
|
558
|
+
| A god component with many optional fields | Split into small single-purpose components; absence encodes "not applicable." |
|
|
559
|
+
| Duplicated `enter` + `update` doing the same thing | One `update({ watch: C, onEnter: true })` when update owns initialization. |
|
|
560
|
+
| One system trying to act in two phases | Split into two systems, one per phase. |
|
|
561
|
+
| Custom phases for app/render logic | Use the standard taxonomy; only engine modules insert phases. |
|
|
562
|
+
| `.each` scanning every entity to detect change | Reactive `.update(C)` — fires only on change. |
|
|
563
|
+
| Networking a relationship | Relationships can be networked when listed in `networkComponents`: `Relationship.target` serialises as a u32 entity id. List `ChildOf` (or custom subclasses) explicitly to replicate parent-child links. |
|
|
564
|
+
| A `registerFooSystem(world)` wrapper per system | Declare the system inline in the module's `init`. |
|
|
562
565
|
|
|
563
566
|
---
|
|
564
567
|
|
|
@@ -576,9 +579,12 @@ system after whatever produces the entity/companion.
|
|
|
576
579
|
- **Within a phase, order = registration order;** across phases, the spine guarantees order. Don't
|
|
577
580
|
use registration order for cross-module correctness — use phases.
|
|
578
581
|
- **Networked component order = wire protocol.** Reordering breaks the protocol.
|
|
579
|
-
- **`@
|
|
582
|
+
- **`@wireType` must survive esbuild's standard decorators** when components load from
|
|
580
583
|
source (tsx/Vite). Otherwise fields silently don't register.
|
|
581
|
-
- **`Relationship.target` is an `Entity`** — not wire-encodable
|
|
584
|
+
- **`Relationship.target` is an `Entity`** — not directly wire-encodable, but
|
|
585
|
+
`vecs-protocol` registers it as an `"entity"` wire field (u32 eid) at module
|
|
586
|
+
load, so `Relationship` subclasses listed in `networkComponents` serialise
|
|
587
|
+
correctly.
|
|
582
588
|
- **`world.module(M)` runs `init` once.** Re-registering with a different config throws.
|
|
583
589
|
|
|
584
590
|
---
|
package/docs/glossary.md
CHANGED
|
@@ -105,8 +105,7 @@ how often a system fires. [Systems](./systems.md#cadence-interval-rate-and-tick-
|
|
|
105
105
|
**Watchlist** — the set of component types a query or system reacts to via `update`, stored as a
|
|
106
106
|
bitmask. [Systems](./systems.md#reactive-callbacks-enter-update-exit).
|
|
107
107
|
|
|
108
|
-
**Wire type** — a field-level encoding declaration (`@
|
|
109
|
-
imported as `wireType`) used by the networking packages to serialize components. Networking is
|
|
108
|
+
**Wire type** — a field-level encoding declaration (`@wireType` from `@vworlds/vecs-wire`) used by the networking packages to serialize components. Networking is
|
|
110
109
|
documented with `@vworlds/vecs-wire` / `@vworlds/vecs-protocol`, not here.
|
|
111
110
|
|
|
112
111
|
**World** — the central container owning entities, component registrations, queries, systems, and
|
package/docs/relationships.md
CHANGED
|
@@ -26,8 +26,12 @@ with `children(ref)` through a reverse index the world maintains automatically.
|
|
|
26
26
|
most one instance of a given relationship class (like any component), so multi-target links are
|
|
27
27
|
modeled with one relationship class per meaning, or child entities.
|
|
28
28
|
|
|
29
|
-
Because `target` is an `Entity` reference,
|
|
30
|
-
|
|
29
|
+
Because `target` is an `Entity` reference, relationships are not wire-serializable by default.
|
|
30
|
+
However, `vecs-protocol` registers `Relationship.prototype.target` as an `"entity"` wire field
|
|
31
|
+
(u32 eid) at module load, so **relationship subclasses listed in `networkComponents` are
|
|
32
|
+
networkable**: the target serialises as a raw entity id, and the client resolves it to a live
|
|
33
|
+
entity (creating a ghost placeholder if the parent hasn't arrived yet). List `ChildOf` (or custom
|
|
34
|
+
subclasses) explicitly in your `networkComponents` array to replicate parent-child links.
|
|
31
35
|
|
|
32
36
|
## Built-in relationships
|
|
33
37
|
|