@idleflowgames/anotherecs 0.1.3 → 0.1.4
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 +14 -0
- package/dist/index.js +96 -54
- package/dist/index.js.map +1 -1
- package/dist/spatial-hash.d.ts +12 -2
- package/package.json +13 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.4
|
|
4
|
+
|
|
5
|
+
- `SpatialHash`: `clear()` is now O(1). Buckets carry a frame stamp and a live
|
|
6
|
+
prefix count, so a stamp bump retires the whole grid and a periodic sweep
|
|
7
|
+
reclaims dead buckets. Queries additionally clamp their cell span to an
|
|
8
|
+
occupied bounding box and a per-column occupied row range, both supersets of
|
|
9
|
+
the true occupied set, so they only ever skip cells that are provably empty.
|
|
10
|
+
Szudzik pairing is inlined at its three call sites with its cx-only half
|
|
11
|
+
hoisted out of the inner loop.
|
|
12
|
+
Result arrays are unchanged in membership AND in order, so a consumer that
|
|
13
|
+
relies on iteration order for determinism is unaffected.
|
|
14
|
+
A whole broadphase frame is 2.32x faster at 50 bodies, 1.90x at 250 and 1.13x
|
|
15
|
+
at 1000; a 253k-op trace recorded from a real game run replays 48% faster.
|
|
16
|
+
|
|
3
17
|
## 0.1.2
|
|
4
18
|
|
|
5
19
|
- No source changes. Toolchain/deps only: Node 24, pnpm 11.5.0, lock-file
|
package/dist/index.js
CHANGED
|
@@ -1218,17 +1218,18 @@ var T = 65536, E = -1, D = class {
|
|
|
1218
1218
|
for (let e = 0; e < this.count; e++) this.sparse[this.entities[e]] = E;
|
|
1219
1219
|
this.entities.length = 0, this.data.length = 0, this.count = 0, this.freeList.length = 0, this._added.length = 0, this._removed.length = 0, this._changed.length = 0, this._addedFired = 0, this._removedFired = 0, this._version++;
|
|
1220
1220
|
}
|
|
1221
|
-
}
|
|
1222
|
-
//#endregion
|
|
1223
|
-
//#region src/spatial-hash.ts
|
|
1224
|
-
function O(e, t) {
|
|
1225
|
-
e.length === 0 ? this.delete(t) : e.length = 0;
|
|
1226
|
-
}
|
|
1227
|
-
var k = class {
|
|
1221
|
+
}, O = 256, k = O - 1, A = 64, j = -2147483648, M = 2147483647, N = class {
|
|
1228
1222
|
invCellSize;
|
|
1229
1223
|
cells = /* @__PURE__ */ new Map();
|
|
1230
1224
|
generation = 0;
|
|
1231
1225
|
seen;
|
|
1226
|
+
occMinCX = 0;
|
|
1227
|
+
occMaxCX = -1;
|
|
1228
|
+
occMinCY = 0;
|
|
1229
|
+
occMaxCY = -1;
|
|
1230
|
+
col = new Int32Array(O * 3);
|
|
1231
|
+
frameGen = 1;
|
|
1232
|
+
sweepIn = A;
|
|
1232
1233
|
constructor(e = 64, t = T) {
|
|
1233
1234
|
if (!(e > 0)) throw Error(`SpatialHash: cellSize must be > 0 (got ${e})`);
|
|
1234
1235
|
this.invCellSize = 1 / e, this.seen = new Int32Array(t);
|
|
@@ -1237,85 +1238,126 @@ var k = class {
|
|
|
1237
1238
|
return this.generation = this.generation + 1 | 0, this.generation === 0 && (this.generation = 1), this.generation;
|
|
1238
1239
|
}
|
|
1239
1240
|
clear() {
|
|
1240
|
-
this.
|
|
1241
|
+
this.occMinCX = 0, this.occMaxCX = -1, this.occMinCY = 0, this.occMaxCY = -1;
|
|
1242
|
+
let e = this.frameGen + 1;
|
|
1243
|
+
if (e >= M) {
|
|
1244
|
+
this.cells.clear(), this.col.fill(0), this.frameGen = 1, this.sweepIn = A;
|
|
1245
|
+
return;
|
|
1246
|
+
}
|
|
1247
|
+
this.frameGen = e, --this.sweepIn <= 0 && (this.sweepIn = A, this.cells.forEach(this.pruneStale, this));
|
|
1248
|
+
}
|
|
1249
|
+
pruneStale(e, t) {
|
|
1250
|
+
this.frameGen - e.g >= A && this.cells.delete(t);
|
|
1241
1251
|
}
|
|
1242
1252
|
insert(e, t, n, r) {
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1253
|
+
let i = this.seen;
|
|
1254
|
+
if (e >= i.length) throw Error(`SpatialHash.insert(): entity id ${e} exceeds maxEntities (${i.length}). Construct the SpatialHash with a maxEntities that matches the consuming World's capacity.`);
|
|
1255
|
+
let a = this.cells, o = this.invCellSize, s = Math.floor((t - r) * o), c = Math.floor((t + r) * o), l = Math.floor((n - r) * o), u = Math.floor((n + r) * o);
|
|
1256
|
+
this.occMaxCX < this.occMinCX ? (this.occMinCX = s, this.occMaxCX = c, this.occMinCY = l, this.occMaxCY = u) : (s < this.occMinCX && (this.occMinCX = s), c > this.occMaxCX && (this.occMaxCX = c), l < this.occMinCY && (this.occMinCY = l), u > this.occMaxCY && (this.occMaxCY = u));
|
|
1257
|
+
let d = this.col, f = this.frameGen, p = l < j ? j : l, m = u > M ? M : u;
|
|
1258
|
+
for (let t = s; t <= c; t++) {
|
|
1259
|
+
let n = (t & k) * 3;
|
|
1260
|
+
d[n] === f ? (p < d[n + 1] && (d[n + 1] = p), m > d[n + 2] && (d[n + 2] = m)) : (d[n] = f, d[n + 1] = p, d[n + 2] = m);
|
|
1261
|
+
let r = t >= 0 ? 2 * t : -2 * t - 1, i = r * r + r;
|
|
1262
|
+
for (let t = l; t <= u; t++) {
|
|
1263
|
+
let n = t >= 0 ? 2 * t : -2 * t - 1, o = r >= n ? i + n : n * n + r, s = a.get(o);
|
|
1264
|
+
s === void 0 ? (s = {
|
|
1265
|
+
e: [],
|
|
1266
|
+
n: 0,
|
|
1267
|
+
g: f
|
|
1268
|
+
}, a.set(o, s)) : s.g !== f && (s.g = f, s.n = 0);
|
|
1269
|
+
let c = s.n, l = s.e;
|
|
1270
|
+
c < l.length ? l[c] = e : l.push(e), s.n = c + 1;
|
|
1271
|
+
}
|
|
1248
1272
|
}
|
|
1249
1273
|
}
|
|
1250
1274
|
query(e, t, n, r) {
|
|
1251
1275
|
r.length = 0;
|
|
1252
|
-
let i = this.nextGen(), a = Math.floor((e - n) *
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1276
|
+
let i = this.nextGen(), a = this.cells, o = this.seen, s = this.invCellSize, c = Math.floor((e - n) * s), l = Math.floor((e + n) * s), u = Math.floor((t - n) * s), d = Math.floor((t + n) * s);
|
|
1277
|
+
c < this.occMinCX && (c = this.occMinCX), l > this.occMaxCX && (l = this.occMaxCX), u < this.occMinCY && (u = this.occMinCY), d > this.occMaxCY && (d = this.occMaxCY);
|
|
1278
|
+
let f = this.col, p = this.frameGen;
|
|
1279
|
+
for (let e = c; e <= l; e++) {
|
|
1280
|
+
let t = (e & k) * 3;
|
|
1281
|
+
if (f[t] !== p) continue;
|
|
1282
|
+
let n = u, s = d;
|
|
1283
|
+
n < f[t + 1] && (n = f[t + 1]), s > f[t + 2] && (s = f[t + 2]);
|
|
1284
|
+
let c = e >= 0 ? 2 * e : -2 * e - 1, l = c * c + c;
|
|
1285
|
+
for (let e = n; e <= s; e++) {
|
|
1286
|
+
let t = e >= 0 ? 2 * e : -2 * e - 1, n = a.get(c >= t ? l + t : t * t + c);
|
|
1287
|
+
if (n === void 0 || n.g !== p) continue;
|
|
1288
|
+
let s = n.e;
|
|
1289
|
+
for (let e = 0, t = n.n; e < t; e++) {
|
|
1290
|
+
let t = s[e];
|
|
1291
|
+
o[t] !== i && (o[t] = i, r.push(t));
|
|
1292
|
+
}
|
|
1258
1293
|
}
|
|
1259
1294
|
}
|
|
1260
1295
|
}
|
|
1261
1296
|
queryRadius(e, t, n, r, i, a) {
|
|
1262
1297
|
a.length = 0;
|
|
1263
|
-
let o = this.nextGen(), s = Math.floor((e - n) *
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1298
|
+
let o = this.nextGen(), s = this.cells, c = this.seen, l = this.invCellSize, u = Math.floor((e - n) * l), d = Math.floor((e + n) * l), f = Math.floor((t - n) * l), p = Math.floor((t + n) * l);
|
|
1299
|
+
u < this.occMinCX && (u = this.occMinCX), d > this.occMaxCX && (d = this.occMaxCX), f < this.occMinCY && (f = this.occMinCY), p > this.occMaxCY && (p = this.occMaxCY);
|
|
1300
|
+
let m = this.col, h = this.frameGen;
|
|
1301
|
+
for (let l = u; l <= d; l++) {
|
|
1302
|
+
let u = (l & k) * 3;
|
|
1303
|
+
if (m[u] !== h) continue;
|
|
1304
|
+
let d = f, g = p;
|
|
1305
|
+
d < m[u + 1] && (d = m[u + 1]), g > m[u + 2] && (g = m[u + 2]);
|
|
1306
|
+
let _ = l >= 0 ? 2 * l : -2 * l - 1, v = _ * _ + _;
|
|
1307
|
+
for (let l = d; l <= g; l++) {
|
|
1308
|
+
let u = l >= 0 ? 2 * l : -2 * l - 1, d = s.get(_ >= u ? v + u : u * u + _);
|
|
1309
|
+
if (d === void 0 || d.g !== h) continue;
|
|
1310
|
+
let f = d.e;
|
|
1311
|
+
for (let s = 0, l = d.n; s < l; s++) {
|
|
1312
|
+
let l = f[s];
|
|
1313
|
+
if (c[l] === o) continue;
|
|
1314
|
+
c[l] = o;
|
|
1315
|
+
let u = r(l);
|
|
1316
|
+
if (!u) continue;
|
|
1317
|
+
let d = i(l), p = u.x - e, m = u.y - t, h = p * p + m * m, g = n + d;
|
|
1318
|
+
h <= g * g && a.push(l);
|
|
1319
|
+
}
|
|
1274
1320
|
}
|
|
1275
1321
|
}
|
|
1276
1322
|
}
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
return n >= r ? n * n + n + r : r * r + n;
|
|
1280
|
-
}
|
|
1281
|
-
}, A = 0, j = 0, M = 0, N = 0, P = 0, F = !0;
|
|
1282
|
-
function I(e, t, n) {
|
|
1323
|
+
}, P = 0, F = 0, I = 0, L = 0, R = 0, z = !0;
|
|
1324
|
+
function B(e, t, n) {
|
|
1283
1325
|
return {
|
|
1284
|
-
id:
|
|
1326
|
+
id: F++,
|
|
1285
1327
|
name: e,
|
|
1286
1328
|
create: t,
|
|
1287
1329
|
reset: n
|
|
1288
1330
|
};
|
|
1289
1331
|
}
|
|
1290
|
-
function
|
|
1332
|
+
function V(e) {
|
|
1291
1333
|
return {
|
|
1292
|
-
id:
|
|
1334
|
+
id: F++,
|
|
1293
1335
|
name: e,
|
|
1294
1336
|
tag: !0
|
|
1295
1337
|
};
|
|
1296
1338
|
}
|
|
1297
|
-
function
|
|
1339
|
+
function H(e) {
|
|
1298
1340
|
return {
|
|
1299
|
-
id:
|
|
1341
|
+
id: I++,
|
|
1300
1342
|
name: e
|
|
1301
1343
|
};
|
|
1302
1344
|
}
|
|
1303
|
-
function
|
|
1345
|
+
function U(e) {
|
|
1304
1346
|
return {
|
|
1305
|
-
id:
|
|
1347
|
+
id: L++,
|
|
1306
1348
|
name: e
|
|
1307
1349
|
};
|
|
1308
1350
|
}
|
|
1309
|
-
function
|
|
1351
|
+
function W(e, t) {
|
|
1310
1352
|
return {
|
|
1311
|
-
id:
|
|
1353
|
+
id: R++,
|
|
1312
1354
|
name: e,
|
|
1313
1355
|
init: t
|
|
1314
1356
|
};
|
|
1315
1357
|
}
|
|
1316
1358
|
//#endregion
|
|
1317
1359
|
//#region src/world.ts
|
|
1318
|
-
var
|
|
1360
|
+
var G = class {
|
|
1319
1361
|
nextId = 1;
|
|
1320
1362
|
maxEntities;
|
|
1321
1363
|
alive = /* @__PURE__ */ new Set();
|
|
@@ -1527,13 +1569,13 @@ var V = class {
|
|
|
1527
1569
|
t.isTracking() || (t.enableTracking(), this.trackedStores.push(t));
|
|
1528
1570
|
}
|
|
1529
1571
|
added(e) {
|
|
1530
|
-
return this.stores[e.id]?.iterAdded() ??
|
|
1572
|
+
return this.stores[e.id]?.iterAdded() ?? q;
|
|
1531
1573
|
}
|
|
1532
1574
|
removed(e) {
|
|
1533
|
-
return this.stores[e.id]?.iterRemoved() ??
|
|
1575
|
+
return this.stores[e.id]?.iterRemoved() ?? q;
|
|
1534
1576
|
}
|
|
1535
1577
|
changed(e) {
|
|
1536
|
-
return this.stores[e.id]?.iterChanged() ??
|
|
1578
|
+
return this.stores[e.id]?.iterChanged() ?? q;
|
|
1537
1579
|
}
|
|
1538
1580
|
markChanged(e, t) {
|
|
1539
1581
|
this.stores[t.id]?.markChanged(e);
|
|
@@ -1649,9 +1691,9 @@ var V = class {
|
|
|
1649
1691
|
return this.backrefsEnabled;
|
|
1650
1692
|
}
|
|
1651
1693
|
backrefs(e) {
|
|
1652
|
-
if (!this.backrefsEnabled || this.backrefEdges === null) return
|
|
1694
|
+
if (!this.backrefsEnabled || this.backrefEdges === null) return K;
|
|
1653
1695
|
let t = this.backrefEdges.get(e);
|
|
1654
|
-
if (t === void 0 || t.length === 0) return
|
|
1696
|
+
if (t === void 0 || t.length === 0) return K;
|
|
1655
1697
|
let n = !0;
|
|
1656
1698
|
for (let e = 0; e < t.length; e++) if (!this.alive.has(t[e])) {
|
|
1657
1699
|
n = !1;
|
|
@@ -1660,7 +1702,7 @@ var V = class {
|
|
|
1660
1702
|
if (n) return t;
|
|
1661
1703
|
let r = [];
|
|
1662
1704
|
for (let e = 0; e < t.length; e++) this.alive.has(t[e]) && r.push(t[e]);
|
|
1663
|
-
return r.length === 0 ?
|
|
1705
|
+
return r.length === 0 ? K : r;
|
|
1664
1706
|
}
|
|
1665
1707
|
unref(e, t) {
|
|
1666
1708
|
if (!this.backrefsEnabled || this.backrefEdges === null) return;
|
|
@@ -1671,8 +1713,8 @@ var V = class {
|
|
|
1671
1713
|
let a = this.holderToTargets?.get(t);
|
|
1672
1714
|
a !== void 0 && (a.delete(n), a.size === 0 && this.holderToTargets?.delete(t));
|
|
1673
1715
|
}
|
|
1674
|
-
},
|
|
1716
|
+
}, K = Object.freeze([]), q = [];
|
|
1675
1717
|
//#endregion
|
|
1676
|
-
export { e as Bitmask, t as CommandBuffer, D as ComponentStore, T as DEFAULT_MAX_ENTITIES, n as EventBus, i as IncrementalQuery, a as MigrationError, o as MigrationRegistry,
|
|
1718
|
+
export { e as Bitmask, t as CommandBuffer, D as ComponentStore, T as DEFAULT_MAX_ENTITIES, n as EventBus, i as IncrementalQuery, a as MigrationError, o as MigrationRegistry, P as NULL_REF, d as QueryEngine, f as Schedule, x as Serializer, N as SpatialHash, z as TAG_VALUE, G as World, l as any, B as defineComponent, U as defineEvent, W as defineLocal, H as defineResource, V as defineTag, w as jsonCodec, c as maybe, s as without };
|
|
1677
1719
|
|
|
1678
1720
|
//# sourceMappingURL=index.js.map
|