@oasys/oecs 0.5.0 → 0.5.1
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/CHANGELOG.md +84 -1
- package/README.md +11 -7
- package/dist/core/ecs/archetype.d.cts +3 -3
- package/dist/core/ecs/archetype.d.ts +3 -3
- package/dist/core/ecs/component.d.cts +25 -0
- package/dist/core/ecs/component.d.ts +25 -0
- package/dist/core/ecs/component.d.ts.map +1 -1
- package/dist/core/ecs/ecs.d.cts +67 -49
- package/dist/core/ecs/ecs.d.ts +67 -49
- package/dist/core/ecs/ecs.d.ts.map +1 -1
- package/dist/core/ecs/entity.d.cts +1 -1
- package/dist/core/ecs/entity.d.ts +1 -1
- package/dist/core/ecs/facades.d.cts +1 -1
- package/dist/core/ecs/facades.d.ts +1 -1
- package/dist/core/ecs/host_commands.d.cts +30 -20
- package/dist/core/ecs/host_commands.d.ts +30 -20
- package/dist/core/ecs/host_commands.d.ts.map +1 -1
- package/dist/core/ecs/index.d.cts +3 -3
- package/dist/core/ecs/index.d.ts +3 -3
- package/dist/core/ecs/index.d.ts.map +1 -1
- package/dist/core/ecs/observer.d.cts +1 -1
- package/dist/core/ecs/observer.d.ts +1 -1
- package/dist/core/ecs/observer.d.ts.map +1 -1
- package/dist/core/ecs/query.d.cts +22 -6
- package/dist/core/ecs/query.d.ts +22 -6
- package/dist/core/ecs/query.d.ts.map +1 -1
- package/dist/core/ecs/ref.d.ts.map +1 -1
- package/dist/core/ecs/run_condition.d.cts +1 -1
- package/dist/core/ecs/run_condition.d.ts +1 -1
- package/dist/core/ecs/run_condition.d.ts.map +1 -1
- package/dist/core/ecs/store.d.cts +10 -23
- package/dist/core/ecs/store.d.ts +10 -23
- package/dist/core/ecs/store.d.ts.map +1 -1
- package/dist/dev_flag.d.cts +0 -15
- package/dist/dev_flag.d.ts +0 -15
- package/dist/dev_flag.d.ts.map +1 -1
- package/dist/extensions/editor/editor.d.cts +31 -29
- package/dist/extensions/editor/editor.d.ts +31 -29
- package/dist/extensions/editor/editor.d.ts.map +1 -1
- package/dist/extensions/editor/field_handle.d.cts +3 -3
- package/dist/extensions/editor/field_handle.d.ts +3 -3
- package/dist/extensions/editor/field_handle.d.ts.map +1 -1
- package/dist/extensions/editor/index.cjs +1 -1
- package/dist/extensions/editor/index.js +53 -51
- package/dist/{host_commands-i4cAeyL5.js → host_commands-BI8pEmjH.js} +26 -18
- package/dist/{host_commands-BF8QMi3c.cjs → host_commands-CxhpzMx9.cjs} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +269 -214
- package/dist/internal.cjs +1 -1
- package/dist/internal.js +1 -1
- package/dist/version.d.cts +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { v as dt, S as O, o as
|
|
2
|
-
import { aC as bn, aA as Cn, av as Sn, az as
|
|
1
|
+
import { v as dt, S as O, o as ht, p as at, q as ct, s as Jt, t as te, u as Ot, w as T, E as v, x as b, N as P, y as ee, z as w, U as I, A as pe, C as _e, F as ge, G as ye, I as me, j as J, J as Lt, R as Et, K as se, L as we, O as Ee, P as ve, Q as lt, T as ne, V as kt, W as re, X as ie, Y as vt, Z as be, _ as Ce, $ as it, a0 as Se, a1 as Re, a2 as et, a3 as Ie, a4 as Ae, a5 as Oe, a6 as ke, a7 as Nt, a8 as Te, a9 as Bt, aa as De, ab as ft, ac as xe, ad as Me, ae as M, af as Le, ag as Ft, ah as Y, k as $t, n as Ne, ai as V, aj as st, ak as Be, al as Fe, am as pt, an as $e, ao as Ge, ap as Pe, c as ut, r as Ue, aq as He, ar as Ve, as as qe, at as je, au as ze } from "./host_commands-BI8pEmjH.js";
|
|
2
|
+
import { aC as bn, aA as Cn, av as Sn, az as Rn, ax as In, aD as An, aB as On, aw as kn, ay as Tn } from "./host_commands-BI8pEmjH.js";
|
|
3
3
|
import { h as We, B as $, i as Ye, j as Qe } from "./typed_arrays-BcXcnzB4.js";
|
|
4
4
|
import { D as Ke, S as Gt, g as Xe } from "./shared-BU1Cd40h.js";
|
|
5
5
|
import { a as xn } from "./shared-BU1Cd40h.js";
|
|
@@ -16,13 +16,13 @@ function he(a) {
|
|
|
16
16
|
function Js(a, ...t) {
|
|
17
17
|
return { def: a, values: t[0] ?? Tt };
|
|
18
18
|
}
|
|
19
|
-
function
|
|
19
|
+
function j(a) {
|
|
20
20
|
return typeof a == "function" ? a : a.def;
|
|
21
21
|
}
|
|
22
|
-
function
|
|
22
|
+
function z(a) {
|
|
23
23
|
return typeof a == "function" ? Tt : a.values;
|
|
24
24
|
}
|
|
25
|
-
class
|
|
25
|
+
class Q extends Error {
|
|
26
26
|
constructor(t) {
|
|
27
27
|
super(t), this.name = "StoreRestoreError";
|
|
28
28
|
}
|
|
@@ -33,25 +33,25 @@ function Ze(a) {
|
|
|
33
33
|
}
|
|
34
34
|
function Je(a, t = Ke) {
|
|
35
35
|
const e = new DataView(a.buffer, a.byteOffset, a.byteLength);
|
|
36
|
-
if (a.byteLength <
|
|
37
|
-
throw new
|
|
38
|
-
`snapshot too small: ${a.byteLength} bytes (header alone needs ${
|
|
36
|
+
if (a.byteLength < ht)
|
|
37
|
+
throw new Q(
|
|
38
|
+
`snapshot too small: ${a.byteLength} bytes (header alone needs ${ht})`
|
|
39
39
|
);
|
|
40
40
|
const s = e.getUint32(O.magic, !0);
|
|
41
|
-
if (s !==
|
|
42
|
-
throw new
|
|
43
|
-
`bad magic: 0x${s.toString(16).padStart(8, "0")} (expected 0x${
|
|
41
|
+
if (s !== at)
|
|
42
|
+
throw new Q(
|
|
43
|
+
`bad magic: 0x${s.toString(16).padStart(8, "0")} (expected 0x${at.toString(16).padStart(8, "0")})`
|
|
44
44
|
);
|
|
45
45
|
const n = e.getUint32(O.sim_abi_version, !0);
|
|
46
|
-
if (n !==
|
|
47
|
-
throw new
|
|
48
|
-
`incompatible sim_abi_version: snapshot=${n}, build=${
|
|
46
|
+
if (n !== ct)
|
|
47
|
+
throw new Q(
|
|
48
|
+
`incompatible sim_abi_version: snapshot=${n}, build=${ct}`
|
|
49
49
|
);
|
|
50
50
|
const r = t(a.byteLength);
|
|
51
51
|
new Uint8Array(r).set(a);
|
|
52
52
|
const i = new DataView(r), o = Jt(i);
|
|
53
53
|
if (o.layoutDescriptorOff < 0 || o.layoutDescriptorOff > r.byteLength)
|
|
54
|
-
throw new
|
|
54
|
+
throw new Q(
|
|
55
55
|
`layout_descriptor_off ${o.layoutDescriptorOff} is outside the snapshot (${r.byteLength} bytes)`
|
|
56
56
|
);
|
|
57
57
|
try {
|
|
@@ -62,7 +62,7 @@ function Je(a, t = Ke) {
|
|
|
62
62
|
), c = Ot(r, h);
|
|
63
63
|
return { buffer: r, view: i, header: o, archetypes: c };
|
|
64
64
|
} catch (h) {
|
|
65
|
-
throw h instanceof RangeError ? new
|
|
65
|
+
throw h instanceof RangeError ? new Q(
|
|
66
66
|
`snapshot layout is corrupt or truncated: a descriptor offset or column extent reads past the ${r.byteLength}-byte buffer (${h.message})`
|
|
67
67
|
) : h;
|
|
68
68
|
}
|
|
@@ -228,7 +228,7 @@ class ns {
|
|
|
228
228
|
return this.map.has(t);
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
|
-
class
|
|
231
|
+
class nt extends Error {
|
|
232
232
|
capacity;
|
|
233
233
|
requested;
|
|
234
234
|
constructor(t, e) {
|
|
@@ -256,7 +256,7 @@ class rs {
|
|
|
256
256
|
* the next read/write. */
|
|
257
257
|
refreshView(t) {
|
|
258
258
|
if (t.length < this._len)
|
|
259
|
-
throw new
|
|
259
|
+
throw new nt(t.length, this._len);
|
|
260
260
|
this._buf = t, this._capacity = t.length;
|
|
261
261
|
}
|
|
262
262
|
get length() {
|
|
@@ -267,7 +267,7 @@ class rs {
|
|
|
267
267
|
}
|
|
268
268
|
push(t) {
|
|
269
269
|
if (this._len >= this._capacity)
|
|
270
|
-
throw new
|
|
270
|
+
throw new nt(this._capacity, this._len + 1);
|
|
271
271
|
this._buf[this._len++] = t;
|
|
272
272
|
}
|
|
273
273
|
pop() {
|
|
@@ -296,7 +296,7 @@ class rs {
|
|
|
296
296
|
* a fixed SAB view here — the mount already adopted the restored capacity). */
|
|
297
297
|
setLength(t) {
|
|
298
298
|
if (t > this._capacity)
|
|
299
|
-
throw new
|
|
299
|
+
throw new nt(this._capacity, t);
|
|
300
300
|
this._len = t;
|
|
301
301
|
}
|
|
302
302
|
/** Raw backing view. Stable for the lifetime of the SAB; views over a
|
|
@@ -325,7 +325,7 @@ class rs {
|
|
|
325
325
|
* across every archetype, which is the §6.1.4 invariant. */
|
|
326
326
|
ensureCapacity(t) {
|
|
327
327
|
if (t > this._capacity)
|
|
328
|
-
throw new
|
|
328
|
+
throw new nt(this._capacity, t);
|
|
329
329
|
}
|
|
330
330
|
/** Append `count` elements from `src[srcOffset..srcOffset+count]`.
|
|
331
331
|
* Throws on overrun. */
|
|
@@ -973,7 +973,7 @@ class Dt {
|
|
|
973
973
|
moveEntityFrom(t, e, s, n, r, i) {
|
|
974
974
|
const o = e >= t.enabledCount;
|
|
975
975
|
if (!this.materializesRows) {
|
|
976
|
-
t.removeRow(e, i), x[0] =
|
|
976
|
+
t.removeRow(e, i), x[0] = I, x[1] = P;
|
|
977
977
|
return;
|
|
978
978
|
}
|
|
979
979
|
const h = this._flatColumns;
|
|
@@ -1000,7 +1000,7 @@ class Dt {
|
|
|
1000
1000
|
moveEntityFromTag(t, e, s, n) {
|
|
1001
1001
|
const r = e >= t.enabledCount;
|
|
1002
1002
|
if (!this.materializesRows) {
|
|
1003
|
-
t.removeRow(e, n), x[0] =
|
|
1003
|
+
t.removeRow(e, n), x[0] = I, x[1] = P;
|
|
1004
1004
|
return;
|
|
1005
1005
|
}
|
|
1006
1006
|
const i = this.length;
|
|
@@ -1114,14 +1114,14 @@ function Ct(a, t) {
|
|
|
1114
1114
|
}
|
|
1115
1115
|
const ae = (a) => dt(
|
|
1116
1116
|
a
|
|
1117
|
-
),
|
|
1117
|
+
), K = Object.freeze([]);
|
|
1118
1118
|
function Ut(a) {
|
|
1119
1119
|
return typeof a == "object" && !Array.isArray(a);
|
|
1120
1120
|
}
|
|
1121
1121
|
function is(a) {
|
|
1122
|
-
let t =
|
|
1122
|
+
let t = K;
|
|
1123
1123
|
a.spawns !== void 0 && a.spawns.length > 0 && (t = a.spawns.map((s) => Ut(s) ? s.defs : s));
|
|
1124
|
-
let e =
|
|
1124
|
+
let e = K;
|
|
1125
1125
|
if (a.despawns !== void 0 && a.despawns.length > 0) {
|
|
1126
1126
|
const s = [];
|
|
1127
1127
|
for (const n of a.despawns)
|
|
@@ -1133,9 +1133,9 @@ function is(a) {
|
|
|
1133
1133
|
writes: a.writes,
|
|
1134
1134
|
spawns: t,
|
|
1135
1135
|
despawns: e,
|
|
1136
|
-
transitions: a.transitions ??
|
|
1137
|
-
resourceReads: a.resourceReads ??
|
|
1138
|
-
resourceWrites: a.resourceWrites ??
|
|
1136
|
+
transitions: a.transitions ?? K,
|
|
1137
|
+
resourceReads: a.resourceReads ?? K,
|
|
1138
|
+
resourceWrites: a.resourceWrites ?? K,
|
|
1139
1139
|
sparseReads: a.sparseReads,
|
|
1140
1140
|
sparseWrites: a.sparseWrites,
|
|
1141
1141
|
relationReads: a.relationReads,
|
|
@@ -1359,7 +1359,7 @@ class us {
|
|
|
1359
1359
|
/** Radix-sort `eids` by entity index (canonical within-observer order), then
|
|
1360
1360
|
* fire `fn` per entity under the observer's access scope. */
|
|
1361
1361
|
_fireEach(t, e, s, n) {
|
|
1362
|
-
|
|
1362
|
+
ot(s, this._radixOut, this._radixC0, this._radixC1);
|
|
1363
1363
|
try {
|
|
1364
1364
|
const r = L ? this.store._trace : null;
|
|
1365
1365
|
for (let i = 0; i < s.length; i++)
|
|
@@ -1398,7 +1398,7 @@ class us {
|
|
|
1398
1398
|
}
|
|
1399
1399
|
_dispatchSetEntity(t, e) {
|
|
1400
1400
|
let s = e.get(t.cid);
|
|
1401
|
-
if (s === void 0 && (s = this.store._takeDirty(t.cid),
|
|
1401
|
+
if (s === void 0 && (s = this.store._takeDirty(t.cid), ot(s, this._radixOut, this._radixC0, this._radixC1), e.set(t.cid, s)), s.length === 0) return;
|
|
1402
1402
|
const n = t.def, r = t.onSetEntity;
|
|
1403
1403
|
try {
|
|
1404
1404
|
for (let i = 0; i < s.length; i++) {
|
|
@@ -1424,7 +1424,7 @@ class us {
|
|
|
1424
1424
|
_yieldExisting(t) {
|
|
1425
1425
|
const e = t.onAdd, s = this.store._collectEntitiesWithComponent(t.cid);
|
|
1426
1426
|
if (s.length !== 0) {
|
|
1427
|
-
|
|
1427
|
+
ot(s, this._radixOut, this._radixC0, this._radixC1);
|
|
1428
1428
|
try {
|
|
1429
1429
|
for (let n = 0; n < s.length; n++) e(T(s[n]), this.ctx);
|
|
1430
1430
|
} finally {
|
|
@@ -1432,7 +1432,7 @@ class us {
|
|
|
1432
1432
|
}
|
|
1433
1433
|
}
|
|
1434
1434
|
}
|
|
1435
|
-
function
|
|
1435
|
+
function ot(a, t, e, s) {
|
|
1436
1436
|
const n = a.length;
|
|
1437
1437
|
if (!(n < 2)) {
|
|
1438
1438
|
t.length < n && (t.length = n), e.fill(0), s.fill(0);
|
|
@@ -1575,7 +1575,7 @@ class ds {
|
|
|
1575
1575
|
pairsOf(t) {
|
|
1576
1576
|
const e = this.relationOf(t), s = [], n = this.host.entityGenerations();
|
|
1577
1577
|
return e.forEachCanonicalPair(
|
|
1578
|
-
(r) =>
|
|
1578
|
+
(r) => J(r, n[r]),
|
|
1579
1579
|
(r, i) => s.push([r, i])
|
|
1580
1580
|
), s;
|
|
1581
1581
|
}
|
|
@@ -1636,25 +1636,25 @@ class ds {
|
|
|
1636
1636
|
const u = Array.from(l).sort((y, p) => y - p), d = this.host.sparseStores(), f = this.host.entityArchetype(), g = this.host.entityRow(), _ = this.host.archetypes();
|
|
1637
1637
|
for (let y = 0; y < u.length; y++) {
|
|
1638
1638
|
const p = T(u[y]), m = w(p), C = f[m];
|
|
1639
|
-
if (C ===
|
|
1639
|
+
if (C === I) continue;
|
|
1640
1640
|
const A = _[C], S = A.mask;
|
|
1641
1641
|
if (!S.contains(e) || s !== null && S.overlaps(s) || n !== null && !S.overlaps(n)) continue;
|
|
1642
|
-
let
|
|
1642
|
+
let R = !0;
|
|
1643
1643
|
for (let E = 0; E < r.length; E++)
|
|
1644
1644
|
if (!d[r[E]].has(m)) {
|
|
1645
|
-
|
|
1645
|
+
R = !1;
|
|
1646
1646
|
break;
|
|
1647
1647
|
}
|
|
1648
|
-
if (
|
|
1648
|
+
if (R) {
|
|
1649
1649
|
for (let E = 0; E < i.length; E++)
|
|
1650
1650
|
if (d[i[E]].has(m)) {
|
|
1651
|
-
|
|
1651
|
+
R = !1;
|
|
1652
1652
|
break;
|
|
1653
1653
|
}
|
|
1654
|
-
if (
|
|
1654
|
+
if (R) {
|
|
1655
1655
|
if (!o) {
|
|
1656
1656
|
const E = g[m];
|
|
1657
|
-
if (E !==
|
|
1657
|
+
if (E !== I && E >= A.enabledCount) continue;
|
|
1658
1658
|
}
|
|
1659
1659
|
h(p);
|
|
1660
1660
|
}
|
|
@@ -1842,7 +1842,7 @@ class ds {
|
|
|
1842
1842
|
(p) => d.push(p),
|
|
1843
1843
|
c
|
|
1844
1844
|
), d.length === 0) return;
|
|
1845
|
-
|
|
1845
|
+
ot(
|
|
1846
1846
|
d,
|
|
1847
1847
|
this._hierarchyRadixOut,
|
|
1848
1848
|
this._hierarchyRadixC0,
|
|
@@ -1958,7 +1958,7 @@ class fs {
|
|
|
1958
1958
|
);
|
|
1959
1959
|
t = this._highWater++, this._generations[t] = Lt, e = Lt, this._lengthView[0] = this._highWater;
|
|
1960
1960
|
}
|
|
1961
|
-
return this._aliveCount++, this.lastIndex = t,
|
|
1961
|
+
return this._aliveCount++, this.lastIndex = t, J(t, e);
|
|
1962
1962
|
}
|
|
1963
1963
|
/** Pre-check that `count` fresh slots fit, so a bulk-spawn commits
|
|
1964
1964
|
* all-or-nothing (#775): `alloc`'s own per-call guard would otherwise
|
|
@@ -2127,8 +2127,8 @@ function le(a, t) {
|
|
|
2127
2127
|
}
|
|
2128
2128
|
function _s(a) {
|
|
2129
2129
|
const t = {};
|
|
2130
|
-
for (let n = 0; n <
|
|
2131
|
-
const r =
|
|
2130
|
+
for (let n = 0; n < lt.length; n++) {
|
|
2131
|
+
const r = lt[n], i = a.view.getUint32(O[r.headerOff], !0);
|
|
2132
2132
|
i !== 0 && r.readOptions(a.view, i, t);
|
|
2133
2133
|
}
|
|
2134
2134
|
const e = ne(a.view);
|
|
@@ -2150,8 +2150,8 @@ function _s(a) {
|
|
|
2150
2150
|
}
|
|
2151
2151
|
function gs(a) {
|
|
2152
2152
|
const t = /* @__PURE__ */ new Map();
|
|
2153
|
-
for (let n = 0; n <
|
|
2154
|
-
const r =
|
|
2153
|
+
for (let n = 0; n < lt.length; n++) {
|
|
2154
|
+
const r = lt[n], i = a.view.getUint32(O[r.headerOff], !0);
|
|
2155
2155
|
if (i === 0) continue;
|
|
2156
2156
|
const o = r.regionBytes(a.view, i);
|
|
2157
2157
|
t.set(r.headerOff, new Uint8Array(a.buffer, i, o).slice());
|
|
@@ -2229,8 +2229,8 @@ function Es(a, t, e) {
|
|
|
2229
2229
|
for (let p = 0; p < t.length; p++) {
|
|
2230
2230
|
const m = t[p], C = a.archetypes.get(m.archetypeId), A = i.get(m.archetypeId);
|
|
2231
2231
|
for (let S = 0; S < C.columnsInOrder.length; S++) {
|
|
2232
|
-
const
|
|
2233
|
-
E > 0 && c.copyWithin(A.columns[S].byteOff,
|
|
2232
|
+
const R = C.columnsInOrder[S], E = m.rowCount * R.stride;
|
|
2233
|
+
E > 0 && c.copyWithin(A.columns[S].byteOff, R.byteOff, R.byteOff + E);
|
|
2234
2234
|
}
|
|
2235
2235
|
}
|
|
2236
2236
|
let l = e;
|
|
@@ -2444,18 +2444,18 @@ function Cs(a, t, e, s) {
|
|
|
2444
2444
|
_reservedDescriptorBytes: a._reservedDescriptorBytes
|
|
2445
2445
|
}, oldViewStamp: l, newViewStamp: d, viewsPreserved: !0 };
|
|
2446
2446
|
}
|
|
2447
|
-
const
|
|
2447
|
+
const Rt = 810766935, It = 1;
|
|
2448
2448
|
class k extends Error {
|
|
2449
2449
|
constructor(t) {
|
|
2450
2450
|
super(t), this.name = "ECSRestoreError";
|
|
2451
2451
|
}
|
|
2452
2452
|
}
|
|
2453
|
-
const
|
|
2453
|
+
const W = 4;
|
|
2454
2454
|
function Ss(a) {
|
|
2455
|
-
const t = a.freeIndices.length, e = a.archetypeRows.length, s =
|
|
2455
|
+
const t = a.freeIndices.length, e = a.archetypeRows.length, s = W * (4 + t + 1 + e * 3), n = new Uint8Array(s), r = new DataView(n.buffer);
|
|
2456
2456
|
let i = 0;
|
|
2457
2457
|
const o = (h) => {
|
|
2458
|
-
r.setUint32(i, h, !0), i +=
|
|
2458
|
+
r.setUint32(i, h, !0), i += W;
|
|
2459
2459
|
};
|
|
2460
2460
|
o(a.tick), o(a.entityHighWater), o(a.entityAliveCount), o(t);
|
|
2461
2461
|
for (let h = 0; h < t; h++) o(a.freeIndices[h]);
|
|
@@ -2466,7 +2466,7 @@ function Ss(a) {
|
|
|
2466
2466
|
}
|
|
2467
2467
|
return n;
|
|
2468
2468
|
}
|
|
2469
|
-
function
|
|
2469
|
+
function Rs(a) {
|
|
2470
2470
|
const t = new DataView(a.buffer, a.byteOffset, a.byteLength), e = a.byteLength;
|
|
2471
2471
|
let s = 0;
|
|
2472
2472
|
const n = (f) => {
|
|
@@ -2475,9 +2475,9 @@ function Is(a) {
|
|
|
2475
2475
|
`host-state truncated: need ${f} more bytes at offset ${s}, have ${e - s}`
|
|
2476
2476
|
);
|
|
2477
2477
|
}, r = () => {
|
|
2478
|
-
n(
|
|
2478
|
+
n(W);
|
|
2479
2479
|
const f = t.getUint32(s, !0);
|
|
2480
|
-
return s +=
|
|
2480
|
+
return s += W, f;
|
|
2481
2481
|
}, i = r(), o = r(), h = r(), c = r(), l = new Array(c);
|
|
2482
2482
|
for (let f = 0; f < c; f++) l[f] = r();
|
|
2483
2483
|
const u = r(), d = new Array(u);
|
|
@@ -2491,25 +2491,25 @@ function Is(a) {
|
|
|
2491
2491
|
);
|
|
2492
2492
|
return { tick: i, entityHighWater: o, entityAliveCount: h, freeIndices: l, archetypeRows: d };
|
|
2493
2493
|
}
|
|
2494
|
-
function
|
|
2495
|
-
const s =
|
|
2496
|
-
return r.setUint32(0,
|
|
2494
|
+
function Is(a, t, e) {
|
|
2495
|
+
const s = W * 5, n = new Uint8Array(s + a.length + t.length + e.length), r = new DataView(n.buffer);
|
|
2496
|
+
return r.setUint32(0, Rt, !0), r.setUint32(4, It, !0), r.setUint32(8, a.length, !0), r.setUint32(12, t.length, !0), r.setUint32(16, e.length, !0), n.set(a, s), n.set(t, s + a.length), n.set(e, s + a.length + t.length), n;
|
|
2497
2497
|
}
|
|
2498
2498
|
function As(a) {
|
|
2499
|
-
const t =
|
|
2499
|
+
const t = W * 5;
|
|
2500
2500
|
if (a.byteLength < t)
|
|
2501
2501
|
throw new k(
|
|
2502
2502
|
`world snapshot too small: ${a.byteLength} bytes (frame header needs ${t})`
|
|
2503
2503
|
);
|
|
2504
2504
|
const e = new DataView(a.buffer, a.byteOffset, a.byteLength), s = e.getUint32(0, !0);
|
|
2505
|
-
if (s !==
|
|
2505
|
+
if (s !== Rt)
|
|
2506
2506
|
throw new k(
|
|
2507
|
-
`bad world-snapshot magic: 0x${s.toString(16).padStart(8, "0")} (expected 0x${
|
|
2507
|
+
`bad world-snapshot magic: 0x${s.toString(16).padStart(8, "0")} (expected 0x${Rt.toString(16).padStart(8, "0")}). A bare dense (SAB) snapshot is not a combined world snapshot — pass the bytes from ECS.snapshot(), not snapshotColumnStore().`
|
|
2508
2508
|
);
|
|
2509
2509
|
const n = e.getUint32(4, !0);
|
|
2510
|
-
if (n !==
|
|
2510
|
+
if (n !== It)
|
|
2511
2511
|
throw new k(
|
|
2512
|
-
`incompatible world-snapshot version: snapshot=${n}, build=${
|
|
2512
|
+
`incompatible world-snapshot version: snapshot=${n}, build=${It}`
|
|
2513
2513
|
);
|
|
2514
2514
|
const r = e.getUint32(8, !0), i = e.getUint32(12, !0), o = e.getUint32(16, !0);
|
|
2515
2515
|
if (t + r + i + o !== a.byteLength)
|
|
@@ -2524,19 +2524,19 @@ function As(a) {
|
|
|
2524
2524
|
};
|
|
2525
2525
|
}
|
|
2526
2526
|
function Os(a, t, e) {
|
|
2527
|
-
if (a.byteLength <
|
|
2527
|
+
if (a.byteLength < ht)
|
|
2528
2528
|
throw new k(
|
|
2529
|
-
`dense section too small: ${a.byteLength} bytes (SAB header needs ${
|
|
2529
|
+
`dense section too small: ${a.byteLength} bytes (SAB header needs ${ht})`
|
|
2530
2530
|
);
|
|
2531
2531
|
const s = new DataView(a.buffer, a.byteOffset, a.byteLength), n = s.getUint32(O.magic, !0);
|
|
2532
|
-
if (n !==
|
|
2532
|
+
if (n !== at)
|
|
2533
2533
|
throw new k(
|
|
2534
|
-
`dense section bad magic: 0x${n.toString(16).padStart(8, "0")} (expected SAB magic 0x${
|
|
2534
|
+
`dense section bad magic: 0x${n.toString(16).padStart(8, "0")} (expected SAB magic 0x${at.toString(16).padStart(8, "0")})`
|
|
2535
2535
|
);
|
|
2536
2536
|
const r = s.getUint32(O.sim_abi_version, !0);
|
|
2537
|
-
if (r !==
|
|
2537
|
+
if (r !== ct)
|
|
2538
2538
|
throw new k(
|
|
2539
|
-
`dense section incompatible sim_abi_version: snapshot=${r}, build=${
|
|
2539
|
+
`dense section incompatible sim_abi_version: snapshot=${r}, build=${ct}`
|
|
2540
2540
|
);
|
|
2541
2541
|
const i = Jt(s);
|
|
2542
2542
|
if (i.layoutDescriptorOff < 0 || i.layoutDescriptorOff > a.byteLength)
|
|
@@ -2548,7 +2548,7 @@ function Os(a, t, e) {
|
|
|
2548
2548
|
throw new k(
|
|
2549
2549
|
`dense entityIndexOff ${o} is outside the section (${a.byteLength} bytes)`
|
|
2550
2550
|
);
|
|
2551
|
-
const h = s.getUint32(o +
|
|
2551
|
+
const h = s.getUint32(o + it.capacity, !0);
|
|
2552
2552
|
if (h !== e)
|
|
2553
2553
|
throw new k(
|
|
2554
2554
|
`entity-index capacity mismatch: live=${e}, snapshot=${h}`
|
|
@@ -2614,7 +2614,7 @@ class Ts {
|
|
|
2614
2614
|
* different orders snapshot byte-for-byte the same (#470). The reverse index
|
|
2615
2615
|
* is derived and never serialized — `restoreSparse` rebuilds it. */
|
|
2616
2616
|
snapshotSparse() {
|
|
2617
|
-
const t = Se(this.host.sparseStores()), e =
|
|
2617
|
+
const t = Se(this.host.sparseStores()), e = Re(this.host.relationStores()), s = new Uint8Array(8 + t.length + e.length), n = new DataView(s.buffer);
|
|
2618
2618
|
return n.setUint32(0, t.length, !0), n.setUint32(4, e.length, !0), s.set(t, 8), s.set(e, 8 + t.length), s;
|
|
2619
2619
|
}
|
|
2620
2620
|
/** Repopulate the sparse stores from `snapshotSparse` bytes, replacing all
|
|
@@ -2629,15 +2629,15 @@ class Ts {
|
|
|
2629
2629
|
restoreSparse(t) {
|
|
2630
2630
|
const e = new DataView(t.buffer, t.byteOffset, t.byteLength);
|
|
2631
2631
|
if (t.byteLength < 8)
|
|
2632
|
-
throw new
|
|
2632
|
+
throw new et(
|
|
2633
2633
|
`sparse snapshot truncated: need 8 header bytes, have ${t.byteLength}`
|
|
2634
2634
|
);
|
|
2635
2635
|
const s = e.getUint32(0, !0), n = e.getUint32(4, !0);
|
|
2636
2636
|
if (8 + s + n !== t.byteLength)
|
|
2637
|
-
throw new
|
|
2637
|
+
throw new et(
|
|
2638
2638
|
`sparse snapshot frame mismatch: header declares 8+${s}+${n}=${8 + s + n} bytes, buffer is ${t.byteLength}`
|
|
2639
2639
|
);
|
|
2640
|
-
|
|
2640
|
+
Ie(this.host.sparseStores(), t.subarray(8, 8 + s)), this.rebuildRelationIndices(t.subarray(8 + s, 8 + s + n));
|
|
2641
2641
|
}
|
|
2642
2642
|
/** Rebuild every relation's derived side indices after the sparse stores have
|
|
2643
2643
|
* been restored. `restoreRelations` resets all relations, rebuilds the multi
|
|
@@ -2646,7 +2646,7 @@ class Ts {
|
|
|
2646
2646
|
* so it's rebuilt here from the backing sparse store: every member row holds
|
|
2647
2647
|
* `(source index → target EntityID)`, which is exactly one reverse edge. */
|
|
2648
2648
|
rebuildRelationIndices(t) {
|
|
2649
|
-
const e = this.host.generations(), s = (r) =>
|
|
2649
|
+
const e = this.host.generations(), s = (r) => J(r, e[r]), n = this.host.relationStores();
|
|
2650
2650
|
Ae(n, t, s);
|
|
2651
2651
|
for (let r = 0; r < n.length; r++) n[r].rebuildReverseFromForward(s);
|
|
2652
2652
|
}
|
|
@@ -2657,7 +2657,7 @@ class Ts {
|
|
|
2657
2657
|
snapshot() {
|
|
2658
2658
|
this.host.publishRowCounts();
|
|
2659
2659
|
const t = new Uint8Array(Ze(this.host.columnStore())), e = this.snapshotSparse(), s = Ss(this.collectHostState());
|
|
2660
|
-
return
|
|
2660
|
+
return Is(t, e, s);
|
|
2661
2661
|
}
|
|
2662
2662
|
/** Gather the host-side state a snapshot carries alongside the dense + sparse
|
|
2663
2663
|
* bytes — see `snapshot()`. The free-list is copied (it's a live mutable). */
|
|
@@ -2683,7 +2683,7 @@ class Ts {
|
|
|
2683
2683
|
* ticking. Fails closed on a malformed frame or a registration mismatch
|
|
2684
2684
|
* BEFORE any live state is touched. */
|
|
2685
2685
|
restoreInto(t) {
|
|
2686
|
-
const e = As(t), s =
|
|
2686
|
+
const e = As(t), s = Rs(e.host);
|
|
2687
2687
|
Os(
|
|
2688
2688
|
e.dense,
|
|
2689
2689
|
this.host.columnStore().archetypes,
|
|
@@ -2703,12 +2703,12 @@ class Ts {
|
|
|
2703
2703
|
assertSparseSectionMatches(t) {
|
|
2704
2704
|
const e = new DataView(t.buffer, t.byteOffset, t.byteLength);
|
|
2705
2705
|
if (t.byteLength < 8)
|
|
2706
|
-
throw new
|
|
2706
|
+
throw new et(
|
|
2707
2707
|
`sparse snapshot truncated: need 8 header bytes, have ${t.byteLength}`
|
|
2708
2708
|
);
|
|
2709
2709
|
const s = e.getUint32(0, !0), n = e.getUint32(4, !0);
|
|
2710
2710
|
if (8 + s + n !== t.byteLength)
|
|
2711
|
-
throw new
|
|
2711
|
+
throw new et(
|
|
2712
2712
|
`sparse snapshot frame mismatch: header declares 8+${s}+${n}=${8 + s + n} bytes, buffer is ${t.byteLength}`
|
|
2713
2713
|
);
|
|
2714
2714
|
Oe(this.host.sparseStores(), t.subarray(8, 8 + s));
|
|
@@ -3252,7 +3252,7 @@ class Ls {
|
|
|
3252
3252
|
s.generations,
|
|
3253
3253
|
new Uint32Array(
|
|
3254
3254
|
this._columnStore.buffer,
|
|
3255
|
-
this._columnStore.header.entityIndexOff +
|
|
3255
|
+
this._columnStore.header.entityIndexOff + it.length,
|
|
3256
3256
|
1
|
|
3257
3257
|
)
|
|
3258
3258
|
), this._snapshots = new Ts(
|
|
@@ -3352,7 +3352,7 @@ class Ls {
|
|
|
3352
3352
|
const t = this._columnStore.view.getUint32(O.entity_index_off, !0), e = Bt(this._columnStore.buffer, t, this._entityIndexCapacity);
|
|
3353
3353
|
this.entityArchetype = e.archetypes, this.entityRow = e.rows, this.entityAllocator.replantViews(
|
|
3354
3354
|
e.generations,
|
|
3355
|
-
new Uint32Array(this._columnStore.buffer, t +
|
|
3355
|
+
new Uint32Array(this._columnStore.buffer, t + it.length, 1)
|
|
3356
3356
|
);
|
|
3357
3357
|
}
|
|
3358
3358
|
/** Centralised "SAB was just reallocated" handler. Refreshes the
|
|
@@ -3638,7 +3638,7 @@ class Ls {
|
|
|
3638
3638
|
// =======================================================
|
|
3639
3639
|
createEntity() {
|
|
3640
3640
|
const t = this.entityAllocator.alloc(), e = this.entityAllocator.lastIndex;
|
|
3641
|
-
return this.entityArchetype[e] = this.emptyArchetypeId, this.entityRow[e] =
|
|
3641
|
+
return this.entityArchetype[e] = this.emptyArchetypeId, this.entityRow[e] = I, t;
|
|
3642
3642
|
}
|
|
3643
3643
|
// =======================================================
|
|
3644
3644
|
// Template / direct-spawn (#462)
|
|
@@ -3691,7 +3691,7 @@ class Ls {
|
|
|
3691
3691
|
b.COMPONENT_NOT_REGISTERED,
|
|
3692
3692
|
`template: component ${c} is not registered`
|
|
3693
3693
|
);
|
|
3694
|
-
const u = t[h].values ??
|
|
3694
|
+
const u = t[h].values ?? Y, d = n._colOffset[c];
|
|
3695
3695
|
for (let f = 0; f < l.fieldNames.length; f++) {
|
|
3696
3696
|
const g = l.fieldNames[f];
|
|
3697
3697
|
r[d + f] = u[g] ?? 0, i.set(g, i.has(g) ? jt : d + f);
|
|
@@ -3734,7 +3734,7 @@ class Ls {
|
|
|
3734
3734
|
s.materializesRows && s.ensureRowCapacity(1);
|
|
3735
3735
|
const n = this._allocEntity(), r = this.entityAllocator.lastIndex;
|
|
3736
3736
|
if (!s.materializesRows)
|
|
3737
|
-
return this.entityArchetype[r] = t.archetypeId, this.entityRow[r] =
|
|
3737
|
+
return this.entityArchetype[r] = t.archetypeId, this.entityRow[r] = I, n;
|
|
3738
3738
|
const i = s.length, o = s.enabledCount, h = s.addEntityWithValues(n, t.flatValues, this._tick, this.entityRow);
|
|
3739
3739
|
return e !== void 0 && this._applyOverrides(s, h, t, e), this.entityArchetype[r] = t.archetypeId, this.entityRow[r] = h, this._onArchGrow(s, i, o), n;
|
|
3740
3740
|
}
|
|
@@ -3755,7 +3755,7 @@ class Ls {
|
|
|
3755
3755
|
if (!n.materializesRows) {
|
|
3756
3756
|
for (let d = 0; d < e; d++) {
|
|
3757
3757
|
const f = w(r[d]);
|
|
3758
|
-
o[f] = t.archetypeId, h[f] =
|
|
3758
|
+
o[f] = t.archetypeId, h[f] = I;
|
|
3759
3759
|
}
|
|
3760
3760
|
return r;
|
|
3761
3761
|
}
|
|
@@ -3809,11 +3809,11 @@ class Ls {
|
|
|
3809
3809
|
* must have already confirmed `id` is alive. */
|
|
3810
3810
|
_destroyOne(t, e) {
|
|
3811
3811
|
const s = w(t), n = this.entityRow[s];
|
|
3812
|
-
if (n !==
|
|
3812
|
+
if (n !== I) {
|
|
3813
3813
|
const r = this.archGet(this.entityArchetype[s]), i = r.length;
|
|
3814
3814
|
r.removeRow(n, this.entityRow), this._onArchLenChange(r, i);
|
|
3815
3815
|
}
|
|
3816
|
-
this.entityArchetype[s] =
|
|
3816
|
+
this.entityArchetype[s] = I, this.entityRow[s] = I, this.relationService.count > 0 && (this.relationService.purgeSource(t), e !== null && this.relationService.cleanupTarget(t, e)), this.sparseStores.length > 0 && this._purgeSparse(s), this._anyDirtyTracked && this._clearDirtyForIndex(s), this.entityAllocator.recycle(s, $t(t));
|
|
3817
3817
|
}
|
|
3818
3818
|
/**
|
|
3819
3819
|
* Liveness check, **fail-closed** against forged / retired / out-of-bounds
|
|
@@ -3923,7 +3923,7 @@ class Ls {
|
|
|
3923
3923
|
if (!this.isAlive(t))
|
|
3924
3924
|
return;
|
|
3925
3925
|
const e = w(t), s = this.entityRow[e];
|
|
3926
|
-
if (s ===
|
|
3926
|
+
if (s === I)
|
|
3927
3927
|
return;
|
|
3928
3928
|
const n = this.archGet(this.entityArchetype[e]);
|
|
3929
3929
|
if (s >= n.enabledCount) return;
|
|
@@ -3935,7 +3935,7 @@ class Ls {
|
|
|
3935
3935
|
if (!this.isAlive(t))
|
|
3936
3936
|
return;
|
|
3937
3937
|
const e = w(t), s = this.entityRow[e];
|
|
3938
|
-
if (s ===
|
|
3938
|
+
if (s === I) return;
|
|
3939
3939
|
const n = this.archGet(this.entityArchetype[e]);
|
|
3940
3940
|
if (s < n.enabledCount) return;
|
|
3941
3941
|
const r = n.enabledCount;
|
|
@@ -3947,7 +3947,7 @@ class Ls {
|
|
|
3947
3947
|
if (!this.isAlive(t))
|
|
3948
3948
|
return !1;
|
|
3949
3949
|
const e = w(t), s = this.entityRow[e];
|
|
3950
|
-
if (s ===
|
|
3950
|
+
if (s === I) return !1;
|
|
3951
3951
|
const n = this.archGet(this.entityArchetype[e]);
|
|
3952
3952
|
return s >= n.enabledCount;
|
|
3953
3953
|
}
|
|
@@ -4039,7 +4039,7 @@ class Ls {
|
|
|
4039
4039
|
* nothing and is skipped. */
|
|
4040
4040
|
_collectToggle(t, e) {
|
|
4041
4041
|
const s = w(t);
|
|
4042
|
-
if (this.entityRow[s] ===
|
|
4042
|
+
if (this.entityRow[s] === I) return;
|
|
4043
4043
|
const n = this.archGet(this.entityArchetype[s]);
|
|
4044
4044
|
this._collectToggleEid = t, n.mask.forEach(e ? this._collectDisableBit : this._collectEnableBit);
|
|
4045
4045
|
}
|
|
@@ -4076,11 +4076,11 @@ class Ls {
|
|
|
4076
4076
|
const y = t[_], p = y & V, m = y >> pt;
|
|
4077
4077
|
if (p >= o || r[p] !== m) continue;
|
|
4078
4078
|
const C = n[p];
|
|
4079
|
-
if (C !==
|
|
4079
|
+
if (C !== I) {
|
|
4080
4080
|
const A = i[s[p]];
|
|
4081
4081
|
g && (this._collectDestroyEid = y, A.mask.forEach(this._collectDestroyRemoveBit)), A.removeRow(C, n), h = !0, A.length === 0 && (c = !0);
|
|
4082
4082
|
}
|
|
4083
|
-
u && this.relationService.purgeSource(y), d && this.relationService.cleanupTarget(y, t), l && this._purgeSparse(p), f && this._clearDirtyForIndex(p), s[p] =
|
|
4083
|
+
u && this.relationService.purgeSource(y), d && this.relationService.cleanupTarget(y, t), l && this._purgeSparse(p), f && this._clearDirtyForIndex(p), s[p] = I, n[p] = I, e.recycle(p, m);
|
|
4084
4084
|
}
|
|
4085
4085
|
t.length = 0, h && (this._rowCountsDirty = !0, c && this._queryDirtyEpoch++);
|
|
4086
4086
|
}
|
|
@@ -4088,7 +4088,7 @@ class Ls {
|
|
|
4088
4088
|
return this._deferred.destroyCount;
|
|
4089
4089
|
}
|
|
4090
4090
|
addComponentDeferred(t, e, s) {
|
|
4091
|
-
this._deferred.queueAdd(t, e, s ??
|
|
4091
|
+
this._deferred.queueAdd(t, e, s ?? Y);
|
|
4092
4092
|
}
|
|
4093
4093
|
removeComponentDeferred(t, e) {
|
|
4094
4094
|
this._deferred.queueRemove(t, e);
|
|
@@ -4107,25 +4107,25 @@ class Ls {
|
|
|
4107
4107
|
for (let y = 0; y < n; y++) {
|
|
4108
4108
|
const p = t[y], m = p & V, C = p >> pt;
|
|
4109
4109
|
if (m >= l || o[m] !== C) continue;
|
|
4110
|
-
const A = r[m], S = e[y].id,
|
|
4111
|
-
if (
|
|
4112
|
-
E.fieldNames.length > 0 &&
|
|
4110
|
+
const A = r[m], S = e[y].id, R = h[A], E = c[S];
|
|
4111
|
+
if (R.mask.has(S)) {
|
|
4112
|
+
E.fieldNames.length > 0 && R.writeFields(i[m], S, s[y], u);
|
|
4113
4113
|
continue;
|
|
4114
4114
|
}
|
|
4115
|
-
const N = this.archResolveAdd(A, S), D = h[N], H = i[m], Mt = !D.hasColumns && !
|
|
4116
|
-
H !==
|
|
4117
|
-
let
|
|
4118
|
-
if (H !==
|
|
4115
|
+
const N = this.archResolveAdd(A, S), D = h[N], H = i[m], Mt = !D.hasColumns && !R.hasColumns;
|
|
4116
|
+
H !== I && R._flushSeenEpoch !== d && (R._flushSeenEpoch = d, R._flushPreLen = R.length, R._flushPreEnabled = R.enabledCount, f.push(R)), D._flushSeenEpoch !== d && (D._flushSeenEpoch = d, D._flushPreLen = D.length, D._flushPreEnabled = D.enabledCount, f.push(D));
|
|
4117
|
+
let tt;
|
|
4118
|
+
if (H !== I) {
|
|
4119
4119
|
if (Mt)
|
|
4120
|
-
D.moveEntityFromTag(
|
|
4120
|
+
D.moveEntityFromTag(R, H, p, i);
|
|
4121
4121
|
else {
|
|
4122
|
-
const fe =
|
|
4123
|
-
D.moveEntityFrom(
|
|
4122
|
+
const fe = R.getEdge(S);
|
|
4123
|
+
D.moveEntityFrom(R, H, p, fe.addMap, u, i);
|
|
4124
4124
|
}
|
|
4125
|
-
|
|
4125
|
+
tt = x[0];
|
|
4126
4126
|
} else
|
|
4127
|
-
|
|
4128
|
-
E.fieldNames.length > 0 && D.writeFields(
|
|
4127
|
+
tt = Mt ? D.addEntityTag(p, i) : D.addEntity(p, i);
|
|
4128
|
+
E.fieldNames.length > 0 && D.writeFields(tt, S, s[y], u), r[m] = N, i[m] = tt, g && E.obsAdd && (_.addComp[_.addLen] = S, _.addEid[_.addLen] = p, _.addLen++);
|
|
4129
4129
|
}
|
|
4130
4130
|
t.length = 0, e.length = 0, s.length = 0, this._settleFlushDirty();
|
|
4131
4131
|
}
|
|
@@ -4137,14 +4137,14 @@ class Ls {
|
|
|
4137
4137
|
if (p >= h || i[p] !== m) continue;
|
|
4138
4138
|
const C = n[p], A = e[_].id, S = o[C];
|
|
4139
4139
|
if (!S.mask.has(A)) continue;
|
|
4140
|
-
const
|
|
4140
|
+
const R = this.archResolveRemove(C, A), E = o[R], N = r[p], D = !E.hasColumns && !S.hasColumns;
|
|
4141
4141
|
if (S._flushSeenEpoch !== l && (S._flushSeenEpoch = l, S._flushPreLen = S.length, S._flushPreEnabled = S.enabledCount, u.push(S)), E._flushSeenEpoch !== l && (E._flushSeenEpoch = l, E._flushPreLen = E.length, E._flushPreEnabled = E.enabledCount, u.push(E)), D)
|
|
4142
4142
|
E.moveEntityFromTag(S, N, y, r);
|
|
4143
4143
|
else {
|
|
4144
4144
|
const H = S.getEdge(A);
|
|
4145
4145
|
E.moveEntityFrom(S, N, y, H.removeMap, c, r);
|
|
4146
4146
|
}
|
|
4147
|
-
n[p] =
|
|
4147
|
+
n[p] = R, r[p] = x[0], f && d[A].obsRem && (g.remComp[g.remLen] = A, g.remEid[g.remLen] = y, g.remLen++);
|
|
4148
4148
|
}
|
|
4149
4149
|
t.length = 0, e.length = 0, this._settleFlushDirty();
|
|
4150
4150
|
}
|
|
@@ -4263,11 +4263,11 @@ class Ls {
|
|
|
4263
4263
|
// Component registration
|
|
4264
4264
|
// =======================================================
|
|
4265
4265
|
registerComponent(t, e) {
|
|
4266
|
-
if (this.componentCount >=
|
|
4266
|
+
if (this.componentCount >= st)
|
|
4267
4267
|
throw new v(
|
|
4268
4268
|
b.COMPONENT_LIMIT_EXCEEDED,
|
|
4269
|
-
`Cannot register more than ${
|
|
4270
|
-
{ componentCount: this.componentCount, limit:
|
|
4269
|
+
`Cannot register more than ${st} components: the SAB archetype descriptor mask is ${st} bits wide. Widen the descriptor mask (descriptor.ts + abi.zig, a SIM_ABI_VERSION bump) to raise it.`,
|
|
4270
|
+
{ componentCount: this.componentCount, limit: st }
|
|
4271
4271
|
);
|
|
4272
4272
|
const s = Object.keys(t), n = new Array(s.length), r = /* @__PURE__ */ Object.create(null);
|
|
4273
4273
|
for (let h = 0; h < s.length; h++)
|
|
@@ -4352,7 +4352,7 @@ class Ls {
|
|
|
4352
4352
|
/** Add (or overwrite) a sparse component on an entity. No archetype
|
|
4353
4353
|
* transition, no row copy — the entity's `archetype_id` is unchanged. */
|
|
4354
4354
|
addSparse(t, e, s) {
|
|
4355
|
-
this.isAlive(t) && this.sparseStoreOf(e).setRow(w(t), s ??
|
|
4355
|
+
this.isAlive(t) && this.sparseStoreOf(e).setRow(w(t), s ?? Y);
|
|
4356
4356
|
}
|
|
4357
4357
|
/** Remove a sparse component from an entity. No-op if absent. */
|
|
4358
4358
|
removeSparse(t, e) {
|
|
@@ -4466,7 +4466,7 @@ class Ls {
|
|
|
4466
4466
|
e[s].isBufferBacked && e[s].refreshViews(this._columnStore);
|
|
4467
4467
|
this.entityAllocator.setHighWater(
|
|
4468
4468
|
t.view.getUint32(
|
|
4469
|
-
t.header.entityIndexOff +
|
|
4469
|
+
t.header.entityIndexOff + it.length,
|
|
4470
4470
|
!0
|
|
4471
4471
|
)
|
|
4472
4472
|
), this._handleBufferResized();
|
|
@@ -4481,11 +4481,11 @@ class Ls {
|
|
|
4481
4481
|
const e = this.entityAllocator.highWater, s = this.entityArchetype, n = this.entityRow, r = this.entityAllocator.generations, i = /* @__PURE__ */ new Map();
|
|
4482
4482
|
for (let o = 0; o < e; o++) {
|
|
4483
4483
|
const h = s[o];
|
|
4484
|
-
if (h ===
|
|
4484
|
+
if (h === I) continue;
|
|
4485
4485
|
const c = n[o];
|
|
4486
|
-
if (c ===
|
|
4486
|
+
if (c === I) continue;
|
|
4487
4487
|
let l = i.get(h);
|
|
4488
|
-
l === void 0 && (l = [], i.set(h, l)), l[c] =
|
|
4488
|
+
l === void 0 && (l = [], i.set(h, l)), l[c] = J(o, r[o]);
|
|
4489
4489
|
}
|
|
4490
4490
|
for (let o = 0; o < t.archetypeRows.length; o++) {
|
|
4491
4491
|
const h = t.archetypeRows[o], c = this.archGet(h.archetypeId), l = i.get(h.archetypeId) ?? [];
|
|
@@ -4604,14 +4604,14 @@ class Ls {
|
|
|
4604
4604
|
}
|
|
4605
4605
|
if (!C) continue;
|
|
4606
4606
|
const A = g[m];
|
|
4607
|
-
if (A ===
|
|
4608
|
-
const S = y[A],
|
|
4609
|
-
if (
|
|
4607
|
+
if (A === I) continue;
|
|
4608
|
+
const S = y[A], R = S.mask;
|
|
4609
|
+
if (R.contains(t) && !(e !== null && R.overlaps(e)) && !(s !== null && !R.overlaps(s))) {
|
|
4610
4610
|
if (!h) {
|
|
4611
4611
|
const E = _[m];
|
|
4612
|
-
if (E !==
|
|
4612
|
+
if (E !== I && E >= S.enabledCount) continue;
|
|
4613
4613
|
}
|
|
4614
|
-
o(
|
|
4614
|
+
o(J(m, f[m]));
|
|
4615
4615
|
}
|
|
4616
4616
|
}
|
|
4617
4617
|
return;
|
|
@@ -4666,7 +4666,7 @@ class Ls {
|
|
|
4666
4666
|
}
|
|
4667
4667
|
const o = this.archResolveAdd(r, e.id), h = this.archGet(o), c = this.entityRow[n];
|
|
4668
4668
|
let l;
|
|
4669
|
-
if (c !==
|
|
4669
|
+
if (c !== I) {
|
|
4670
4670
|
const u = i.length, d = h.length, f = h.enabledCount, g = i.getEdge(e.id);
|
|
4671
4671
|
!h.hasColumns && !i.hasColumns ? h.moveEntityFromTag(i, c, t, this.entityRow) : h.moveEntityFrom(
|
|
4672
4672
|
i,
|
|
@@ -4687,6 +4687,28 @@ class Ls {
|
|
|
4687
4687
|
this._tick
|
|
4688
4688
|
), this.entityArchetype[n] = o, this.entityRow[n] = l;
|
|
4689
4689
|
}
|
|
4690
|
+
/** Add multiple components in one transition (resolves final archetype, then moves once).
|
|
4691
|
+
*
|
|
4692
|
+
* Final-mask resolve, not graph walk. The previous implementation called
|
|
4693
|
+
* `archResolveAdd` once per entry, which threaded through every
|
|
4694
|
+
* intermediate archetype on the path — and each unseen intermediate
|
|
4695
|
+
* triggered a fresh `extendColumnStore` even though no entity ever lived
|
|
4696
|
+
* there. Computing the union mask up front and resolving once via
|
|
4697
|
+
* `archGetOrCreateFromMask` collapses N-1 intermediate-archetype
|
|
4698
|
+
* creations into zero for the batched case (#211 follow-up). The lazy
|
|
4699
|
+
* single-mask path remains the same; this just avoids feeding it
|
|
4700
|
+
* archetypes the entity never visits.
|
|
4701
|
+
*
|
|
4702
|
+
* #659 — composite-add edge cache. The final-mask resolve, unlike the
|
|
4703
|
+
* single-add `edges[]` walk, re-pays a per-call `mask.hash()`, `ArchetypeGraph.lookup`
|
|
4704
|
+
* (the Map-of-buckets + `equals` scan), and `getBatchTransitionMap` on
|
|
4705
|
+
* every call — a ~2× gap vs a cached edge walk that the decomposition probe
|
|
4706
|
+
* pinned on the two `Map.get`s, not the hash. So a repeated (source, added-
|
|
4707
|
+
* set) add now resolves through `currentArch`'s composite-add cache: one
|
|
4708
|
+
* `Map.get` on an exact packed key yields the target + transition map, and we
|
|
4709
|
+
* skip the union-mask build entirely. First call per key still resolves via
|
|
4710
|
+
* the final-mask path below (no intermediate planting) and plants the edge.
|
|
4711
|
+
* See docs/reports/bench/regressions/add-components-composite-edge.md. */
|
|
4690
4712
|
addComponents(t, e) {
|
|
4691
4713
|
if (!this.isAlive(t))
|
|
4692
4714
|
return;
|
|
@@ -4726,7 +4748,7 @@ class Ls {
|
|
|
4726
4748
|
r.writeFields(
|
|
4727
4749
|
d,
|
|
4728
4750
|
e[f].def.id,
|
|
4729
|
-
e[f].values ??
|
|
4751
|
+
e[f].values ?? Y,
|
|
4730
4752
|
this._tick
|
|
4731
4753
|
);
|
|
4732
4754
|
return;
|
|
@@ -4751,7 +4773,7 @@ class Ls {
|
|
|
4751
4773
|
_addComponentsInto(t, e, s, n, r, i, o) {
|
|
4752
4774
|
const h = this.entityRow[e];
|
|
4753
4775
|
let c;
|
|
4754
|
-
if (h !==
|
|
4776
|
+
if (h !== I) {
|
|
4755
4777
|
const l = s.length, u = n.length, d = n.enabledCount;
|
|
4756
4778
|
n.moveEntityFrom(
|
|
4757
4779
|
s,
|
|
@@ -4769,7 +4791,7 @@ class Ls {
|
|
|
4769
4791
|
n.writeFields(
|
|
4770
4792
|
c,
|
|
4771
4793
|
o[l].def.id,
|
|
4772
|
-
o[l].values ??
|
|
4794
|
+
o[l].values ?? Y,
|
|
4773
4795
|
this._tick
|
|
4774
4796
|
);
|
|
4775
4797
|
this.entityArchetype[e] = r, this.entityRow[e] = c;
|
|
@@ -4869,7 +4891,7 @@ class Ls {
|
|
|
4869
4891
|
const _ = s.entityIds;
|
|
4870
4892
|
for (let y = 0; y < h; y++) {
|
|
4871
4893
|
const p = w(_[y]);
|
|
4872
|
-
l[p] = r, u[p] =
|
|
4894
|
+
l[p] = r, u[p] = I;
|
|
4873
4895
|
}
|
|
4874
4896
|
s.clearRows(), this._onArchLenChange(s, c);
|
|
4875
4897
|
return;
|
|
@@ -5140,7 +5162,7 @@ class Fs {
|
|
|
5140
5162
|
* @example
|
|
5141
5163
|
* const GameTime = resourceKey<{ elapsed: number }>("GameTime");
|
|
5142
5164
|
* ecs.resources.register(GameTime, { elapsed: 0 });
|
|
5143
|
-
* ecs.resources.get(GameTime).elapsed; // or ctx.
|
|
5165
|
+
* ecs.resources.get(GameTime).elapsed; // or ctx.getResource(GameTime) inside a system
|
|
5144
5166
|
*/
|
|
5145
5167
|
register(t, e) {
|
|
5146
5168
|
this.store.registerResource(t, e);
|
|
@@ -5280,10 +5302,10 @@ class Gs {
|
|
|
5280
5302
|
}
|
|
5281
5303
|
}
|
|
5282
5304
|
const Yt = Object.freeze([]), Ps = Object.freeze([]), Qt = Object.freeze([]), Kt = Number.POSITIVE_INFINITY;
|
|
5283
|
-
function
|
|
5305
|
+
function X(a, t) {
|
|
5284
5306
|
return (a << 16 | t) >>> 0;
|
|
5285
5307
|
}
|
|
5286
|
-
function
|
|
5308
|
+
function rt(a, t) {
|
|
5287
5309
|
for (let e = 0; e < a.length; e++)
|
|
5288
5310
|
if (a[e] === t) return a;
|
|
5289
5311
|
return [...a, t];
|
|
@@ -5401,7 +5423,7 @@ class F {
|
|
|
5401
5423
|
);
|
|
5402
5424
|
}
|
|
5403
5425
|
/** Whether this query carries only dense terms — the precondition for the
|
|
5404
|
-
* archetype-walk fast paths (`
|
|
5426
|
+
* archetype-walk fast paths (`entityCount`, `firstEntity`, `singleEntity`). */
|
|
5405
5427
|
_isDenseOnly() {
|
|
5406
5428
|
return this._sparseInclude.length === 0 && this._sparseExclude.length === 0 && this._relationIncludes.length === 0 && this._relationExcludes.length === 0 && this._hierarchy === null;
|
|
5407
5429
|
}
|
|
@@ -5545,10 +5567,10 @@ class F {
|
|
|
5545
5567
|
* the resolver's shared single-term map. Both the single- and multi-arg public
|
|
5546
5568
|
* forms fold over this, so all sparse-require composition is deduplicated. */
|
|
5547
5569
|
_withSparseOne(t) {
|
|
5548
|
-
const e =
|
|
5570
|
+
const e = X(this._id, t), s = this._resolver._caches.withSparseSingle, n = s.get(e);
|
|
5549
5571
|
if (n !== void 0) return n;
|
|
5550
5572
|
const r = this._deriveSparse(
|
|
5551
|
-
|
|
5573
|
+
rt(this._sparseInclude, t),
|
|
5552
5574
|
this._sparseExclude
|
|
5553
5575
|
);
|
|
5554
5576
|
return s.set(e, r), r;
|
|
@@ -5564,11 +5586,11 @@ class F {
|
|
|
5564
5586
|
/** One-id `withoutSparse` composition, cached on `(parent_id, sparseId)`. The
|
|
5565
5587
|
* multi-arg form folds over this (#497) — mirrors `_withSparseOne`. */
|
|
5566
5588
|
_withoutSparseOne(t) {
|
|
5567
|
-
const e =
|
|
5589
|
+
const e = X(this._id, t), s = this._resolver._caches.withoutSparseSingle, n = s.get(e);
|
|
5568
5590
|
if (n !== void 0) return n;
|
|
5569
5591
|
const r = this._deriveSparse(
|
|
5570
5592
|
this._sparseInclude,
|
|
5571
|
-
|
|
5593
|
+
rt(this._sparseExclude, t)
|
|
5572
5594
|
);
|
|
5573
5595
|
return s.set(e, r), r;
|
|
5574
5596
|
}
|
|
@@ -5613,10 +5635,10 @@ class F {
|
|
|
5613
5635
|
return e;
|
|
5614
5636
|
}
|
|
5615
5637
|
_withRelationOne(t) {
|
|
5616
|
-
const e =
|
|
5638
|
+
const e = X(this._id, t), s = this._resolver._caches.withRelationSingle, n = s.get(e);
|
|
5617
5639
|
if (n !== void 0) return n;
|
|
5618
5640
|
const r = this._resolver._relationBackingSparseId(t), i = this._deriveRelation(
|
|
5619
|
-
|
|
5641
|
+
rt(this._sparseInclude, r),
|
|
5620
5642
|
this._sparseExclude,
|
|
5621
5643
|
Xt(this._relationIncludes, t),
|
|
5622
5644
|
this._relationExcludes
|
|
@@ -5633,11 +5655,11 @@ class F {
|
|
|
5633
5655
|
return e;
|
|
5634
5656
|
}
|
|
5635
5657
|
_withoutRelationOne(t) {
|
|
5636
|
-
const e =
|
|
5658
|
+
const e = X(this._id, t), s = this._resolver._caches.withoutRelationSingle, n = s.get(e);
|
|
5637
5659
|
if (n !== void 0) return n;
|
|
5638
5660
|
const r = this._resolver._relationBackingSparseId(t), i = this._deriveRelation(
|
|
5639
5661
|
this._sparseInclude,
|
|
5640
|
-
|
|
5662
|
+
rt(this._sparseExclude, r),
|
|
5641
5663
|
this._relationIncludes,
|
|
5642
5664
|
Xt(this._relationExcludes, t)
|
|
5643
5665
|
);
|
|
@@ -5687,7 +5709,7 @@ class F {
|
|
|
5687
5709
|
* `not` / `anyOf`). Returns a new query; the unbounded form is cached. */
|
|
5688
5710
|
hierarchy(t, e = Kt) {
|
|
5689
5711
|
if (e === Kt) {
|
|
5690
|
-
const s =
|
|
5712
|
+
const s = X(this._id, t), n = this._resolver._caches.hierarchySingle, r = n.get(s);
|
|
5691
5713
|
if (r !== void 0) return r;
|
|
5692
5714
|
const i = this._deriveHierarchy({ relation: t, maxDepth: e });
|
|
5693
5715
|
return n.set(s, i), i;
|
|
@@ -5722,9 +5744,9 @@ class F {
|
|
|
5722
5744
|
* outside a system `checkRelationRead` is a no-op. */
|
|
5723
5745
|
_checkRelationAccess() {
|
|
5724
5746
|
for (let t = 0; t < this._relationIncludes.length; t++)
|
|
5725
|
-
|
|
5747
|
+
ut.checkRelationRead(this._relationIncludes[t]);
|
|
5726
5748
|
for (let t = 0; t < this._relationExcludes.length; t++)
|
|
5727
|
-
|
|
5749
|
+
ut.checkRelationRead(this._relationExcludes[t]);
|
|
5728
5750
|
}
|
|
5729
5751
|
/** Iterate every source related to `target` under **any** relation — the
|
|
5730
5752
|
* `(*, T)` wildcard (#579) — intersected with this query's dense + sparse +
|
|
@@ -6092,8 +6114,8 @@ class qs {
|
|
|
6092
6114
|
spawn(...t) {
|
|
6093
6115
|
const e = this.store.createEntity();
|
|
6094
6116
|
for (let s = 0; s < t.length; s++) {
|
|
6095
|
-
const n =
|
|
6096
|
-
this.store.addComponentDeferred(e, n,
|
|
6117
|
+
const n = j(t[s]);
|
|
6118
|
+
this.store.addComponentDeferred(e, n, z(t[s]));
|
|
6097
6119
|
}
|
|
6098
6120
|
return e;
|
|
6099
6121
|
}
|
|
@@ -6103,8 +6125,8 @@ class qs {
|
|
|
6103
6125
|
return this.store.addComponentDeferred(t, s, e[1]), this;
|
|
6104
6126
|
}
|
|
6105
6127
|
for (let s = 0; s < e.length; s++) {
|
|
6106
|
-
const n = e[s], r =
|
|
6107
|
-
this.store.addComponentDeferred(t, r,
|
|
6128
|
+
const n = e[s], r = j(n);
|
|
6129
|
+
this.store.addComponentDeferred(t, r, z(n));
|
|
6108
6130
|
}
|
|
6109
6131
|
return this;
|
|
6110
6132
|
}
|
|
@@ -6330,7 +6352,12 @@ class js {
|
|
|
6330
6352
|
// =======================================================
|
|
6331
6353
|
// Resources
|
|
6332
6354
|
// =======================================================
|
|
6333
|
-
resource(
|
|
6355
|
+
/** Read a resource (declared in `resourceReads`). The flat `ctx` surface verbs
|
|
6356
|
+
* its accessors — `getResource`/`setResource`/`removeResource`/`hasResource`,
|
|
6357
|
+
* matching `getField`/`setField`/`hasComponent`. The grouped `ecs.resources`
|
|
6358
|
+
* facade drops the noun (`get`/`set`/`remove`/`has`) because its receiver
|
|
6359
|
+
* already names it. */
|
|
6360
|
+
getResource(t) {
|
|
6334
6361
|
return T(this.store.getResource(t));
|
|
6335
6362
|
}
|
|
6336
6363
|
setResource(t, e) {
|
|
@@ -6647,36 +6674,56 @@ class sn {
|
|
|
6647
6674
|
}
|
|
6648
6675
|
/**
|
|
6649
6676
|
* Spawn an entity from varargs bundles (§bundles) — the immediate
|
|
6650
|
-
* host-side analog of `ctx.commands.spawn
|
|
6651
|
-
*
|
|
6652
|
-
*
|
|
6653
|
-
*
|
|
6654
|
-
*
|
|
6677
|
+
* host-side analog of `ctx.commands.spawn`, and the same callable-bundle
|
|
6678
|
+
* grammar as `addComponents` / `template`. `ecs.spawnBundle(Pos({x,y}),
|
|
6679
|
+
* Vel({vx:1}), IsEnemy)` collapses the attach shapes into one; each item is
|
|
6680
|
+
* checked against its own def's schema (`StrictBundles`). Bundles are applied
|
|
6681
|
+
* immediately; a single combined-archetype insertion (one transition instead
|
|
6682
|
+
* of one-per-component) is a later optimization — for now this mirrors the
|
|
6683
|
+
* per-component `addComponent` path (unlike `addComponents`, which batches).
|
|
6684
|
+
*
|
|
6685
|
+
* Immediate — inside a system use the deferred `ctx.commands.spawn(...)`
|
|
6686
|
+
* (calling this from a system body throws in DEV). Note the redirect trades
|
|
6687
|
+
* timing: `commands.spawn` returns the id now but defers the attaches to the
|
|
6688
|
+
* phase flush, so the entity sits in its empty/partial archetype until then —
|
|
6689
|
+
* unlike `spawnBundle`'s immediate, fully-populated archetype.
|
|
6655
6690
|
*/
|
|
6656
6691
|
spawnBundle(...t) {
|
|
6657
6692
|
const e = this.store.createEntity();
|
|
6658
6693
|
for (let s = 0; s < t.length; s++) {
|
|
6659
|
-
const n =
|
|
6660
|
-
this.store.addComponent(e,
|
|
6694
|
+
const n = t[s], r = j(n);
|
|
6695
|
+
this.store.addComponent(e, r, z(n));
|
|
6661
6696
|
}
|
|
6662
6697
|
return e;
|
|
6663
6698
|
}
|
|
6699
|
+
/** Bulk-spawn `count` entities from `template`, optionally applying one
|
|
6700
|
+
* shared `overrides` object to every spawned row (same typed keys as
|
|
6701
|
+
* `spawn`). Field writes are O(columns) (one `TypedArray.fill` per
|
|
6702
|
+
* column), not O(count×columns). Returns the new ids in spawn order.
|
|
6703
|
+
* Immediate — inside a system use `ctx.commands.spawn` per entity (calling
|
|
6704
|
+
* this from a system body throws in DEV). */
|
|
6705
|
+
spawnMany(t, e, s) {
|
|
6706
|
+
return this.store.spawnMany(t, e, s);
|
|
6707
|
+
}
|
|
6664
6708
|
/** DEV-only: throw when an *immediate* host structural mutator is called
|
|
6665
6709
|
* from inside one of THIS world's system bodies (or an observer / onAdded
|
|
6666
6710
|
* hook — they run in the same access spans). One rule for every host
|
|
6667
|
-
* mutator
|
|
6668
|
-
*
|
|
6669
|
-
*
|
|
6670
|
-
*
|
|
6671
|
-
*
|
|
6672
|
-
*
|
|
6711
|
+
* structural mutator — despawn, add/remove(Components), batchAdd/Remove,
|
|
6712
|
+
* disable/enable, AND the spawn family (spawn/spawnBundle/spawnMany): an
|
|
6713
|
+
* immediate structural op mid-schedule can move or swap rows a running query
|
|
6714
|
+
* is walking — or, for a spawn-append into that archetype, trip a column
|
|
6715
|
+
* realloc under it — and it is invisible to observers. The archetype-level
|
|
6716
|
+
* `_iterDepth` guard only catches mutations touching the archetype currently
|
|
6717
|
+
* being iterated (and the append paths skip even that), so an op landing
|
|
6718
|
+
* elsewhere would silently skip observers; the receiver rule ("inside a
|
|
6719
|
+
* system, use ctx.commands") is enforced wholesale here.
|
|
6673
6720
|
*
|
|
6674
6721
|
* `_updating` scopes the guard to THIS world: the accessCheck slot is
|
|
6675
6722
|
* process-global, so without it a system of world A mutating world B (a
|
|
6676
6723
|
* supported #785 pattern — B is not mid-iteration) would false-throw. */
|
|
6677
6724
|
_assertHostMutationOutsideSystem(t, e) {
|
|
6678
|
-
if (this._updating &&
|
|
6679
|
-
const s =
|
|
6725
|
+
if (this._updating && ut.current() !== null) {
|
|
6726
|
+
const s = ut.current(), n = s.name ?? `system_${s.id}`;
|
|
6680
6727
|
throw new v(
|
|
6681
6728
|
b.ACCESS_UNDECLARED,
|
|
6682
6729
|
`ecs.${t} called from inside system '${n}' — host ${t} is immediate and unsafe mid-iteration (and invisible to observers); use ${e} instead`,
|
|
@@ -6691,7 +6738,7 @@ class sn {
|
|
|
6691
6738
|
* a system body throws in DEV, since an immediate destroy mid-iteration
|
|
6692
6739
|
* can invalidate rows the running query is walking. */
|
|
6693
6740
|
despawn(t) {
|
|
6694
|
-
this.store.destroyEntity(t);
|
|
6741
|
+
return this.store.destroyEntity(t), this;
|
|
6695
6742
|
}
|
|
6696
6743
|
// --- Entity enable/disable (#577) ---
|
|
6697
6744
|
// A disabled entity keeps its components, relations, sparse data, and stable
|
|
@@ -6703,29 +6750,37 @@ class sn {
|
|
|
6703
6750
|
// in-flight `forEach` over that archetype). A disabled entity must hold at
|
|
6704
6751
|
// least one component (a component-less entity has no archetype row to
|
|
6705
6752
|
// partition).
|
|
6706
|
-
/** Disable `
|
|
6753
|
+
/** Disable `entityId` (idempotent). Excluded from default queries until re-enabled. */
|
|
6707
6754
|
disable(t) {
|
|
6708
6755
|
return this.store.disableEntity(t), this;
|
|
6709
6756
|
}
|
|
6710
|
-
/** Re-enable a disabled `
|
|
6757
|
+
/** Re-enable a disabled `entityId` (idempotent). */
|
|
6711
6758
|
enable(t) {
|
|
6712
6759
|
return this.store.enableEntity(t), this;
|
|
6713
6760
|
}
|
|
6714
6761
|
addComponent(t, e, s) {
|
|
6715
|
-
const n =
|
|
6716
|
-
return this.store.addComponent(t, n, s ??
|
|
6717
|
-
}
|
|
6718
|
-
/** Batch-attach several components in one archetype transition.
|
|
6719
|
-
*
|
|
6720
|
-
*
|
|
6721
|
-
*
|
|
6722
|
-
|
|
6723
|
-
|
|
6762
|
+
const n = j(e);
|
|
6763
|
+
return this.store.addComponent(t, n, s ?? z(e)), this;
|
|
6764
|
+
}
|
|
6765
|
+
/** Batch-attach several components in one archetype transition. Takes the
|
|
6766
|
+
* same callable-bundle varargs as `spawnBundle` — `world.addComponents(e,
|
|
6767
|
+
* Pos({ x, y }), Vel({ vx }), Frozen)` — each item checked against its own
|
|
6768
|
+
* def's schema (a misspelled or cross-component field is a compile error;
|
|
6769
|
+
* tags refuse values). Omitted fields zero-fill. */
|
|
6770
|
+
addComponents(t, ...e) {
|
|
6771
|
+
const s = [];
|
|
6772
|
+
for (let n = 0; n < e.length; n++) {
|
|
6773
|
+
const r = e[n];
|
|
6774
|
+
s.push({ def: j(r), values: z(r) });
|
|
6775
|
+
}
|
|
6776
|
+
return this.store.addComponents(t, s), this;
|
|
6724
6777
|
}
|
|
6725
6778
|
removeComponent(t, e) {
|
|
6726
6779
|
return this.store.removeComponent(t, e), this;
|
|
6727
6780
|
}
|
|
6728
|
-
|
|
6781
|
+
/** Detach several components in one archetype transition — the varargs
|
|
6782
|
+
* mirror of `addComponents` (bare defs; removing needs no values). */
|
|
6783
|
+
removeComponents(t, ...e) {
|
|
6729
6784
|
return this.store.removeComponents(t, e), this;
|
|
6730
6785
|
}
|
|
6731
6786
|
batchAddComponent(t, e, s) {
|
|
@@ -6848,7 +6903,7 @@ class sn {
|
|
|
6848
6903
|
return this.systems.add(r), r;
|
|
6849
6904
|
}
|
|
6850
6905
|
removeSystem(t) {
|
|
6851
|
-
this.schedule.removeSystem(t), t.onRemoved?.(), this.systems.delete(t);
|
|
6906
|
+
return this.schedule.removeSystem(t), t.onRemoved?.(), this.systems.delete(t), this;
|
|
6852
6907
|
}
|
|
6853
6908
|
get systemCount() {
|
|
6854
6909
|
return this.systems.size;
|
|
@@ -6926,6 +6981,30 @@ class sn {
|
|
|
6926
6981
|
t.dispose?.(), t.onRemoved?.();
|
|
6927
6982
|
this.systems.clear(), this.schedule.clear();
|
|
6928
6983
|
}
|
|
6984
|
+
/** Register an archetype template (#462). Resolves the component set +
|
|
6985
|
+
* default field values to a target archetype once (creating it if absent —
|
|
6986
|
+
* fits the prewarm model), so later `spawn` / `spawnMany` calls land
|
|
6987
|
+
* entities directly in that archetype with **zero archetype transitions**.
|
|
6988
|
+
*
|
|
6989
|
+
* const Bullet = ecs.template(Position({ x: 0, y: 0 }), Velocity({ vx: 0, vy: 0 }));
|
|
6990
|
+
*
|
|
6991
|
+
* Takes the same callable-bundle varargs as `spawnBundle` / `addComponents`
|
|
6992
|
+
* (each item schema-checked against its own def); the resulting
|
|
6993
|
+
* `Template<[Position, Velocity]>` keeps the typed key set that `spawn`'s
|
|
6994
|
+
* `overrides` map over. Not a pass-through — it normalizes bundles to the
|
|
6995
|
+
* store's entry shape, so it lives here with the other real logic, not in the
|
|
6996
|
+
* delegation band. The big win is multi-component entities and bulk spawns; a
|
|
6997
|
+
* single-component spawn is no faster than `spawn` + `addComponent`, which
|
|
6998
|
+
* already bump-allocates a fresh entity into the target archetype. See
|
|
6999
|
+
* ADR-0010. */
|
|
7000
|
+
template(...t) {
|
|
7001
|
+
const e = [];
|
|
7002
|
+
for (let s = 0; s < t.length; s++) {
|
|
7003
|
+
const n = t[s];
|
|
7004
|
+
e.push({ def: j(n), values: z(n) });
|
|
7005
|
+
}
|
|
7006
|
+
return this.store.resolveTemplate(e);
|
|
7007
|
+
}
|
|
6929
7008
|
// ============================================================================
|
|
6930
7009
|
// === BEGIN STORE PASS-THROUGH BAND ===
|
|
6931
7010
|
//
|
|
@@ -6994,30 +7073,6 @@ class sn {
|
|
|
6994
7073
|
registerSparseTag() {
|
|
6995
7074
|
return this.store.registerSparseComponent({});
|
|
6996
7075
|
}
|
|
6997
|
-
/** Register an archetype template (#462). Resolves the component set +
|
|
6998
|
-
* default field values to a target archetype once (creating it if absent —
|
|
6999
|
-
* fits the prewarm model), so later `spawn` / `spawnMany` calls land
|
|
7000
|
-
* entities directly in that archetype with **zero archetype transitions**.
|
|
7001
|
-
*
|
|
7002
|
-
* const Bullet = ecs.template([
|
|
7003
|
-
* { def: Position, values: { x: 0, y: 0 } },
|
|
7004
|
-
* { def: Velocity, values: { vx: 0, vy: 0 } },
|
|
7005
|
-
* ]);
|
|
7006
|
-
*
|
|
7007
|
-
* The big win is multi-component entities and bulk spawns; a single-
|
|
7008
|
-
* component spawn is no faster than `spawn` + `addComponent`, which
|
|
7009
|
-
* already bump-allocates a fresh entity into the target archetype. See
|
|
7010
|
-
* ADR-0010. */
|
|
7011
|
-
template(t) {
|
|
7012
|
-
return this.store.resolveTemplate(t);
|
|
7013
|
-
}
|
|
7014
|
-
/** Bulk-spawn `count` entities from `template`, optionally applying one
|
|
7015
|
-
* shared `overrides` object to every spawned row (same typed keys as
|
|
7016
|
-
* `spawn`). Field writes are O(columns) (one `TypedArray.fill` per
|
|
7017
|
-
* column), not O(count×columns). Returns the new ids in spawn order. */
|
|
7018
|
-
spawnMany(t, e, s) {
|
|
7019
|
-
return this.store.spawnMany(t, e, s);
|
|
7020
|
-
}
|
|
7021
7076
|
isAlive(t) {
|
|
7022
7077
|
return this.store.isAlive(t);
|
|
7023
7078
|
}
|
|
@@ -7027,7 +7082,7 @@ class sn {
|
|
|
7027
7082
|
hasComponent(t, e) {
|
|
7028
7083
|
return this.store.hasComponent(t, e);
|
|
7029
7084
|
}
|
|
7030
|
-
/** Whether `
|
|
7085
|
+
/** Whether `entityId` is currently disabled. Toggle via `disable` / `enable`
|
|
7031
7086
|
* (immediate, above the band — they carry the in-system dev guard). */
|
|
7032
7087
|
isDisabled(t) {
|
|
7033
7088
|
return this.store.isDisabled(t);
|
|
@@ -7189,7 +7244,7 @@ function nn(a, t) {
|
|
|
7189
7244
|
return {
|
|
7190
7245
|
name: `runIfResourceEq(${a.description ?? "?"})`,
|
|
7191
7246
|
resourceReads: [a],
|
|
7192
|
-
evaluate: (e) => e.
|
|
7247
|
+
evaluate: (e) => e.getResource(a) === t
|
|
7193
7248
|
};
|
|
7194
7249
|
}
|
|
7195
7250
|
function rn(a, t = 0) {
|
|
@@ -7278,21 +7333,21 @@ class ln {
|
|
|
7278
7333
|
};
|
|
7279
7334
|
}
|
|
7280
7335
|
}
|
|
7281
|
-
const
|
|
7336
|
+
const Z = "__component_def";
|
|
7282
7337
|
function un(a) {
|
|
7283
7338
|
return JSON.stringify(a, (t, e) => {
|
|
7284
7339
|
if (typeof e == "function" && "id" in e)
|
|
7285
|
-
return { [
|
|
7286
|
-
if (e !== null && typeof e == "object" &&
|
|
7340
|
+
return { [Z]: e.id };
|
|
7341
|
+
if (e !== null && typeof e == "object" && Z in e)
|
|
7287
7342
|
throw new v(
|
|
7288
7343
|
b.COMMAND_LOG_TAG_COLLISION,
|
|
7289
|
-
`Cannot serialize the command log: a value object owns a field named "${
|
|
7344
|
+
`Cannot serialize the command log: a value object owns a field named "${Z}", the reserved tag the serializer uses for component defs. Rename that component field so the log can round-trip losslessly.`
|
|
7290
7345
|
);
|
|
7291
7346
|
return e;
|
|
7292
7347
|
});
|
|
7293
7348
|
}
|
|
7294
7349
|
function dn(a) {
|
|
7295
|
-
return JSON.parse(a, (t, e) => e !== null && typeof e == "object" &&
|
|
7350
|
+
return JSON.parse(a, (t, e) => e !== null && typeof e == "object" && Z in e ? he(oe(e[Z])) : e);
|
|
7296
7351
|
}
|
|
7297
7352
|
function fn(a, t, e, s) {
|
|
7298
7353
|
for (const i of e.startup) t.push(i);
|
|
@@ -7464,7 +7519,7 @@ function yn(a, t) {
|
|
|
7464
7519
|
function mn(a) {
|
|
7465
7520
|
return T(Symbol(a));
|
|
7466
7521
|
}
|
|
7467
|
-
const wn = "0.5.
|
|
7522
|
+
const wn = "0.5.1";
|
|
7468
7523
|
export {
|
|
7469
7524
|
bn as ANY_RELATION,
|
|
7470
7525
|
U as ChangedQuery,
|
|
@@ -7474,7 +7529,7 @@ export {
|
|
|
7474
7529
|
v as ECSError,
|
|
7475
7530
|
k as ECSRestoreError,
|
|
7476
7531
|
b as ECS_ERROR,
|
|
7477
|
-
|
|
7532
|
+
It as ECS_SNAPSHOT_VERSION,
|
|
7478
7533
|
_n as FrameStepper,
|
|
7479
7534
|
pn as FrameTraceRecorder,
|
|
7480
7535
|
Kt as HIERARCHY_UNBOUNDED,
|
|
@@ -7484,18 +7539,18 @@ export {
|
|
|
7484
7539
|
Vs as QueryBuilder,
|
|
7485
7540
|
Sn as SCHEDULE,
|
|
7486
7541
|
xn as SabUnavailableError,
|
|
7487
|
-
|
|
7488
|
-
|
|
7542
|
+
et as SparseRestoreError,
|
|
7543
|
+
Q as StoreRestoreError,
|
|
7489
7544
|
js as SystemContext,
|
|
7490
7545
|
wn as VERSION,
|
|
7491
7546
|
an as allOf,
|
|
7492
7547
|
cn as anyOf,
|
|
7493
|
-
|
|
7548
|
+
Rn as applyHostCommand,
|
|
7494
7549
|
Js as bundle,
|
|
7495
7550
|
dn as deserializeCommandLog,
|
|
7496
7551
|
tn as eventKey,
|
|
7497
7552
|
w as getEntityIndex,
|
|
7498
|
-
|
|
7553
|
+
In as installHostCommandSeam,
|
|
7499
7554
|
An as isEcsError,
|
|
7500
7555
|
hn as not,
|
|
7501
7556
|
yn as registerChildOf,
|