@ecsia/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +29 -0
- package/dist/bitmask/bitmask.d.ts +21 -0
- package/dist/bitmask/bitmask.d.ts.map +1 -0
- package/dist/bitmask/bitmask.js +103 -0
- package/dist/bitmask/bitmask.js.map +1 -0
- package/dist/bitmask/index.d.ts +3 -0
- package/dist/bitmask/index.d.ts.map +1 -0
- package/dist/bitmask/index.js +2 -0
- package/dist/bitmask/index.js.map +1 -0
- package/dist/component/accessor.d.ts +40 -0
- package/dist/component/accessor.d.ts.map +1 -0
- package/dist/component/accessor.js +220 -0
- package/dist/component/accessor.js.map +1 -0
- package/dist/component/column-set.d.ts +20 -0
- package/dist/component/column-set.d.ts.map +1 -0
- package/dist/component/column-set.js +60 -0
- package/dist/component/column-set.js.map +1 -0
- package/dist/component/define.d.ts +23 -0
- package/dist/component/define.d.ts.map +1 -0
- package/dist/component/define.js +155 -0
- package/dist/component/define.js.map +1 -0
- package/dist/component/descriptors.d.ts +3 -0
- package/dist/component/descriptors.d.ts.map +1 -0
- package/dist/component/descriptors.js +147 -0
- package/dist/component/descriptors.js.map +1 -0
- package/dist/component/index.d.ts +10 -0
- package/dist/component/index.d.ts.map +1 -0
- package/dist/component/index.js +6 -0
- package/dist/component/index.js.map +1 -0
- package/dist/component/sidecar.d.ts +58 -0
- package/dist/component/sidecar.d.ts.map +1 -0
- package/dist/component/sidecar.js +136 -0
- package/dist/component/sidecar.js.map +1 -0
- package/dist/config.d.ts +55 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +70 -0
- package/dist/config.js.map +1 -0
- package/dist/entity/codec.d.ts +45 -0
- package/dist/entity/codec.d.ts.map +1 -0
- package/dist/entity/codec.js +53 -0
- package/dist/entity/codec.js.map +1 -0
- package/dist/entity/index-allocator.d.ts +46 -0
- package/dist/entity/index-allocator.d.ts.map +1 -0
- package/dist/entity/index-allocator.js +121 -0
- package/dist/entity/index-allocator.js.map +1 -0
- package/dist/entity/index.d.ts +13 -0
- package/dist/entity/index.d.ts.map +1 -0
- package/dist/entity/index.js +7 -0
- package/dist/entity/index.js.map +1 -0
- package/dist/entity/record.d.ts +28 -0
- package/dist/entity/record.d.ts.map +1 -0
- package/dist/entity/record.js +42 -0
- package/dist/entity/record.js.map +1 -0
- package/dist/entity/ref.d.ts +70 -0
- package/dist/entity/ref.d.ts.map +1 -0
- package/dist/entity/ref.js +104 -0
- package/dist/entity/ref.js.map +1 -0
- package/dist/entity/reservation.d.ts +12 -0
- package/dist/entity/reservation.d.ts.map +1 -0
- package/dist/entity/reservation.js +28 -0
- package/dist/entity/reservation.js.map +1 -0
- package/dist/entity/store.d.ts +60 -0
- package/dist/entity/store.d.ts.map +1 -0
- package/dist/entity/store.js +193 -0
- package/dist/entity/store.js.map +1 -0
- package/dist/env.d.ts +2 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +12 -0
- package/dist/env.js.map +1 -0
- package/dist/ids.d.ts +9 -0
- package/dist/ids.d.ts.map +1 -0
- package/dist/ids.js +8 -0
- package/dist/ids.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/inspect-surface.d.ts +27 -0
- package/dist/inspect-surface.d.ts.map +1 -0
- package/dist/inspect-surface.js +14 -0
- package/dist/inspect-surface.js.map +1 -0
- package/dist/internal.d.ts +19 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +19 -0
- package/dist/internal.js.map +1 -0
- package/dist/memory/allocU32.d.ts +25 -0
- package/dist/memory/allocU32.d.ts.map +1 -0
- package/dist/memory/allocU32.js +95 -0
- package/dist/memory/allocU32.js.map +1 -0
- package/dist/memory/buffers.d.ts +94 -0
- package/dist/memory/buffers.d.ts.map +1 -0
- package/dist/memory/buffers.js +308 -0
- package/dist/memory/buffers.js.map +1 -0
- package/dist/memory/index.d.ts +7 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +4 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/layout.d.ts +37 -0
- package/dist/memory/layout.d.ts.map +1 -0
- package/dist/memory/layout.js +116 -0
- package/dist/memory/layout.js.map +1 -0
- package/dist/query/compile.d.ts +73 -0
- package/dist/query/compile.d.ts.map +1 -0
- package/dist/query/compile.js +158 -0
- package/dist/query/compile.js.map +1 -0
- package/dist/query/engine.d.ts +48 -0
- package/dist/query/engine.d.ts.map +1 -0
- package/dist/query/engine.js +230 -0
- package/dist/query/engine.js.map +1 -0
- package/dist/query/index.d.ts +8 -0
- package/dist/query/index.d.ts.map +1 -0
- package/dist/query/index.js +10 -0
- package/dist/query/index.js.map +1 -0
- package/dist/query/live-query.d.ts +122 -0
- package/dist/query/live-query.d.ts.map +1 -0
- package/dist/query/live-query.js +543 -0
- package/dist/query/live-query.js.map +1 -0
- package/dist/query/sparse-set.d.ts +18 -0
- package/dist/query/sparse-set.d.ts.map +1 -0
- package/dist/query/sparse-set.js +126 -0
- package/dist/query/sparse-set.js.map +1 -0
- package/dist/reactivity/change-version.d.ts +19 -0
- package/dist/reactivity/change-version.d.ts.map +1 -0
- package/dist/reactivity/change-version.js +76 -0
- package/dist/reactivity/change-version.js.map +1 -0
- package/dist/reactivity/index.d.ts +12 -0
- package/dist/reactivity/index.d.ts.map +1 -0
- package/dist/reactivity/index.js +12 -0
- package/dist/reactivity/index.js.map +1 -0
- package/dist/reactivity/log.d.ts +83 -0
- package/dist/reactivity/log.d.ts.map +1 -0
- package/dist/reactivity/log.js +260 -0
- package/dist/reactivity/log.js.map +1 -0
- package/dist/reactivity/observer-commands.d.ts +40 -0
- package/dist/reactivity/observer-commands.d.ts.map +1 -0
- package/dist/reactivity/observer-commands.js +111 -0
- package/dist/reactivity/observer-commands.js.map +1 -0
- package/dist/reactivity/observers.d.ts +50 -0
- package/dist/reactivity/observers.d.ts.map +1 -0
- package/dist/reactivity/observers.js +127 -0
- package/dist/reactivity/observers.js.map +1 -0
- package/dist/reactivity/reactivity.d.ts +141 -0
- package/dist/reactivity/reactivity.d.ts.map +1 -0
- package/dist/reactivity/reactivity.js +479 -0
- package/dist/reactivity/reactivity.js.map +1 -0
- package/dist/reactivity/structural-journal.d.ts +30 -0
- package/dist/reactivity/structural-journal.d.ts.map +1 -0
- package/dist/reactivity/structural-journal.js +77 -0
- package/dist/reactivity/structural-journal.js.map +1 -0
- package/dist/registry.d.ts +26 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +58 -0
- package/dist/registry.js.map +1 -0
- package/dist/serialize-surface.d.ts +170 -0
- package/dist/serialize-surface.d.ts.map +1 -0
- package/dist/serialize-surface.js +6 -0
- package/dist/serialize-surface.js.map +1 -0
- package/dist/storage/archetype.d.ts +38 -0
- package/dist/storage/archetype.d.ts.map +1 -0
- package/dist/storage/archetype.js +47 -0
- package/dist/storage/archetype.js.map +1 -0
- package/dist/storage/cold-store.d.ts +41 -0
- package/dist/storage/cold-store.d.ts.map +1 -0
- package/dist/storage/cold-store.js +100 -0
- package/dist/storage/cold-store.js.map +1 -0
- package/dist/storage/index.d.ts +10 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +5 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/signature.d.ts +27 -0
- package/dist/storage/signature.d.ts.map +1 -0
- package/dist/storage/signature.js +115 -0
- package/dist/storage/signature.js.map +1 -0
- package/dist/storage/storage.d.ts +72 -0
- package/dist/storage/storage.d.ts.map +1 -0
- package/dist/storage/storage.js +192 -0
- package/dist/storage/storage.js.map +1 -0
- package/dist/storage/store.d.ts +88 -0
- package/dist/storage/store.d.ts.map +1 -0
- package/dist/storage/store.js +473 -0
- package/dist/storage/store.js.map +1 -0
- package/dist/util/stable-index.d.ts +29 -0
- package/dist/util/stable-index.d.ts.map +1 -0
- package/dist/util/stable-index.js +51 -0
- package/dist/util/stable-index.js.map +1 -0
- package/dist/world.d.ts +262 -0
- package/dist/world.d.ts.map +1 -0
- package/dist/world.js +831 -0
- package/dist/world.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAGtE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAE5D,qBAAa,iBAAiB;;gBAQhB,GAAG,OAAO,EAAE,SAAS,OAAO,EAAE;IAG1C,QAAQ,CAAC,UAAU,EAAE,SAAS,YAAY,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI;IAU3D;;;;OAIG;IACH,gBAAgB,IAAI,WAAW;IAM/B;;;;;OAKG;IACH,iBAAiB,CAAC,GAAG,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,WAAW,GAAG,IAAI;IAMnE,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,MAAM,CAAC,GAAG,WAAW,GAAG,SAAS;IAIxD,KAAK,CAAC,EAAE,EAAE,WAAW,GAAG,YAAY,CAAC,MAAM,CAAC,GAAG,SAAS;IAIxD,iFAAiF;IACjF,IAAI,eAAe,IAAI,MAAM,CAE5B;CACF;AAED,YAAY,EAAE,gBAAgB,EAAE,CAAA"}
|
package/dist/registry.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// The component registry the world owns. Mints dense
|
|
2
|
+
// ComponentIds from FIRST_USER_COMPONENT_ID in createWorld({ components }) declaration order, wires
|
|
3
|
+
// each def's accessor factory, and exposes id↔def lookup. Column-set lifecycle moved to the storage
|
|
4
|
+
// module at (each real archetype owns its own ColumnSets); the registry no longer holds a
|
|
5
|
+
// (archetypeId, componentId) column cache or act as the accessor resolver.
|
|
6
|
+
import { FIRST_USER_COMPONENT_ID } from './ids.js';
|
|
7
|
+
import { registerComponentId } from './component/index.js';
|
|
8
|
+
export class ComponentRegistry {
|
|
9
|
+
#nextId = FIRST_USER_COMPONENT_ID;
|
|
10
|
+
#byDef = new Map();
|
|
11
|
+
#byId = [];
|
|
12
|
+
// The legacy (buffers, world) constructor args are no longer used by the registry (storage owns
|
|
13
|
+
// column-set lifecycle at ); they are accepted and ignored so call sites that only mint ids
|
|
14
|
+
// through `new ComponentRegistry(buffers, world).register(...)` keep compiling.
|
|
15
|
+
constructor(..._legacy) { }
|
|
16
|
+
// Deterministic dense id assignment in createWorld({ components }) declaration order.
|
|
17
|
+
register(components) {
|
|
18
|
+
for (const def of components) {
|
|
19
|
+
const id = this.#nextId;
|
|
20
|
+
this.#nextId += 1;
|
|
21
|
+
registerComponentId(def, id);
|
|
22
|
+
this.#byDef.set(def, id);
|
|
23
|
+
this.#byId[id] = def;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Mint the next dense ComponentId WITHOUT binding a def (allocSyntheticComponentId).
|
|
28
|
+
* Pair/presence/overflow ids draw from the SAME dense space as ordinary
|
|
29
|
+
* components so storage, queries, and the bitmask treat them identically. Serial / main-thread.
|
|
30
|
+
*/
|
|
31
|
+
allocSyntheticId() {
|
|
32
|
+
const id = this.#nextId;
|
|
33
|
+
this.#nextId += 1;
|
|
34
|
+
return id;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Intern a synthetic ComponentDef (a relation presence/overflow def, or a per-pair def) at an id
|
|
38
|
+
* already minted by `allocSyntheticId`, so `defOf`/`idOf` resolve it and storage can build its
|
|
39
|
+
* ColumnSet. Serial / main-thread; relations is the only caller (the acyclic boundary holds —
|
|
40
|
+
* the world exposes this through a seam, core never imports relations).
|
|
41
|
+
*/
|
|
42
|
+
registerSynthetic(def, id) {
|
|
43
|
+
registerComponentId(def, id);
|
|
44
|
+
this.#byDef.set(def, id);
|
|
45
|
+
this.#byId[id] = def;
|
|
46
|
+
}
|
|
47
|
+
idOf(def) {
|
|
48
|
+
return this.#byDef.get(def);
|
|
49
|
+
}
|
|
50
|
+
defOf(id) {
|
|
51
|
+
return this.#byId[id];
|
|
52
|
+
}
|
|
53
|
+
/**: seeds the bitmask/sigWords fixed stride = ceil(nextComponentId/32) ( C4). */
|
|
54
|
+
get nextComponentId() {
|
|
55
|
+
return this.#nextId;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,oGAAoG;AACpG,oGAAoG;AACpG,0FAA0F;AAC1F,2EAA2E;AAG3E,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAA;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAG1D,MAAM,OAAO,iBAAiB;IAC5B,OAAO,GAAW,uBAA4C,CAAA;IACrD,MAAM,GAAG,IAAI,GAAG,EAAqC,CAAA;IACrD,KAAK,GAA2B,EAAE,CAAA;IAE3C,gGAAgG;IAChG,4FAA4F;IAC5F,gFAAgF;IAChF,YAAY,GAAG,OAA2B,IAAG,CAAC;IAE9C,sFAAsF;IACtF,QAAQ,CAAC,UAA2C;QAClD,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,MAAM,EAAE,GAAG,IAAI,CAAC,OAAsB,CAAA;YACtC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAA;YACjB,mBAAmB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;YAC5B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;YACxB,IAAI,CAAC,KAAK,CAAC,EAAY,CAAC,GAAG,GAAG,CAAA;QAChC,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,gBAAgB;QACd,MAAM,EAAE,GAAG,IAAI,CAAC,OAAsB,CAAA;QACtC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAA;QACjB,OAAO,EAAE,CAAA;IACX,CAAC;IAED;;;;;OAKG;IACH,iBAAiB,CAAC,GAAyB,EAAE,EAAe;QAC1D,mBAAmB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;QAC5B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;QACxB,IAAI,CAAC,KAAK,CAAC,EAAY,CAAC,GAAG,GAAG,CAAA;IAChC,CAAC;IAED,IAAI,CAAC,GAAyB;QAC5B,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC7B,CAAC;IAED,KAAK,CAAC,EAAe;QACnB,OAAO,IAAI,CAAC,KAAK,CAAC,EAAY,CAAC,CAAA;IACjC,CAAC;IAED,iFAAiF;IACjF,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import type { ComponentId, EntityHandle, FieldDescriptor, RelationId, StorageStrategy } from '@ecsia/schema';
|
|
2
|
+
import type { Column, RuntimeCapabilities } from './memory/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* One persisted structural op (Create/Destroy/ComponentAdd/ComponentRemove/AddPair/RemovePair/
|
|
5
|
+
* SetPayload) the delta serializer reads from the since-T structural journal.
|
|
6
|
+
* `kind` is the SHARED structural-op ordinal (= reactivity ShapeKind = serialization
|
|
7
|
+
* DeltaOp). Handles are FULL portable handles; `componentId` is a user id (Add/Remove) or a synthetic
|
|
8
|
+
* pair id (AddPair/RemovePair); `target` is the full pair-target handle (0 when not a pair op).
|
|
9
|
+
*/
|
|
10
|
+
export interface SerializeStructuralRecord {
|
|
11
|
+
readonly tick: number;
|
|
12
|
+
readonly kind: number;
|
|
13
|
+
readonly handle: number;
|
|
14
|
+
readonly componentId: number;
|
|
15
|
+
readonly target: number;
|
|
16
|
+
}
|
|
17
|
+
/** One column-bearing component's columns on a hot archetype, with its field descriptors. */
|
|
18
|
+
export interface SerializeComponentColumns {
|
|
19
|
+
readonly componentId: ComponentId;
|
|
20
|
+
/** One Column per column-backed field (object fields contribute no column). */
|
|
21
|
+
readonly columns: readonly Column[];
|
|
22
|
+
/** The resolved field descriptors for the column-backed fields (parallel to `columns`). */
|
|
23
|
+
readonly fields: readonly FieldDescriptor[];
|
|
24
|
+
}
|
|
25
|
+
/** A hot archetype's serializable view: identity, signature, occupants, and column-bearing members. */
|
|
26
|
+
export interface SerializeArchetype {
|
|
27
|
+
readonly id: number;
|
|
28
|
+
/** The sorted canonical signature (ComponentIds, including tag/pair/presence ids). */
|
|
29
|
+
readonly signature: readonly number[];
|
|
30
|
+
readonly count: number;
|
|
31
|
+
/** rows[r] = the FULL EntityHandle occupying row r (memory-buffers ). */
|
|
32
|
+
readonly rows: Uint32Array;
|
|
33
|
+
/** Column-bearing components only (tags skipped — ). */
|
|
34
|
+
readonly components: readonly SerializeComponentColumns[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* One rich (sidecar-backed) field across the registered component set. The
|
|
38
|
+
* snapshot/delta JSON sidecar section enumerates these — CRITICALLY independent of `SerializeArchetype`,
|
|
39
|
+
* because `archetypeView`/`SerializeComponentColumns` skip no-ColumnSet components and strip `ctor===null`
|
|
40
|
+
* fields, so a rich-ONLY component (e.g. `{ name: 'string' }`) never appears in `a.components`. The
|
|
41
|
+
* writer joins `a.signature ∩ richFields()` per entity rather than reading `a.components`.
|
|
42
|
+
*/
|
|
43
|
+
export interface SerializeRichField {
|
|
44
|
+
readonly componentId: ComponentId;
|
|
45
|
+
/** The field's index in `def.fields` (declaration order) — parallel on producer + receiver. */
|
|
46
|
+
readonly fieldIndex: number;
|
|
47
|
+
readonly name: string;
|
|
48
|
+
readonly kind: 'string' | 'object';
|
|
49
|
+
}
|
|
50
|
+
/** Component-registry metadata for the snapshot registry section. */
|
|
51
|
+
export interface SerializeComponentMeta {
|
|
52
|
+
readonly name: string;
|
|
53
|
+
readonly id: ComponentId;
|
|
54
|
+
readonly fieldCount: number;
|
|
55
|
+
readonly storage: StorageStrategy;
|
|
56
|
+
}
|
|
57
|
+
/** One logical live relation pair. */
|
|
58
|
+
export interface SerializePair {
|
|
59
|
+
readonly subject: EntityHandle;
|
|
60
|
+
readonly relationId: RelationId;
|
|
61
|
+
/** The target handle, or null for a cleared exclusive target. */
|
|
62
|
+
readonly target: EntityHandle | null;
|
|
63
|
+
/** Payload field values keyed by field name, or undefined for tag relations. */
|
|
64
|
+
readonly payload: Record<string, unknown> | undefined;
|
|
65
|
+
}
|
|
66
|
+
/** Relation metadata + live-pair enumeration + re-apply, provided by @ecsia/relations ( seam). */
|
|
67
|
+
export interface SerializeRelationProvider {
|
|
68
|
+
/** Dense relation metadata, in registration (relationId-ascending) order. */
|
|
69
|
+
relations(): readonly {
|
|
70
|
+
readonly name: string;
|
|
71
|
+
readonly id: RelationId;
|
|
72
|
+
readonly exclusive: boolean;
|
|
73
|
+
readonly hasPayload: boolean;
|
|
74
|
+
readonly presenceId: ComponentId;
|
|
75
|
+
}[];
|
|
76
|
+
/** Every live pair across all relations, in deterministic (relationId, subject, target) order. */
|
|
77
|
+
livePairs(): readonly SerializePair[];
|
|
78
|
+
/** Re-establish a pair on deserialize (re-mints the receiver-local pair id). */
|
|
79
|
+
addPair(subject: EntityHandle, relationId: RelationId, target: EntityHandle | null, payload: Record<string, unknown> | undefined): void;
|
|
80
|
+
/** Map a synthetic pair ComponentId back to its logical RelationId (delta structural pair records). */
|
|
81
|
+
relationIdOfPair(pairId: ComponentId): RelationId | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* Read a live pair's CURRENT payload by logical (subject, relationId, target), or undefined for a tag
|
|
84
|
+
* relation / absent pair. The delta structural section reads this at emit time so PairAdd/PairPayload
|
|
85
|
+
* records carry values-on-add.
|
|
86
|
+
*/
|
|
87
|
+
pairPayloadOf(subject: EntityHandle, relationId: RelationId, target: EntityHandle): Record<string, unknown> | undefined;
|
|
88
|
+
/** Tear down a pair on a delta-apply receiver (PairRemove). */
|
|
89
|
+
removePair(subject: EntityHandle, relationId: RelationId, target: EntityHandle): void;
|
|
90
|
+
}
|
|
91
|
+
/** The full surface @ecsia/serialization drives. All members are serial / main-thread. */
|
|
92
|
+
export interface SerializationSurface {
|
|
93
|
+
/** FNV-1a hash of the canonical (componentName, fieldName, token)* + relation names. */
|
|
94
|
+
schemaHash(): number;
|
|
95
|
+
/** Registry component metadata in dense-id order (real user components only; not synthetic). */
|
|
96
|
+
components(): readonly SerializeComponentMeta[];
|
|
97
|
+
/** A registered component's resolved field descriptors (for payload encode/decode by name). */
|
|
98
|
+
fieldsOf(id: ComponentId): readonly FieldDescriptor[] | undefined;
|
|
99
|
+
/** Resolve a component id by registered name (deserialize id-remap-by-name). */
|
|
100
|
+
componentIdByName(name: string): ComponentId | undefined;
|
|
101
|
+
/** Number of registered component types at snapshot time (sanity check). */
|
|
102
|
+
numComponentTypes(): number;
|
|
103
|
+
/** Hot archetypes with >=1 row, in id-ascending order. */
|
|
104
|
+
archetypes(): readonly SerializeArchetype[];
|
|
105
|
+
/** Relation provider, or undefined in a relation-free world. */
|
|
106
|
+
relations(): SerializeRelationProvider | undefined;
|
|
107
|
+
/**
|
|
108
|
+
* Rich-field descriptors across ALL registered components, in (componentId, fieldIndex) order. The
|
|
109
|
+
* snapshot/delta rich-value walk MUST use this, NOT `archetypes()[].components`, which cannot surface
|
|
110
|
+
* rich-only components. Empty in a world with no `'string'`/`object<T>` fields.
|
|
111
|
+
*/
|
|
112
|
+
richFields(): readonly SerializeRichField[];
|
|
113
|
+
/**
|
|
114
|
+
* Read a live entity's rich value by (handle, componentId, fieldIndex). Returns the field default for a
|
|
115
|
+
* never-written / recycled slot (RF-HYGIENE). Returns `undefined` for an unknown column or dead handle.
|
|
116
|
+
*/
|
|
117
|
+
richValueOf(handle: EntityHandle, componentId: ComponentId, fieldIndex: number): unknown;
|
|
118
|
+
/**
|
|
119
|
+
* Whether a live entity has a WRITTEN rich value (vs the lazy default) at (handle, componentId,
|
|
120
|
+
* fieldIndex). The snapshot/delta writers emit only present values — a
|
|
121
|
+
* default/empty slot is skipped and re-defaulted on the receiver.
|
|
122
|
+
*/
|
|
123
|
+
richIsPresent(handle: EntityHandle, componentId: ComponentId, fieldIndex: number): boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Write a rich value on a deserialize/apply receiver. Routes through the sidecar AND `trackWrite` so the
|
|
126
|
+
* loaded value is change-tracked identically to a live write (a subsequent delta from the receiver picks
|
|
127
|
+
* it up). No-op for a dead handle / unknown column.
|
|
128
|
+
*/
|
|
129
|
+
setRichValue(handle: EntityHandle, componentId: ComponentId, fieldIndex: number, value: unknown): void;
|
|
130
|
+
/**
|
|
131
|
+
* Turn on the persistent structural journal: the since-T STRUCTURAL source a
|
|
132
|
+
* delta serializer needs. Idempotent; the structural twin of enabling changeVersion stamping. Call
|
|
133
|
+
* once at delta-serializer construction so subsequent structural ops are journaled.
|
|
134
|
+
*/
|
|
135
|
+
enableStructuralJournal(): void;
|
|
136
|
+
/**
|
|
137
|
+
* /: the structural ops committed with tick > since, in commit order, as portable
|
|
138
|
+
* full-handle records. `gap` is true when `since` predates the bounded journal's live window (the
|
|
139
|
+
* caller must resync from a snapshot — the no-partial-apply delta-gap rule).
|
|
140
|
+
*/
|
|
141
|
+
drainStructuralSince(since: number): {
|
|
142
|
+
records: readonly SerializeStructuralRecord[];
|
|
143
|
+
gap: boolean;
|
|
144
|
+
};
|
|
145
|
+
/** Map a synthetic pair ComponentId to its logical RelationId (for delta structural pair records). */
|
|
146
|
+
relationIdOfPair(pairId: ComponentId): RelationId | undefined;
|
|
147
|
+
/** Spawn a fresh entity (PASS 1 remap-table build). */
|
|
148
|
+
spawn(): EntityHandle;
|
|
149
|
+
/** Place a live handle into the target signature in ONE migration. */
|
|
150
|
+
spawnInto(handle: EntityHandle, componentIds: readonly ComponentId[]): void;
|
|
151
|
+
/** Remove the given components from `handle` in ONE migration (delta apply: ComponentRemove). */
|
|
152
|
+
removeComponents(handle: EntityHandle, componentIds: readonly ComponentId[]): void;
|
|
153
|
+
/** Destroy a live entity (delta apply: EntityDestroy). Idempotent on a dead handle. */
|
|
154
|
+
despawn(handle: EntityHandle): void;
|
|
155
|
+
/** The (hot) ColumnSet columns + row for `componentId` on `handle`, or null if absent/cold/tag. */
|
|
156
|
+
columnsOf(handle: EntityHandle, componentId: ComponentId): {
|
|
157
|
+
columns: readonly Column[];
|
|
158
|
+
fields: readonly FieldDescriptor[];
|
|
159
|
+
row: number;
|
|
160
|
+
} | null;
|
|
161
|
+
/** Despawn every alive entity (mode:'replace' precondition, / world.clear). */
|
|
162
|
+
clearAll(): void;
|
|
163
|
+
/** Count of currently-alive entities (mode:'replace' empty-check). */
|
|
164
|
+
aliveCount(): number;
|
|
165
|
+
readonly indexBits: number;
|
|
166
|
+
handleIndex(handle: EntityHandle): number;
|
|
167
|
+
/** Frozen runtime capabilities (memory-buffers ) for the worker bootstrap manifest. */
|
|
168
|
+
capabilities(): RuntimeCapabilities;
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=serialize-surface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize-surface.d.ts","sourceRoot":"","sources":["../src/serialize-surface.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// The internal seam @ecsia/serialization reads/writes through, exposed on World as `__serialize`.
|
|
2
|
+
// Keeps the dependency direction acyclic: serialization imports @ecsia/core for this surface; core
|
|
3
|
+
// NEVER imports serialization. Everything here is serial / main-thread (snapshots run at a flush
|
|
4
|
+
// point). The world wires a concrete implementation in createWorld.
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=serialize-surface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize-surface.js","sourceRoot":"","sources":["../src/serialize-surface.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,mGAAmG;AACnG,iGAAiG;AACjG,oEAAoE"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ComponentId, ComponentDef, Schema } from '@ecsia/schema';
|
|
2
|
+
import type { ArchetypeId } from '@ecsia/schema';
|
|
3
|
+
import type { Buffers, Column } from '../memory/index.js';
|
|
4
|
+
import type { AccessorWorld, ColumnSet } from '../component/index.js';
|
|
5
|
+
import type { Signature } from './signature.js';
|
|
6
|
+
/** Synthetic component id keying each archetype's row-list column (never in any signature). */
|
|
7
|
+
declare const ROWLIST_COMPONENT_ID = 4294967294;
|
|
8
|
+
export interface Archetype {
|
|
9
|
+
readonly id: ArchetypeId;
|
|
10
|
+
readonly signature: Signature;
|
|
11
|
+
readonly sigWords: Uint32Array;
|
|
12
|
+
readonly hash: number;
|
|
13
|
+
/** componentId → its ColumnSet. Hot archetypes only; tag/cold archetypes leave it empty. */
|
|
14
|
+
readonly columnSets: Map<ComponentId, ColumnSet>;
|
|
15
|
+
/** Dense entity-row list column: rows[r] = the FULL EntityHandle occupying row r. */
|
|
16
|
+
rowsColumn: Column | null;
|
|
17
|
+
rows: Uint32Array;
|
|
18
|
+
count: number;
|
|
19
|
+
/** Lazy edge cache keyed by single ComponentId. */
|
|
20
|
+
readonly edges: Map<ComponentId, {
|
|
21
|
+
add?: Archetype;
|
|
22
|
+
remove?: Archetype;
|
|
23
|
+
}>;
|
|
24
|
+
/** Fragmentation policy state. */
|
|
25
|
+
cold: boolean;
|
|
26
|
+
lastAccessTick: number;
|
|
27
|
+
}
|
|
28
|
+
export interface ArchetypeColumnDeps {
|
|
29
|
+
readonly buffers: Buffers;
|
|
30
|
+
readonly accessorWorld: AccessorWorld;
|
|
31
|
+
readonly initialCapacity: number;
|
|
32
|
+
defOf(c: ComponentId): ComponentDef<Schema> | undefined;
|
|
33
|
+
}
|
|
34
|
+
/** Allocate the row-list column + one ColumnSet per column-bearing component (hot archetype only). */
|
|
35
|
+
export declare function attachHotColumns(arch: Archetype, deps: ArchetypeColumnDeps): void;
|
|
36
|
+
export declare function makeArchetype(id: ArchetypeId, sig: Signature, hash: number, stride: number, tick: number, cold: boolean): Archetype;
|
|
37
|
+
export { ROWLIST_COMPONENT_ID };
|
|
38
|
+
//# sourceMappingURL=archetype.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archetype.d.ts","sourceRoot":"","sources":["../../src/storage/archetype.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAGzD,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAoB,MAAM,uBAAuB,CAAA;AACvF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAG/C,+FAA+F;AAC/F,QAAA,MAAM,oBAAoB,aAAc,CAAA;AAIxC,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,EAAE,WAAW,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAA;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IAErB,4FAA4F;IAC5F,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;IAEhD,qFAAqF;IACrF,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,IAAI,EAAE,WAAW,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IAEb,mDAAmD;IACnD,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,WAAW,EAAE;QAAE,GAAG,CAAC,EAAE,SAAS,CAAC;QAAC,MAAM,CAAC,EAAE,SAAS,CAAA;KAAE,CAAC,CAAA;IAEzE,kCAAkC;IAClC,IAAI,EAAE,OAAO,CAAA;IACb,cAAc,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAA;IACrC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,KAAK,CAAC,CAAC,EAAE,WAAW,GAAG,YAAY,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;CACxD;AAED,sGAAsG;AACtG,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAoBjF;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,SAAS,CAcnI;AAED,OAAO,EAAE,oBAAoB,EAAE,CAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// The archetype table: a ColumnSet per column-bearing component in the
|
|
2
|
+
// signature + a dense entity-row list. Tag / zero-field components contribute NO ColumnSet
|
|
3
|
+
// (presence is pure signature membership). The rows list is itself a u32 column allocated
|
|
4
|
+
// through Buffers so it grows under the same length-tracking protocol as data columns.
|
|
5
|
+
import { columnKey, makeColumnLayout } from '../memory/index.js';
|
|
6
|
+
import { buildColumnSet } from '../component/index.js';
|
|
7
|
+
import { buildSigWords } from './signature.js';
|
|
8
|
+
/** Synthetic component id keying each archetype's row-list column (never in any signature). */
|
|
9
|
+
const ROWLIST_COMPONENT_ID = 0xffff_fffe;
|
|
10
|
+
const ROW_LAYOUT = makeColumnLayout('u32', 1, 0);
|
|
11
|
+
/** Allocate the row-list column + one ColumnSet per column-bearing component (hot archetype only). */
|
|
12
|
+
export function attachHotColumns(arch, deps) {
|
|
13
|
+
const { buffers, accessorWorld, initialCapacity, defOf } = deps;
|
|
14
|
+
const rowsKey = columnKey(arch.id, ROWLIST_COMPONENT_ID, 0);
|
|
15
|
+
const rowsColumn = buffers.column(rowsKey, ROW_LAYOUT, initialCapacity);
|
|
16
|
+
arch.rowsColumn = rowsColumn;
|
|
17
|
+
arch.rows = rowsColumn.view;
|
|
18
|
+
for (let i = 0; i < arch.signature.length; i++) {
|
|
19
|
+
const c = arch.signature[i];
|
|
20
|
+
const def = defOf(c);
|
|
21
|
+
if (def === undefined)
|
|
22
|
+
continue; // pair/synthetic id with no registered def yet (relations)
|
|
23
|
+
const rt = def;
|
|
24
|
+
// A pure tag (no columns AND no rich fields) gets no ColumnSet. A rich-only or mixed component DOES
|
|
25
|
+
// get one — its accessor carries the sidecar getters/setters even with zero columns.
|
|
26
|
+
if (rt.columnLayouts.length === 0 && !rt.hasRichFields)
|
|
27
|
+
continue;
|
|
28
|
+
arch.columnSets.set(c, buildColumnSet({ buffers, archetypeId: arch.id, def, world: accessorWorld, initialCapacity }));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export function makeArchetype(id, sig, hash, stride, tick, cold) {
|
|
32
|
+
return {
|
|
33
|
+
id,
|
|
34
|
+
signature: sig,
|
|
35
|
+
sigWords: buildSigWords(sig, stride),
|
|
36
|
+
hash,
|
|
37
|
+
columnSets: new Map(),
|
|
38
|
+
rowsColumn: null,
|
|
39
|
+
rows: new Uint32Array(0),
|
|
40
|
+
count: 0,
|
|
41
|
+
edges: new Map(),
|
|
42
|
+
cold,
|
|
43
|
+
lastAccessTick: tick,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export { ROWLIST_COMPONENT_ID };
|
|
47
|
+
//# sourceMappingURL=archetype.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archetype.js","sourceRoot":"","sources":["../../src/storage/archetype.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,2FAA2F;AAC3F,0FAA0F;AAC1F,uFAAuF;AAKvF,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAGtD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAE9C,+FAA+F;AAC/F,MAAM,oBAAoB,GAAG,WAAW,CAAA;AAExC,MAAM,UAAU,GAAG,gBAAgB,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;AA+BhD,sGAAsG;AACtG,MAAM,UAAU,gBAAgB,CAAC,IAAe,EAAE,IAAyB;IACzE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,KAAK,EAAE,GAAG,IAAI,CAAA;IAC/D,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,EAAY,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAA;IACrE,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,eAAe,CAAC,CAAA;IACvE,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC5B,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC,IAAmB,CAAA;IAE1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/C,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAA0B,CAAA;QACpD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;QACpB,IAAI,GAAG,KAAK,SAAS;YAAE,SAAQ,CAAC,2DAA2D;QAC3F,MAAM,EAAE,GAAG,GAA+B,CAAA;QAC1C,oGAAoG;QACpG,qFAAqF;QACrF,IAAI,EAAE,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa;YAAE,SAAQ;QAChE,IAAI,CAAC,UAAU,CAAC,GAAG,CACjB,CAAC,EACD,cAAc,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,EAAY,EAAE,GAAG,EAAE,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,CAAC,CACxG,CAAA;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAAe,EAAE,GAAc,EAAE,IAAY,EAAE,MAAc,EAAE,IAAY,EAAE,IAAa;IACtH,OAAO;QACL,EAAE;QACF,SAAS,EAAE,GAAG;QACd,QAAQ,EAAE,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC;QACpC,IAAI;QACJ,UAAU,EAAE,IAAI,GAAG,EAAE;QACrB,UAAU,EAAE,IAAI;QAChB,IAAI,EAAE,IAAI,WAAW,CAAC,CAAC,CAAC;QACxB,KAAK,EAAE,CAAC;QACR,KAAK,EAAE,IAAI,GAAG,EAAE;QAChB,IAAI;QACJ,cAAc,EAAE,IAAI;KACrB,CAAA;AACH,CAAC;AAED,OAAO,EAAE,oBAAoB,EAAE,CAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { ComponentId, ComponentDef, Schema } from '@ecsia/schema';
|
|
2
|
+
import type { ArchetypeId } from '@ecsia/schema';
|
|
3
|
+
import type { Buffers } from '../memory/index.js';
|
|
4
|
+
import type { AccessorWorld, ColumnSet } from '../component/index.js';
|
|
5
|
+
declare const COLD_ARCHETYPE_ID = 4294967040;
|
|
6
|
+
export interface ColdStore {
|
|
7
|
+
/** componentId → a packed SoA block (one ColumnSet per component TYPE, not per archetype). */
|
|
8
|
+
readonly blocks: Map<ComponentId, ColumnSet>;
|
|
9
|
+
/** (entityIndex, componentId) → row in that component's block. key = entityIndex * SCALE + componentId. */
|
|
10
|
+
readonly rowOf: Map<number, number>;
|
|
11
|
+
/** entityIndex → its cold archetype id (so resolveLocation still yields an ArchetypeId). */
|
|
12
|
+
readonly archOf: Map<number, ArchetypeId>;
|
|
13
|
+
/** entityIndex → the full EntityHandle occupying the cold slot (for promotion's hot row list). */
|
|
14
|
+
readonly handleOf: Map<number, number>;
|
|
15
|
+
/** Next free row per component block. */
|
|
16
|
+
readonly nextRow: Map<ComponentId, number>;
|
|
17
|
+
/** Reclaimed rows per component block, reused before advancing nextRow (prevents leak). */
|
|
18
|
+
readonly freeRows: Map<ComponentId, number[]>;
|
|
19
|
+
}
|
|
20
|
+
export declare function makeColdStore(): ColdStore;
|
|
21
|
+
export interface ColdDeps {
|
|
22
|
+
readonly buffers: Buffers;
|
|
23
|
+
readonly accessorWorld: AccessorWorld;
|
|
24
|
+
readonly initialCapacity: number;
|
|
25
|
+
defOf(c: ComponentId): ComponentDef<Schema> | undefined;
|
|
26
|
+
}
|
|
27
|
+
declare function coldKey(entityIndex: number, componentId: number): number;
|
|
28
|
+
export declare function blockFor(cold: ColdStore, c: ComponentId, deps: ColdDeps): ColumnSet | null;
|
|
29
|
+
/** Reserve a cold row for `componentId` under `entityIndex`, growing the block as needed. */
|
|
30
|
+
export declare function coldAllocRow(cold: ColdStore, entityIndex: number, c: ComponentId, deps: ColdDeps): number;
|
|
31
|
+
/** The cold block row for (entityIndex, componentId), or -1 if absent. */
|
|
32
|
+
export declare function coldRowOf(cold: ColdStore, entityIndex: number, c: ComponentId): number;
|
|
33
|
+
/**
|
|
34
|
+
* Reclaim the cold rows this entity holds for the components in `comps`, returning each to its
|
|
35
|
+
* block's free-list. Stale (index,componentId) mappings would otherwise leak monotonically and
|
|
36
|
+
* survive generational index reuse. When `dropEntity` (the entity is leaving the cold store
|
|
37
|
+
* entirely — despawn or promotion to a hot archetype) also drop its archOf/handleOf entries.
|
|
38
|
+
*/
|
|
39
|
+
export declare function coldReclaim(cold: ColdStore, entityIndex: number, comps: Iterable<number>, dropEntity?: boolean): void;
|
|
40
|
+
export { COLD_ARCHETYPE_ID, coldKey };
|
|
41
|
+
//# sourceMappingURL=cold-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cold-store.d.ts","sourceRoot":"","sources":["../../src/storage/cold-store.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAIrE,QAAA,MAAM,iBAAiB,aAAc,CAAA;AAErC,MAAM,WAAW,SAAS;IACxB,8FAA8F;IAC9F,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;IAC5C,2GAA2G;IAC3G,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,4FAA4F;IAC5F,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IACzC,kGAAkG;IAClG,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACtC,yCAAyC;IACzC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;IAC1C,2FAA2F;IAC3F,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,CAAA;CAC9C;AAID,wBAAgB,aAAa,IAAI,SAAS,CASzC;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAA;IACrC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,KAAK,CAAC,CAAC,EAAE,WAAW,GAAG,YAAY,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;CACxD;AAED,iBAAS,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,IAAI,CAmB1F;AAED,6FAA6F;AAC7F,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAgBzG;AAED,0EAA0E;AAC1E,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,EAAE,WAAW,GAAG,MAAM,CAEtF;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,SAAS,EACf,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,EACvB,UAAU,UAAO,GAChB,IAAI,CAkBN;AAED,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAA"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// The cold-archetype overflow store. When hotCount reaches
|
|
2
|
+
// maxHotArchetypes, new archetypes are marked cold: they have NO dedicated columns; their entities
|
|
3
|
+
// live in a shared SoA block keyed per component type (NOT per archetype). Membership still uses
|
|
4
|
+
// the per-entity bitmask + signature, so has()/matching/iteration are transparent.
|
|
5
|
+
//
|
|
6
|
+
// This module is the cold-path SCAFFOLDING, built for correctness: per-component blocks allocated lazily via
|
|
7
|
+
// Buffers.column, an (entityIndex, componentId) → row map, and an entityIndex → cold ArchetypeId
|
|
8
|
+
// map so resolveLocation still yields an ArchetypeId. Relation-driven fragmentation is exercised at
|
|
9
|
+
// explicit world.warm promotion is wired here.
|
|
10
|
+
import { buildColumnSet } from '../component/index.js';
|
|
11
|
+
const COLD_ARCHETYPE_ID = 0xffff_ff00; // synthetic archetype id keying every cold component block
|
|
12
|
+
const KEY_SCALE = 0x1_0000_0000; // entityIndex occupies the high bits, componentId the low 32
|
|
13
|
+
export function makeColdStore() {
|
|
14
|
+
return {
|
|
15
|
+
blocks: new Map(),
|
|
16
|
+
rowOf: new Map(),
|
|
17
|
+
archOf: new Map(),
|
|
18
|
+
handleOf: new Map(),
|
|
19
|
+
nextRow: new Map(),
|
|
20
|
+
freeRows: new Map(),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function coldKey(entityIndex, componentId) {
|
|
24
|
+
return entityIndex * KEY_SCALE + componentId;
|
|
25
|
+
}
|
|
26
|
+
export function blockFor(cold, c, deps) {
|
|
27
|
+
let block = cold.blocks.get(c);
|
|
28
|
+
if (block !== undefined)
|
|
29
|
+
return block;
|
|
30
|
+
const def = deps.defOf(c);
|
|
31
|
+
if (def === undefined)
|
|
32
|
+
return null;
|
|
33
|
+
const rt = def;
|
|
34
|
+
// Pure tag: no cold block. A rich-only/mixed component DOES get one so its accessor (carrying the
|
|
35
|
+
// sidecar getters) is resolvable cold; the 0-column block allocates no column storage.
|
|
36
|
+
if (rt.columnLayouts.length === 0 && !rt.hasRichFields)
|
|
37
|
+
return null;
|
|
38
|
+
block = buildColumnSet({
|
|
39
|
+
buffers: deps.buffers,
|
|
40
|
+
archetypeId: COLD_ARCHETYPE_ID,
|
|
41
|
+
def,
|
|
42
|
+
world: deps.accessorWorld,
|
|
43
|
+
initialCapacity: deps.initialCapacity,
|
|
44
|
+
});
|
|
45
|
+
cold.blocks.set(c, block);
|
|
46
|
+
cold.nextRow.set(c, 0);
|
|
47
|
+
return block;
|
|
48
|
+
}
|
|
49
|
+
/** Reserve a cold row for `componentId` under `entityIndex`, growing the block as needed. */
|
|
50
|
+
export function coldAllocRow(cold, entityIndex, c, deps) {
|
|
51
|
+
const block = blockFor(cold, c, deps);
|
|
52
|
+
if (block === null)
|
|
53
|
+
return -1;
|
|
54
|
+
const free = cold.freeRows.get(c);
|
|
55
|
+
const reclaimed = free !== undefined && free.length > 0 ? free.pop() : undefined;
|
|
56
|
+
if (reclaimed !== undefined) {
|
|
57
|
+
cold.rowOf.set(coldKey(entityIndex, c), reclaimed);
|
|
58
|
+
return reclaimed;
|
|
59
|
+
}
|
|
60
|
+
const next = cold.nextRow.get(c) ?? 0;
|
|
61
|
+
for (const col of block.columns) {
|
|
62
|
+
if (next + 1 > col.capacity())
|
|
63
|
+
deps.buffers.grow(col, next + 1);
|
|
64
|
+
}
|
|
65
|
+
cold.nextRow.set(c, next + 1);
|
|
66
|
+
cold.rowOf.set(coldKey(entityIndex, c), next);
|
|
67
|
+
return next;
|
|
68
|
+
}
|
|
69
|
+
/** The cold block row for (entityIndex, componentId), or -1 if absent. */
|
|
70
|
+
export function coldRowOf(cold, entityIndex, c) {
|
|
71
|
+
return cold.rowOf.get(coldKey(entityIndex, c)) ?? -1;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Reclaim the cold rows this entity holds for the components in `comps`, returning each to its
|
|
75
|
+
* block's free-list. Stale (index,componentId) mappings would otherwise leak monotonically and
|
|
76
|
+
* survive generational index reuse. When `dropEntity` (the entity is leaving the cold store
|
|
77
|
+
* entirely — despawn or promotion to a hot archetype) also drop its archOf/handleOf entries.
|
|
78
|
+
*/
|
|
79
|
+
export function coldReclaim(cold, entityIndex, comps, dropEntity = true) {
|
|
80
|
+
for (const cn of comps) {
|
|
81
|
+
const c = cn;
|
|
82
|
+
const key = coldKey(entityIndex, cn);
|
|
83
|
+
const row = cold.rowOf.get(key);
|
|
84
|
+
if (row === undefined)
|
|
85
|
+
continue;
|
|
86
|
+
cold.rowOf.delete(key);
|
|
87
|
+
let free = cold.freeRows.get(c);
|
|
88
|
+
if (free === undefined) {
|
|
89
|
+
free = [];
|
|
90
|
+
cold.freeRows.set(c, free);
|
|
91
|
+
}
|
|
92
|
+
free.push(row);
|
|
93
|
+
}
|
|
94
|
+
if (dropEntity) {
|
|
95
|
+
cold.archOf.delete(entityIndex);
|
|
96
|
+
cold.handleOf.delete(entityIndex);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export { COLD_ARCHETYPE_ID, coldKey };
|
|
100
|
+
//# sourceMappingURL=cold-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cold-store.js","sourceRoot":"","sources":["../../src/storage/cold-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { ArchetypeStore, EMPTY_ARCHETYPE_ID, ARCHETYPE_NONE, } from './store.js';
|
|
2
|
+
export type { RecordSurface, StorageDeps } from './store.js';
|
|
3
|
+
export { Storage } from './storage.js';
|
|
4
|
+
export type { StorageConfig, DefRegistry } from './storage.js';
|
|
5
|
+
export type { Archetype } from './archetype.js';
|
|
6
|
+
export type { ColdStore } from './cold-store.js';
|
|
7
|
+
export { makeColdStore, coldRowOf, coldReclaim } from './cold-store.js';
|
|
8
|
+
export type { Signature, MatchTerm } from './signature.js';
|
|
9
|
+
export { canonicalize, sigEquals, sigHash, sigHas, sigWithAdded, sigWithRemoved, buildSigWords, signatureMatches, } from './signature.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,cAAc,GACf,MAAM,YAAY,CAAA;AACnB,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE5D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE9D,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE/C,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAEvE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,EACL,YAAY,EACZ,SAAS,EACT,OAAO,EACP,MAAM,EACN,YAAY,EACZ,cAAc,EACd,aAAa,EACb,gBAAgB,GACjB,MAAM,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { ArchetypeStore, EMPTY_ARCHETYPE_ID, ARCHETYPE_NONE, } from './store.js';
|
|
2
|
+
export { Storage } from './storage.js';
|
|
3
|
+
export { makeColdStore, coldRowOf, coldReclaim } from './cold-store.js';
|
|
4
|
+
export { canonicalize, sigEquals, sigHash, sigHas, sigWithAdded, sigWithRemoved, buildSigWords, signatureMatches, } from './signature.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,cAAc,GACf,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAMtC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAGvE,OAAO,EACL,YAAY,EACZ,SAAS,EACT,OAAO,EACP,MAAM,EACN,YAAY,EACZ,cAAc,EACd,aAAa,EACb,gBAAgB,GACjB,MAAM,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ComponentId } from '@ecsia/schema';
|
|
2
|
+
/** Canonical, sorted, de-duplicated component ids. Owned (never aliased) per archetype. */
|
|
3
|
+
export type Signature = Uint32Array & {
|
|
4
|
+
readonly __ecsiaSignature: unique symbol;
|
|
5
|
+
};
|
|
6
|
+
/** O(n) equality of two sorted signatures. */
|
|
7
|
+
export declare function sigEquals(a: Signature, b: Signature): boolean;
|
|
8
|
+
/** FNV-1a over the sorted ids → 32-bit hash for the archetype lookup map. */
|
|
9
|
+
export declare function sigHash(a: Signature): number;
|
|
10
|
+
/** Sort + de-dup an arbitrary id multiset into the canonical form ( holds). */
|
|
11
|
+
export declare function canonicalize(ids: Iterable<ComponentId | number>): Signature;
|
|
12
|
+
/** The neighbor signature reached by adding `c` (sorted insert). Idempotent if `c` already present. */
|
|
13
|
+
export declare function sigWithAdded(sig: Signature, c: ComponentId): Signature;
|
|
14
|
+
/** The neighbor signature reached by removing `c`. Returns `sig` unchanged if `c` is absent. */
|
|
15
|
+
export declare function sigWithRemoved(sig: Signature, c: ComponentId): Signature;
|
|
16
|
+
/** Packed membership words for fast bitwise-AND query matching. */
|
|
17
|
+
export declare function buildSigWords(sig: Signature, stride: number): Uint32Array;
|
|
18
|
+
/** Exact membership test against the sorted signature array, O(log |sig|). */
|
|
19
|
+
export declare function sigHas(sig: Signature, c: ComponentId | number): boolean;
|
|
20
|
+
/** One AND-term against a packed signature word. */
|
|
21
|
+
export interface MatchTerm {
|
|
22
|
+
readonly wordIndex: number;
|
|
23
|
+
readonly mask: number;
|
|
24
|
+
}
|
|
25
|
+
/** Signature-AND helper the query module calls; exposed for testing. */
|
|
26
|
+
export declare function signatureMatches(sigWords: Uint32Array, withW: readonly MatchTerm[], notW: readonly MatchTerm[], orW: readonly MatchTerm[]): boolean;
|
|
27
|
+
//# sourceMappingURL=signature.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signature.d.ts","sourceRoot":"","sources":["../../src/storage/signature.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,2FAA2F;AAC3F,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG;IAAE,QAAQ,CAAC,gBAAgB,EAAE,OAAO,MAAM,CAAA;CAAE,CAAA;AAElF,8CAA8C;AAC9C,wBAAgB,SAAS,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,GAAG,OAAO,CAI7D;AAED,6EAA6E;AAC7E,wBAAgB,OAAO,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAO5C;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,WAAW,GAAG,MAAM,CAAC,GAAG,SAAS,CAI3E;AAED,uGAAuG;AACvG,wBAAgB,YAAY,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,EAAE,WAAW,GAAG,SAAS,CAiBtE;AAED,gGAAgG;AAChG,wBAAgB,cAAc,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,EAAE,WAAW,GAAG,SAAS,CAoBxE;AAED,mEAAmE;AACnE,wBAAgB,aAAa,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAOzE;AAED,8EAA8E;AAC9E,wBAAgB,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,OAAO,CAYvE;AAED,oDAAoD;AACpD,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,WAAW,EACrB,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,IAAI,EAAE,SAAS,SAAS,EAAE,EAC1B,GAAG,EAAE,SAAS,SAAS,EAAE,GACxB,OAAO,CAKT"}
|