@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,473 @@
|
|
|
1
|
+
// The archetype store: signature interning, the lazy edge graph, swap-pop row alloc/removal, and
|
|
2
|
+
// migration. All run serial / main-thread. The
|
|
3
|
+
// store owns archetype identity + columns; it CALLS the entity record's commitRecord (the two-word
|
|
4
|
+
// structural commit point) and drives the per-entity bitmask delta after each
|
|
5
|
+
// migration commit. It never owns the handle codec or the free-list (entity module).
|
|
6
|
+
import { canonicalize, sigEquals, sigHas, sigHash, sigWithAdded, sigWithRemoved, } from './signature.js';
|
|
7
|
+
import { attachHotColumns, makeArchetype } from './archetype.js';
|
|
8
|
+
import { makeColdStore, coldAllocRow, coldRowOf, coldReclaim } from './cold-store.js';
|
|
9
|
+
// EMPTY_ARCHETYPE_ID is dense id 0: a REAL archetype (the empty signature), distinct from the
|
|
10
|
+
// ARCHETYPE_NONE record sentinel. This module is the normative definer.
|
|
11
|
+
export const EMPTY_ARCHETYPE_ID = 0;
|
|
12
|
+
export const ARCHETYPE_NONE = 0xffffffff;
|
|
13
|
+
const INITIAL_ROWS = 64;
|
|
14
|
+
// ShapeKind ordinals used at the structural commit points.
|
|
15
|
+
const SHAPE_ADD = 2;
|
|
16
|
+
export class ArchetypeStore {
|
|
17
|
+
#deps;
|
|
18
|
+
byId = [];
|
|
19
|
+
#byHash = new Map();
|
|
20
|
+
#hotCount = 0;
|
|
21
|
+
cold = makeColdStore();
|
|
22
|
+
#initialRows;
|
|
23
|
+
/** archetypeCreated subscribers: tested against each new archetype once. */
|
|
24
|
+
#onCreated = [];
|
|
25
|
+
constructor(deps) {
|
|
26
|
+
this.#deps = deps;
|
|
27
|
+
// A new column reserves its address space from initialCapacity; never reserve past the world's
|
|
28
|
+
// mint ceiling or the resizable backing's maxByteLength is invalid for tiny maxEntities.
|
|
29
|
+
this.#initialRows = Math.max(1, Math.min(INITIAL_ROWS, deps.maxEntities));
|
|
30
|
+
// EMPTY_ARCHETYPE_ID = 0 is created eagerly so spawn always has a hot archetype to land in.
|
|
31
|
+
this.getOrCreateArchetype(canonicalize([]));
|
|
32
|
+
}
|
|
33
|
+
get hotCount() {
|
|
34
|
+
return this.#hotCount;
|
|
35
|
+
}
|
|
36
|
+
get emptyArchetype() {
|
|
37
|
+
return this.byId[EMPTY_ARCHETYPE_ID];
|
|
38
|
+
}
|
|
39
|
+
// --- (signature interning) ---------------------------
|
|
40
|
+
getOrCreateArchetype(sig) {
|
|
41
|
+
const h = sigHash(sig);
|
|
42
|
+
const bucket = this.#byHash.get(h);
|
|
43
|
+
if (bucket !== undefined) {
|
|
44
|
+
for (const a of bucket)
|
|
45
|
+
if (sigEquals(a.signature, sig))
|
|
46
|
+
return a;
|
|
47
|
+
}
|
|
48
|
+
return this.#createArchetype(sig, h);
|
|
49
|
+
}
|
|
50
|
+
#createArchetype(sig, hash) {
|
|
51
|
+
const id = this.byId.length;
|
|
52
|
+
const isCold = this.#hotCount >= this.#deps.maxHotArchetypes;
|
|
53
|
+
const arch = makeArchetype(id, sig, hash, this.#deps.stride, this.#deps.tick(), isCold);
|
|
54
|
+
if (!isCold) {
|
|
55
|
+
attachHotColumns(arch, {
|
|
56
|
+
buffers: this.#deps.buffers,
|
|
57
|
+
accessorWorld: this.#deps.accessorWorld,
|
|
58
|
+
initialCapacity: this.#initialRows,
|
|
59
|
+
defOf: (c) => this.#deps.defOf(c),
|
|
60
|
+
});
|
|
61
|
+
this.#hotCount += 1;
|
|
62
|
+
}
|
|
63
|
+
this.byId.push(arch);
|
|
64
|
+
let bucket = this.#byHash.get(hash);
|
|
65
|
+
if (bucket === undefined) {
|
|
66
|
+
bucket = [];
|
|
67
|
+
this.#byHash.set(hash, bucket);
|
|
68
|
+
}
|
|
69
|
+
bucket.push(arch);
|
|
70
|
+
// Each registered query AND-tests this new archetype's sigWords once and, on
|
|
71
|
+
// match, appends it to its matchingArchetypes. Emitted AFTER the archetype is fully interned.
|
|
72
|
+
for (const fn of this.#onCreated)
|
|
73
|
+
fn(arch);
|
|
74
|
+
return arch;
|
|
75
|
+
}
|
|
76
|
+
/** Subscribe to archetypeCreated. Serial-phase only. */
|
|
77
|
+
onArchetypeCreated(fn) {
|
|
78
|
+
this.#onCreated.push(fn);
|
|
79
|
+
}
|
|
80
|
+
// --- (both directions cached on a miss) ---------------
|
|
81
|
+
edgeAdd(arch, c) {
|
|
82
|
+
const e = arch.edges.get(c);
|
|
83
|
+
if (e !== undefined && e.add !== undefined)
|
|
84
|
+
return e.add;
|
|
85
|
+
const targetSig = sigWithAdded(arch.signature, c);
|
|
86
|
+
const target = this.getOrCreateArchetype(targetSig);
|
|
87
|
+
this.#setEdge(arch, c, 'add', target);
|
|
88
|
+
this.#setEdge(target, c, 'remove', arch);
|
|
89
|
+
return target;
|
|
90
|
+
}
|
|
91
|
+
edgeRemove(arch, c) {
|
|
92
|
+
const e = arch.edges.get(c);
|
|
93
|
+
if (e !== undefined && e.remove !== undefined)
|
|
94
|
+
return e.remove;
|
|
95
|
+
const targetSig = sigWithRemoved(arch.signature, c);
|
|
96
|
+
const target = this.getOrCreateArchetype(targetSig);
|
|
97
|
+
this.#setEdge(arch, c, 'remove', target);
|
|
98
|
+
this.#setEdge(target, c, 'add', arch);
|
|
99
|
+
return target;
|
|
100
|
+
}
|
|
101
|
+
#setEdge(arch, c, dir, target) {
|
|
102
|
+
let e = arch.edges.get(c);
|
|
103
|
+
if (e === undefined) {
|
|
104
|
+
e = {};
|
|
105
|
+
arch.edges.set(c, e);
|
|
106
|
+
}
|
|
107
|
+
e[dir] = target;
|
|
108
|
+
}
|
|
109
|
+
// --- / swap-pop removal ---------------------------------------
|
|
110
|
+
#ensureRowCapacity(arch, need) {
|
|
111
|
+
const rowsColumn = arch.rowsColumn;
|
|
112
|
+
if (rowsColumn === null)
|
|
113
|
+
return; // cold archetype: rows live in the overflow store
|
|
114
|
+
if (need > rowsColumn.capacity()) {
|
|
115
|
+
this.#deps.buffers.grow(rowsColumn, need);
|
|
116
|
+
arch.rows = rowsColumn.view;
|
|
117
|
+
}
|
|
118
|
+
for (const cs of arch.columnSets.values()) {
|
|
119
|
+
for (const col of cs.columns) {
|
|
120
|
+
if (need > col.capacity())
|
|
121
|
+
this.#deps.buffers.grow(col, need);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/** Reserve a row in `arch` for `handle`; records the occupant. Caller writes column values. */
|
|
126
|
+
allocRow(arch, handle) {
|
|
127
|
+
if (arch.cold)
|
|
128
|
+
return this.#coldAllocRow(arch, handle);
|
|
129
|
+
this.#ensureRowCapacity(arch, arch.count + 1);
|
|
130
|
+
const row = arch.count;
|
|
131
|
+
arch.rows[row] = handle >>> 0;
|
|
132
|
+
arch.count = row + 1;
|
|
133
|
+
arch.lastAccessTick = this.#deps.tick();
|
|
134
|
+
return row;
|
|
135
|
+
}
|
|
136
|
+
#coldAllocRow(arch, handle) {
|
|
137
|
+
const index = this.#deps.handleIndex(handle);
|
|
138
|
+
this.cold.archOf.set(index, arch.id);
|
|
139
|
+
this.cold.handleOf.set(index, handle >>> 0);
|
|
140
|
+
for (let i = 0; i < arch.signature.length; i++) {
|
|
141
|
+
const c = arch.signature[i];
|
|
142
|
+
// Cold rows are keyed per (entityIndex, componentId), NOT per archetype. A cold→cold migration
|
|
143
|
+
// that keeps a component must REUSE the entity's existing row for it — reallocating would orphan
|
|
144
|
+
// the prior value and the source-side reclaim would then delete the fresh mapping. Only allocate
|
|
145
|
+
// a row for a component the entity does not already hold.
|
|
146
|
+
if (coldRowOf(this.cold, index, c) >= 0)
|
|
147
|
+
continue;
|
|
148
|
+
coldAllocRow(this.cold, index, c, {
|
|
149
|
+
buffers: this.#deps.buffers,
|
|
150
|
+
accessorWorld: this.#deps.accessorWorld,
|
|
151
|
+
initialCapacity: this.#initialRows,
|
|
152
|
+
defOf: (cc) => this.#deps.defOf(cc),
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
// Cold rows are addressed per-component via cold.rowOf; the record stores the entityIndex itself
|
|
156
|
+
// as the "row" so resolveLocation round-trips through the cold store.
|
|
157
|
+
arch.count += 1;
|
|
158
|
+
arch.lastAccessTick = this.#deps.tick();
|
|
159
|
+
return index;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Swap-pop removal: move the last live row into `row`, then fix the moved sibling's record via
|
|
163
|
+
* the callback. `fixSibling` fires exactly once iff row !== count-1 (I6). Serial only.
|
|
164
|
+
*
|
|
165
|
+
*: when `relocateDying` is supplied (a remove-observer subscribes to a
|
|
166
|
+
* held component), the dying entity's column data must survive intact until after observerDrain so
|
|
167
|
+
* an onRemove handler can read its last value. Instead of a one-way overwrite of the dying row, we
|
|
168
|
+
* SWAP it with the last live row: the sibling's data lands in `row` (record fixed), and the dying
|
|
169
|
+
* entity's data lands at the now-excluded `last` slot (record relocated via `relocateDying`). The
|
|
170
|
+
* dying row is naturally reclaimed — it sits at/above `count`, outside every `[0,count)` iteration,
|
|
171
|
+
* and is overwritten by the next allocRow (which only happens next frame, since observer mutations
|
|
172
|
+
* stage to command buffers). For hot rows this needs no per-frame stale-row list.
|
|
173
|
+
*/
|
|
174
|
+
removeRow(arch, row, fixSibling, relocateDying) {
|
|
175
|
+
if (arch.cold) {
|
|
176
|
+
// Cold "row" is the entity index (the record row word for cold entities). Reclaim its
|
|
177
|
+
// overflow rows so blocks don't leak and stale (index,componentId) mappings can't survive a
|
|
178
|
+
// generational index reuse. Cold blocks are keyed per (entityIndex, componentId), so the dying
|
|
179
|
+
// entity's values are addressed by its own index and survive the count decrement regardless —
|
|
180
|
+
// the deferral concern (sibling overwrite) does not arise. Reclaim runs as usual.
|
|
181
|
+
coldReclaim(this.cold, row, arch.signature);
|
|
182
|
+
arch.count -= 1;
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const last = arch.count - 1;
|
|
186
|
+
if (row !== last) {
|
|
187
|
+
const defer = relocateDying !== undefined;
|
|
188
|
+
for (const cs of arch.columnSets.values()) {
|
|
189
|
+
for (const col of cs.columns) {
|
|
190
|
+
if (defer)
|
|
191
|
+
swapRowWithinColumn(col, last, row);
|
|
192
|
+
else
|
|
193
|
+
copyRowWithinColumn(col, last, row);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const movedHandle = arch.rows[last];
|
|
197
|
+
const dyingHandle = arch.rows[row];
|
|
198
|
+
arch.rows[row] = movedHandle;
|
|
199
|
+
fixSibling(this.#deps.handleIndex(movedHandle), row);
|
|
200
|
+
if (defer) {
|
|
201
|
+
// The dying entity's data now lives at `last`; keep its record pointing there so a leniently
|
|
202
|
+
// bound EntityRef reads its own pre-removal values during the drain.
|
|
203
|
+
arch.rows[last] = dyingHandle;
|
|
204
|
+
relocateDying(last);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
arch.count = last;
|
|
208
|
+
}
|
|
209
|
+
// ---
|
|
210
|
+
/** Move one entity from fromArch to toArch: K-shared copy + init-added + shuffle-pop + commit. */
|
|
211
|
+
migrate(handle, fromArch, toArch) {
|
|
212
|
+
const index = this.#deps.handleIndex(handle);
|
|
213
|
+
const oldRow = this.#deps.record.rowOf(index);
|
|
214
|
+
// Snapshot the source field locations BEFORE allocRow. A cold target reallocates this entity's
|
|
215
|
+
// per-type cold rows (cold.rowOf), which for a cold→cold migration would clobber the source row
|
|
216
|
+
// mapping of shared components before we copy them.
|
|
217
|
+
const srcLocs = new Map();
|
|
218
|
+
for (let i = 0; i < toArch.signature.length; i++) {
|
|
219
|
+
const c = toArch.signature[i];
|
|
220
|
+
if (!sigHas(fromArch.signature, c))
|
|
221
|
+
continue;
|
|
222
|
+
const src = this.#fieldLocation(fromArch, c, index, oldRow);
|
|
223
|
+
if (src !== null)
|
|
224
|
+
srcLocs.set(c, src);
|
|
225
|
+
}
|
|
226
|
+
const newRow = this.allocRow(toArch, handle);
|
|
227
|
+
// Shared-column copy: for every column-bearing component in the DESTINATION, copy
|
|
228
|
+
// its field values from the source (hot row OR cold block) or initialize if newly added. This
|
|
229
|
+
// holds in all four hot/cold combinations — the column-copy is NOT skipped for cold targets,
|
|
230
|
+
// which would silently drop shared field data.
|
|
231
|
+
for (let i = 0; i < toArch.signature.length; i++) {
|
|
232
|
+
const c = toArch.signature[i];
|
|
233
|
+
const dst = this.#fieldLocation(toArch, c, index, newRow);
|
|
234
|
+
if (dst === null)
|
|
235
|
+
continue; // tag / no def: pure membership, no columns
|
|
236
|
+
const src = srcLocs.get(c);
|
|
237
|
+
if (src !== undefined) {
|
|
238
|
+
for (let f = 0; f < dst.set.columns.length; f++) {
|
|
239
|
+
copyRowAcrossColumns(src.set.columns[f], src.row, dst.set.columns[f], dst.row);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
this.#initColumnRow(dst.set, dst.row, c);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// Removal reactivity for components in fromArch \ toArch, BEFORE the source row is overwritten.
|
|
247
|
+
for (let i = 0; i < fromArch.signature.length; i++) {
|
|
248
|
+
const c = fromArch.signature[i];
|
|
249
|
+
if (!sigHas(toArch.signature, c))
|
|
250
|
+
this.#deps.enqueueRemoveLog(index, c);
|
|
251
|
+
}
|
|
252
|
+
if (fromArch.cold) {
|
|
253
|
+
// Reclaim only the cold rows the entity no longer keeps in the COLD store: components removed
|
|
254
|
+
// outright, plus shared components that moved into a hot target's columns. Shared components
|
|
255
|
+
// that stay cold (cold→cold) retain their existing row (reused by #coldAllocRow above).
|
|
256
|
+
const toReclaim = [];
|
|
257
|
+
for (let i = 0; i < fromArch.signature.length; i++) {
|
|
258
|
+
const c = fromArch.signature[i];
|
|
259
|
+
const stillCold = sigHas(toArch.signature, c) && toArch.cold;
|
|
260
|
+
if (!stillCold)
|
|
261
|
+
toReclaim.push(c);
|
|
262
|
+
}
|
|
263
|
+
coldReclaim(this.cold, index, toReclaim, !toArch.cold);
|
|
264
|
+
fromArch.count -= 1;
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
this.removeRow(fromArch, oldRow, (movedIndex, newSrcRow) => {
|
|
268
|
+
this.#deps.record.commitRecord(movedIndex, fromArch.id, newSrcRow);
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
this.#deps.record.commitRecord(index, toArch.id, newRow);
|
|
272
|
+
this.#deps.bitmask.bitmaskApplyDelta(index, fromArch.signature, toArch.signature);
|
|
273
|
+
// /: one shape-log Add per component in toArch \ fromArch (NOT per copied
|
|
274
|
+
// column). Removes were emitted via enqueueRemoveLog above, before the source row was overwritten.
|
|
275
|
+
const trackShape = this.#deps.trackShape;
|
|
276
|
+
if (trackShape !== undefined) {
|
|
277
|
+
for (let i = 0; i < toArch.signature.length; i++) {
|
|
278
|
+
const c = toArch.signature[i];
|
|
279
|
+
if (!sigHas(fromArch.signature, c))
|
|
280
|
+
trackShape(index, c, SHAPE_ADD);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
// Re-test this one entity against the queries
|
|
284
|
+
// referencing each component in the symmetric difference (added OR removed). Runs AFTER the
|
|
285
|
+
// bitmask delta so matchesEntityNow sees the coherent post-migration shape.
|
|
286
|
+
const maintain = this.#deps.maintainEntity;
|
|
287
|
+
if (maintain !== undefined) {
|
|
288
|
+
for (let i = 0; i < toArch.signature.length; i++) {
|
|
289
|
+
const c = toArch.signature[i];
|
|
290
|
+
if (!sigHas(fromArch.signature, c))
|
|
291
|
+
maintain(index, c);
|
|
292
|
+
}
|
|
293
|
+
for (let i = 0; i < fromArch.signature.length; i++) {
|
|
294
|
+
const c = fromArch.signature[i];
|
|
295
|
+
if (!sigHas(toArch.signature, c))
|
|
296
|
+
maintain(index, c);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return newRow;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Resolve the (ColumnSet, row) holding component `c`'s fields for `index` in `arch`, whether hot
|
|
303
|
+
* (per-archetype columnSet, addressed by `hotRow`) or cold (per-type block, addressed by the
|
|
304
|
+
* entity's cold row). Returns null for tags / unregistered ids that carry no columns.
|
|
305
|
+
*/
|
|
306
|
+
#fieldLocation(arch, c, index, hotRow) {
|
|
307
|
+
if (arch.cold) {
|
|
308
|
+
const set = this.cold.blocks.get(c);
|
|
309
|
+
if (set === undefined)
|
|
310
|
+
return null;
|
|
311
|
+
const row = coldRowOf(this.cold, index, c);
|
|
312
|
+
if (row < 0)
|
|
313
|
+
return null;
|
|
314
|
+
return { set, row };
|
|
315
|
+
}
|
|
316
|
+
const set = arch.columnSets.get(c);
|
|
317
|
+
if (set === undefined)
|
|
318
|
+
return null;
|
|
319
|
+
return { set, row: hotRow };
|
|
320
|
+
}
|
|
321
|
+
#initColumnRow(cs, row, c) {
|
|
322
|
+
const def = this.#deps.defOf(c);
|
|
323
|
+
if (def === undefined)
|
|
324
|
+
return;
|
|
325
|
+
const rt = def;
|
|
326
|
+
let layoutIndex = 0;
|
|
327
|
+
let fieldIndex = 0;
|
|
328
|
+
for (const f of rt.fields) {
|
|
329
|
+
if (f.ctor === null) {
|
|
330
|
+
fieldIndex += 1;
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
const col = cs.columns[layoutIndex];
|
|
334
|
+
if (f.needsExplicitInit) {
|
|
335
|
+
const fill = col.layout.fillOnInit;
|
|
336
|
+
const base = row * col.layout.stride;
|
|
337
|
+
for (let a = 0; a < col.layout.stride; a++)
|
|
338
|
+
col.view[base + a] = fill;
|
|
339
|
+
}
|
|
340
|
+
// else: the column's zero-init already holds the intrinsic default.
|
|
341
|
+
layoutIndex += 1;
|
|
342
|
+
fieldIndex += 1;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
// --- /
|
|
346
|
+
/** entity.add(C): single-id add via the cached edge. */
|
|
347
|
+
migrateAdding(handle, c) {
|
|
348
|
+
const index = this.#deps.handleIndex(handle);
|
|
349
|
+
const fromArch = this.byId[this.#deps.record.archetypeIdOf(index)];
|
|
350
|
+
if (sigHas(fromArch.signature, c))
|
|
351
|
+
return this.#deps.record.rowOf(index); // idempotent
|
|
352
|
+
const toArch = this.edgeAdd(fromArch, c);
|
|
353
|
+
return this.migrate(handle, fromArch, toArch);
|
|
354
|
+
}
|
|
355
|
+
/** entity.remove(C): single-id remove via the cached edge. */
|
|
356
|
+
migrateRemoving(handle, c) {
|
|
357
|
+
const index = this.#deps.handleIndex(handle);
|
|
358
|
+
const fromArch = this.byId[this.#deps.record.archetypeIdOf(index)];
|
|
359
|
+
if (!sigHas(fromArch.signature, c))
|
|
360
|
+
return this.#deps.record.rowOf(index); // idempotent
|
|
361
|
+
const toArch = this.edgeRemove(fromArch, c);
|
|
362
|
+
return this.migrate(handle, fromArch, toArch);
|
|
363
|
+
}
|
|
364
|
+
/** Multi-id atomic add — ONE target signature, one migration (relations atomicity). */
|
|
365
|
+
migrateAddingMany(handle, addIds) {
|
|
366
|
+
const index = this.#deps.handleIndex(handle);
|
|
367
|
+
const fromArch = this.byId[this.#deps.record.archetypeIdOf(index)];
|
|
368
|
+
const effective = addIds.filter((c) => !sigHas(fromArch.signature, c));
|
|
369
|
+
if (effective.length === 0)
|
|
370
|
+
return this.#deps.record.rowOf(index);
|
|
371
|
+
const targetSig = canonicalize([...fromArch.signature, ...effective]);
|
|
372
|
+
const toArch = this.getOrCreateArchetype(targetSig);
|
|
373
|
+
return this.migrate(handle, fromArch, toArch);
|
|
374
|
+
}
|
|
375
|
+
/** Multi-id atomic remove — symmetric to migrateAddingMany. */
|
|
376
|
+
migrateRemovingMany(handle, removeIds) {
|
|
377
|
+
const index = this.#deps.handleIndex(handle);
|
|
378
|
+
const fromArch = this.byId[this.#deps.record.archetypeIdOf(index)];
|
|
379
|
+
const effective = removeIds.filter((c) => sigHas(fromArch.signature, c));
|
|
380
|
+
if (effective.length === 0)
|
|
381
|
+
return this.#deps.record.rowOf(index);
|
|
382
|
+
const removeSet = new Set(effective);
|
|
383
|
+
const kept = [];
|
|
384
|
+
for (let i = 0; i < fromArch.signature.length; i++) {
|
|
385
|
+
const c = fromArch.signature[i];
|
|
386
|
+
if (!removeSet.has(c))
|
|
387
|
+
kept.push(c);
|
|
388
|
+
}
|
|
389
|
+
const toArch = this.getOrCreateArchetype(canonicalize(kept));
|
|
390
|
+
return this.migrate(handle, fromArch, toArch);
|
|
391
|
+
}
|
|
392
|
+
/** spawnWith fast path: compute the target signature up front and migrate ONCE. */
|
|
393
|
+
spawnWith(handle, defs) {
|
|
394
|
+
const ids = [];
|
|
395
|
+
for (const d of defs)
|
|
396
|
+
ids.push(d.id);
|
|
397
|
+
const toArch = this.getOrCreateArchetype(canonicalize(ids));
|
|
398
|
+
return this.migrate(handle, this.emptyArchetype, toArch);
|
|
399
|
+
}
|
|
400
|
+
// ---
|
|
401
|
+
/** Promote a cold archetype (by signature) to hot: allocate columns, migrate its rows out. */
|
|
402
|
+
warm(sig) {
|
|
403
|
+
const arch = this.getOrCreateArchetype(sig);
|
|
404
|
+
if (!arch.cold)
|
|
405
|
+
return;
|
|
406
|
+
// Snapshot the resident cold entities BEFORE flipping the flag — their data lives in the shared
|
|
407
|
+
// overflow blocks keyed (entityIndex, componentId), addressed via cold.rowOf.
|
|
408
|
+
const residents = [];
|
|
409
|
+
for (const [entityIndex, archId] of this.cold.archOf) {
|
|
410
|
+
if (archId === arch.id)
|
|
411
|
+
residents.push(entityIndex);
|
|
412
|
+
}
|
|
413
|
+
attachHotColumns(arch, {
|
|
414
|
+
buffers: this.#deps.buffers,
|
|
415
|
+
accessorWorld: this.#deps.accessorWorld,
|
|
416
|
+
initialCapacity: this.#initialRows,
|
|
417
|
+
defOf: (c) => this.#deps.defOf(c),
|
|
418
|
+
});
|
|
419
|
+
arch.count = 0;
|
|
420
|
+
arch.cold = false;
|
|
421
|
+
this.#hotCount += 1;
|
|
422
|
+
// Migrate each resident out of the overflow store into a contiguous hot row, copying field
|
|
423
|
+
// values from the cold blocks, fixing its record, then reclaiming its cold rows.
|
|
424
|
+
for (const entityIndex of residents) {
|
|
425
|
+
const newRow = arch.count;
|
|
426
|
+
this.#ensureRowCapacity(arch, newRow + 1);
|
|
427
|
+
const handle = this.cold.handleOf.get(entityIndex) ?? entityIndex;
|
|
428
|
+
arch.rows[newRow] = handle >>> 0;
|
|
429
|
+
arch.count = newRow + 1;
|
|
430
|
+
for (let i = 0; i < arch.signature.length; i++) {
|
|
431
|
+
const c = arch.signature[i];
|
|
432
|
+
const dstSet = arch.columnSets.get(c);
|
|
433
|
+
if (dstSet === undefined)
|
|
434
|
+
continue;
|
|
435
|
+
const srcSet = this.cold.blocks.get(c);
|
|
436
|
+
const srcRow = coldRowOf(this.cold, entityIndex, c);
|
|
437
|
+
if (srcSet === undefined || srcRow < 0) {
|
|
438
|
+
this.#initColumnRow(dstSet, newRow, c);
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
for (let f = 0; f < dstSet.columns.length; f++) {
|
|
442
|
+
copyRowAcrossColumns(srcSet.columns[f], srcRow, dstSet.columns[f], newRow);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
coldReclaim(this.cold, entityIndex, arch.signature);
|
|
446
|
+
this.#deps.record.commitRecord(entityIndex, arch.id, newRow);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
/** Copy one row's stride elements from srcRow to dstRow within the SAME column. */
|
|
451
|
+
function copyRowWithinColumn(col, srcRow, dstRow) {
|
|
452
|
+
const s = col.layout.stride;
|
|
453
|
+
const v = col.view;
|
|
454
|
+
v.copyWithin(dstRow * s, srcRow * s, srcRow * s + s);
|
|
455
|
+
}
|
|
456
|
+
/** Swap two rows' stride elements within the same column. */
|
|
457
|
+
function swapRowWithinColumn(col, a, b) {
|
|
458
|
+
const s = col.layout.stride;
|
|
459
|
+
const v = col.view;
|
|
460
|
+
const ab = a * s;
|
|
461
|
+
const bb = b * s;
|
|
462
|
+
for (let i = 0; i < s; i++) {
|
|
463
|
+
const t = v[ab + i];
|
|
464
|
+
v[ab + i] = v[bb + i];
|
|
465
|
+
v[bb + i] = t;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
/** Copy one row from a source column to a same-layout destination column (cross-archetype). */
|
|
469
|
+
function copyRowAcrossColumns(src, srcRow, dst, dstRow) {
|
|
470
|
+
const s = src.layout.stride;
|
|
471
|
+
dst.view.set(src.view.subarray(srcRow * s, srcRow * s + s), dstRow * s);
|
|
472
|
+
}
|
|
473
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/storage/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ComponentDef, EntityHandle, FieldValue, Schema, SchemaOf } from '@ecsia/schema';
|
|
2
|
+
import { onAdd } from '../reactivity/index.js';
|
|
3
|
+
interface StableIndexWorld {
|
|
4
|
+
observe(term: ReturnType<typeof onAdd>, handler: (e: {
|
|
5
|
+
handle: EntityHandle;
|
|
6
|
+
read(def: unknown): unknown;
|
|
7
|
+
}) => void): {
|
|
8
|
+
dispose(): void;
|
|
9
|
+
};
|
|
10
|
+
decodeHandle(handle: EntityHandle): {
|
|
11
|
+
index: number;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export interface StableIndex<K> {
|
|
15
|
+
/** The entity currently holding stable id `k`, or undefined. */
|
|
16
|
+
get(k: K): EntityHandle | undefined;
|
|
17
|
+
/** Does some live entity hold `k`? */
|
|
18
|
+
has(k: K): boolean;
|
|
19
|
+
/** Stop observing and clear the index. */
|
|
20
|
+
dispose(): void;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Build a world-level `idField → entity` index over a component carrying a stable id field. Maintained
|
|
24
|
+
* via onAdd/onRemove: when the component is added, its id field is read and the entity recorded; when
|
|
25
|
+
* removed (or the entity despawned), the mapping is dropped. Last writer wins on collision.
|
|
26
|
+
*/
|
|
27
|
+
export declare function createStableIndex<C extends ComponentDef<Schema>, F extends keyof SchemaOf<C> & string>(world: StableIndexWorld, component: C, idField: F): StableIndex<FieldValue<SchemaOf<C>[F]>>;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=stable-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stable-index.d.ts","sourceRoot":"","sources":["../../src/util/stable-index.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAC7F,OAAO,EAAE,KAAK,EAAY,MAAM,wBAAwB,CAAA;AAExD,UAAU,gBAAgB;IACxB,OAAO,CACL,IAAI,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,EAC9B,OAAO,EAAE,CAAC,CAAC,EAAE;QAAE,MAAM,EAAE,YAAY,CAAC;QAAC,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAA;KAAE,KAAK,IAAI,GAC1E;QAAE,OAAO,IAAI,IAAI,CAAA;KAAE,CAAA;IACtB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CACtD;AAED,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,gEAAgE;IAChE,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,YAAY,GAAG,SAAS,CAAA;IACnC,sCAAsC;IACtC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,CAAA;IAClB,0CAA0C;IAC1C,OAAO,IAAI,IAAI,CAAA;CAChB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS,MAAM,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM,EACpG,KAAK,EAAE,gBAAgB,EACvB,SAAS,EAAE,CAAC,EACZ,OAAO,EAAE,CAAC,GACT,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAkCzC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// createStableIndex — a tiny core util mapping a user-meaningful stable id (typically a 'string' rich
|
|
2
|
+
// field) to the entity currently holding it. Built on world.observe(onAdd/onRemove);
|
|
3
|
+
// ids are NOT baked into entity identity. The index rebuilds itself after a snapshot load because the
|
|
4
|
+
// deserialize path re-adds components, firing onAdd for every re-created entity.
|
|
5
|
+
//
|
|
6
|
+
// onRemove fires at observerDrain AFTER the entity is despawned + its index generation bumped, so a
|
|
7
|
+
// rich-field read on the dying entity would hit the generation guard and return the DEFAULT. The
|
|
8
|
+
// byIndex cache (populated at onAdd) is the only reliable id source in onRemove — this is why the util
|
|
9
|
+
// sidesteps RF-REMOVE-READ entirely. The cache is keyed by entity INDEX (generation-stripped),
|
|
10
|
+
// because the handle an onRemove observer sees carries the bumped generation and would not match the
|
|
11
|
+
// onAdd handle.
|
|
12
|
+
import { onAdd, onRemove } from '../reactivity/index.js';
|
|
13
|
+
/**
|
|
14
|
+
* Build a world-level `idField → entity` index over a component carrying a stable id field. Maintained
|
|
15
|
+
* via onAdd/onRemove: when the component is added, its id field is read and the entity recorded; when
|
|
16
|
+
* removed (or the entity despawned), the mapping is dropped. Last writer wins on collision.
|
|
17
|
+
*/
|
|
18
|
+
export function createStableIndex(world, component, idField) {
|
|
19
|
+
const map = new Map();
|
|
20
|
+
const byIndex = new Map();
|
|
21
|
+
const indexOf = (h) => world.decodeHandle(h).index;
|
|
22
|
+
const add = world.observe(onAdd(component), (e) => {
|
|
23
|
+
const id = e.read(component)[idField];
|
|
24
|
+
map.set(id, e.handle);
|
|
25
|
+
byIndex.set(indexOf(e.handle), id);
|
|
26
|
+
});
|
|
27
|
+
const remove = world.observe(onRemove(component), (e) => {
|
|
28
|
+
// The handle here carries the BUMPED generation (despawn already ran), so it never equals the handle
|
|
29
|
+
// onAdd stored. Disambiguate by entity INDEX: only drop the mapping if it still points at this index
|
|
30
|
+
// (a re-add at the same index under a new id must not be clobbered by the prior tenant's removal).
|
|
31
|
+
const idx = indexOf(e.handle);
|
|
32
|
+
const id = byIndex.get(idx);
|
|
33
|
+
if (id !== undefined) {
|
|
34
|
+
const current = map.get(id);
|
|
35
|
+
if (current !== undefined && indexOf(current) === idx)
|
|
36
|
+
map.delete(id);
|
|
37
|
+
}
|
|
38
|
+
byIndex.delete(idx);
|
|
39
|
+
});
|
|
40
|
+
return {
|
|
41
|
+
get: (k) => map.get(k),
|
|
42
|
+
has: (k) => map.has(k),
|
|
43
|
+
dispose: () => {
|
|
44
|
+
add.dispose();
|
|
45
|
+
remove.dispose();
|
|
46
|
+
map.clear();
|
|
47
|
+
byIndex.clear();
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=stable-index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stable-index.js","sourceRoot":"","sources":["../../src/util/stable-index.ts"],"names":[],"mappings":"AAAA,sGAAsG;AACtG,qFAAqF;AACrF,sGAAsG;AACtG,iFAAiF;AACjF,EAAE;AACF,oGAAoG;AACpG,iGAAiG;AACjG,uGAAuG;AACvG,+FAA+F;AAC/F,qGAAqG;AACrG,gBAAgB;AAGhB,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAmBxD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAuB,EACvB,SAAY,EACZ,OAAU;IAGV,MAAM,GAAG,GAAG,IAAI,GAAG,EAAmB,CAAA;IACtC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAa,CAAA;IACpC,MAAM,OAAO,GAAG,CAAC,CAAe,EAAU,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;IAExE,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE;QAChD,MAAM,EAAE,GAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAA6B,CAAC,OAAO,CAAM,CAAA;QACvE,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAA;QACrB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAA;IACpC,CAAC,CAAC,CAAA;IACF,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B,EAAE,CAAC,CAAC,EAAE,EAAE;QAClF,qGAAqG;QACrG,qGAAqG;QACrG,mGAAmG;QACnG,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;QAC7B,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC3B,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YACrB,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YAC3B,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,GAAG;gBAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QACvE,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACrB,CAAC,CAAC,CAAA;IAEF,OAAO;QACL,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QACtB,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QACtB,OAAO,EAAE,GAAG,EAAE;YACZ,GAAG,CAAC,OAAO,EAAE,CAAA;YACb,MAAM,CAAC,OAAO,EAAE,CAAA;YAChB,GAAG,CAAC,KAAK,EAAE,CAAA;YACX,OAAO,CAAC,KAAK,EAAE,CAAA;QACjB,CAAC;KACF,CAAA;AACH,CAAC"}
|