@oasys/oecs 0.1.0 → 0.1.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/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +375 -352
- package/dist/schedule.d.ts +3 -0
- package/dist/schedule.d.ts.map +1 -1
- package/dist/world.d.ts +11 -1
- package/dist/world.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
var X = (a, t, e) => t in a ? F(a, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[t] = e;
|
|
3
|
-
var l = (a, t, e) => X(a, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
-
class Y extends Error {
|
|
1
|
+
class R extends Error {
|
|
5
2
|
constructor(t, e, s) {
|
|
6
3
|
super(t), this.is_operational = e, this.context = s, this.name = this.constructor.name, Error.captureStackTrace(this, this.constructor);
|
|
7
4
|
}
|
|
8
5
|
}
|
|
9
|
-
var
|
|
10
|
-
class
|
|
6
|
+
var d = /* @__PURE__ */ ((a) => (a.EID_MAX_INDEX_OVERFLOW = "EID_MAX_INDEX_OVERFLOW", a.EID_MAX_GEN_OVERFLOW = "EID_MAX_GEN_OVERFLOW", a.COMPONENT_NOT_REGISTERED = "COMPONENT_NOT_REGISTERED", a.ENTITY_NOT_ALIVE = "ENTITY_NOT_ALIVE", a.CIRCULAR_SYSTEM_DEPENDENCY = "CIRCULAR_SYSTEM_DEPENDENCY", a.DUPLICATE_SYSTEM = "DUPLICATE_SYSTEM", a.ARCHETYPE_NOT_FOUND = "ARCHETYPE_NOT_FOUND", a))(d || {});
|
|
7
|
+
class u extends R {
|
|
11
8
|
constructor(t, e, s) {
|
|
12
9
|
super(e ?? t, !0, s), this.category = t;
|
|
13
10
|
}
|
|
14
11
|
}
|
|
15
|
-
var
|
|
16
|
-
class
|
|
12
|
+
var Y = /* @__PURE__ */ ((a) => (a.ASSERTION_FAIL_CONDITION = "ASSERTION_FAIL_CONDITION", a.VALIDATION_FAIL_CONDITION = "VALIDATION_FAIL_CONDITION", a))(Y || {});
|
|
13
|
+
class X extends R {
|
|
17
14
|
constructor(t, e, s) {
|
|
18
15
|
super(e, !1, s), this.category = t;
|
|
19
16
|
}
|
|
@@ -21,17 +18,17 @@ class G extends Y {
|
|
|
21
18
|
const P = (a) => Number.isInteger(a) && a >= 0;
|
|
22
19
|
function b(a, t, e) {
|
|
23
20
|
if (process.env.NODE_ENV !== "production" && !t(a))
|
|
24
|
-
throw new
|
|
25
|
-
|
|
21
|
+
throw new X(
|
|
22
|
+
Y.VALIDATION_FAIL_CONDITION,
|
|
26
23
|
`Expected value to meet validation: ${e}`
|
|
27
24
|
);
|
|
28
25
|
return a;
|
|
29
26
|
}
|
|
30
|
-
const
|
|
31
|
-
class
|
|
27
|
+
const C = 4;
|
|
28
|
+
class N {
|
|
29
|
+
_words;
|
|
32
30
|
constructor(t) {
|
|
33
|
-
|
|
34
|
-
this._words = t ?? new Array($).fill(0);
|
|
31
|
+
this._words = t ?? new Array(C).fill(0);
|
|
35
32
|
}
|
|
36
33
|
has(t) {
|
|
37
34
|
const e = t >>> 5;
|
|
@@ -56,8 +53,8 @@ class T {
|
|
|
56
53
|
contains(t) {
|
|
57
54
|
const e = t._words, s = this._words, n = s.length;
|
|
58
55
|
for (let r = 0; r < e.length; r++) {
|
|
59
|
-
const
|
|
60
|
-
if (
|
|
56
|
+
const i = e[r];
|
|
57
|
+
if (i !== 0 && (r >= n || (s[r] & i) !== i))
|
|
61
58
|
return !1;
|
|
62
59
|
}
|
|
63
60
|
return !0;
|
|
@@ -65,22 +62,22 @@ class T {
|
|
|
65
62
|
equals(t) {
|
|
66
63
|
const e = this._words, s = t._words, n = e.length > s.length ? e.length : s.length;
|
|
67
64
|
for (let r = 0; r < n; r++) {
|
|
68
|
-
const
|
|
69
|
-
if (
|
|
65
|
+
const i = r < e.length ? e[r] : 0, _ = r < s.length ? s[r] : 0;
|
|
66
|
+
if (i !== _) return !1;
|
|
70
67
|
}
|
|
71
68
|
return !0;
|
|
72
69
|
}
|
|
73
70
|
copy() {
|
|
74
|
-
return new
|
|
71
|
+
return new N(this._words.slice());
|
|
75
72
|
}
|
|
76
73
|
copy_with_set(t) {
|
|
77
74
|
const e = t >>> 5, s = e + 1, n = this._words.length > s ? this._words.length : s, r = new Array(n).fill(0);
|
|
78
|
-
for (let
|
|
79
|
-
return r[e] |= 1 << (t & 31), new
|
|
75
|
+
for (let i = 0; i < this._words.length; i++) r[i] = this._words[i];
|
|
76
|
+
return r[e] |= 1 << (t & 31), new N(r);
|
|
80
77
|
}
|
|
81
78
|
copy_with_clear(t) {
|
|
82
79
|
const e = this._words.slice(), s = t >>> 5;
|
|
83
|
-
return s < e.length && (e[s] &= ~(1 << (t & 31))), new
|
|
80
|
+
return s < e.length && (e[s] &= ~(1 << (t & 31))), new N(e);
|
|
84
81
|
}
|
|
85
82
|
/** FNV-1a hash. Skips trailing zero words so differently-sized arrays with the same bits hash equally. */
|
|
86
83
|
hash() {
|
|
@@ -100,8 +97,8 @@ class T {
|
|
|
100
97
|
if (n === 0) continue;
|
|
101
98
|
const r = s << 5;
|
|
102
99
|
for (; n !== 0; ) {
|
|
103
|
-
const
|
|
104
|
-
t(r + _), n ^=
|
|
100
|
+
const i = n & -n >>> 0, _ = 31 - Math.clz32(i);
|
|
101
|
+
t(r + _), n ^= i;
|
|
105
102
|
}
|
|
106
103
|
}
|
|
107
104
|
}
|
|
@@ -113,28 +110,28 @@ class T {
|
|
|
113
110
|
this._words = s;
|
|
114
111
|
}
|
|
115
112
|
}
|
|
116
|
-
const
|
|
113
|
+
const I = 20, k = (1 << I) - 1, j = k, G = 31 - I, D = (1 << G) - 1, $ = (a, t) => {
|
|
117
114
|
if (process.env.NODE_ENV !== "production") {
|
|
118
|
-
if (a < 0 || a >
|
|
119
|
-
throw new
|
|
120
|
-
if (t < 0 || t >
|
|
121
|
-
throw new
|
|
115
|
+
if (a < 0 || a > j)
|
|
116
|
+
throw new u(d.EID_MAX_INDEX_OVERFLOW);
|
|
117
|
+
if (t < 0 || t > D)
|
|
118
|
+
throw new u(d.EID_MAX_GEN_OVERFLOW);
|
|
122
119
|
}
|
|
123
|
-
return t <<
|
|
124
|
-
},
|
|
120
|
+
return t << I | a;
|
|
121
|
+
}, y = (a) => a & k, q = (a) => a >> I, z = (a) => b(
|
|
125
122
|
a,
|
|
126
123
|
P,
|
|
127
124
|
"ComponentID must be a non-negative integer"
|
|
128
|
-
),
|
|
125
|
+
), W = (a) => b(
|
|
129
126
|
a,
|
|
130
127
|
P,
|
|
131
128
|
"EventID must be a non-negative integer"
|
|
132
129
|
);
|
|
133
|
-
class
|
|
130
|
+
class B {
|
|
131
|
+
field_names;
|
|
132
|
+
columns;
|
|
133
|
+
reader;
|
|
134
134
|
constructor(t) {
|
|
135
|
-
l(this, "field_names");
|
|
136
|
-
l(this, "columns");
|
|
137
|
-
l(this, "reader");
|
|
138
135
|
this.field_names = t, this.columns = [];
|
|
139
136
|
for (let s = 0; s < t.length; s++)
|
|
140
137
|
this.columns.push([]);
|
|
@@ -160,36 +157,36 @@ class J {
|
|
|
160
157
|
t[e].length = 0;
|
|
161
158
|
}
|
|
162
159
|
}
|
|
163
|
-
const
|
|
160
|
+
const Q = (a) => b(
|
|
164
161
|
a,
|
|
165
162
|
P,
|
|
166
163
|
"ArchetypeID must be a non-negative integer"
|
|
167
164
|
);
|
|
168
|
-
class
|
|
165
|
+
class K {
|
|
166
|
+
id;
|
|
167
|
+
mask;
|
|
168
|
+
has_columns;
|
|
169
|
+
entity_ids = [];
|
|
170
|
+
length = 0;
|
|
171
|
+
edges = [];
|
|
172
|
+
// Sparse array indexed by ComponentID — undefined for absent components.
|
|
173
|
+
// Allows O(1) column group lookup by component.
|
|
174
|
+
column_groups = [];
|
|
175
|
+
// Dense list of ComponentIDs that have columns — used to iterate only
|
|
176
|
+
// data-bearing components in copy/add/remove operations.
|
|
177
|
+
_column_ids = [];
|
|
169
178
|
constructor(t, e, s) {
|
|
170
|
-
l(this, "id");
|
|
171
|
-
l(this, "mask");
|
|
172
|
-
l(this, "has_columns");
|
|
173
|
-
l(this, "entity_ids", []);
|
|
174
|
-
l(this, "length", 0);
|
|
175
|
-
l(this, "edges", []);
|
|
176
|
-
// Sparse array indexed by ComponentID — undefined for absent components.
|
|
177
|
-
// Allows O(1) column group lookup by component.
|
|
178
|
-
l(this, "column_groups", []);
|
|
179
|
-
// Dense list of ComponentIDs that have columns — used to iterate only
|
|
180
|
-
// data-bearing components in copy/add/remove operations.
|
|
181
|
-
l(this, "_column_ids", []);
|
|
182
179
|
if (this.id = t, this.mask = e, s)
|
|
183
180
|
for (let n = 0; n < s.length; n++) {
|
|
184
|
-
const r = s[n],
|
|
181
|
+
const r = s[n], i = new Array(r.field_names.length);
|
|
185
182
|
for (let h = 0; h < r.field_names.length; h++)
|
|
186
|
-
|
|
183
|
+
i[h] = [];
|
|
187
184
|
const _ = /* @__PURE__ */ Object.create(null);
|
|
188
185
|
for (let h = 0; h < r.field_names.length; h++)
|
|
189
|
-
_[r.field_names[h]] =
|
|
186
|
+
_[r.field_names[h]] = i[h];
|
|
190
187
|
this.column_groups[r.component_id] = {
|
|
191
188
|
layout: r,
|
|
192
|
-
columns:
|
|
189
|
+
columns: i,
|
|
193
190
|
record: _
|
|
194
191
|
}, this._column_ids.push(r.component_id);
|
|
195
192
|
}
|
|
@@ -211,14 +208,14 @@ class H {
|
|
|
211
208
|
get_column(t, e) {
|
|
212
209
|
const s = this.column_groups[t];
|
|
213
210
|
if (process.env.NODE_ENV !== "production" && !s)
|
|
214
|
-
throw new
|
|
215
|
-
|
|
211
|
+
throw new u(
|
|
212
|
+
d.COMPONENT_NOT_REGISTERED,
|
|
216
213
|
`Component ${t} not in archetype ${this.id}`
|
|
217
214
|
);
|
|
218
215
|
const n = s.layout.field_index[e];
|
|
219
216
|
if (process.env.NODE_ENV !== "production" && n === void 0)
|
|
220
|
-
throw new
|
|
221
|
-
|
|
217
|
+
throw new u(
|
|
218
|
+
d.COMPONENT_NOT_REGISTERED,
|
|
222
219
|
`Field "${e}" does not exist on component`
|
|
223
220
|
);
|
|
224
221
|
return s.columns[n];
|
|
@@ -232,8 +229,8 @@ class H {
|
|
|
232
229
|
const n = this.column_groups[e];
|
|
233
230
|
if (!n) return;
|
|
234
231
|
const { field_names: r } = n.layout;
|
|
235
|
-
for (let
|
|
236
|
-
n.columns[
|
|
232
|
+
for (let i = 0; i < r.length; i++)
|
|
233
|
+
n.columns[i][t] = s[r[i]];
|
|
237
234
|
}
|
|
238
235
|
read_field(t, e, s) {
|
|
239
236
|
const n = this.column_groups[e];
|
|
@@ -244,12 +241,12 @@ class H {
|
|
|
244
241
|
/** Copy all shared component columns from source archetype at src_row into dst_row. */
|
|
245
242
|
copy_shared_from(t, e, s) {
|
|
246
243
|
const n = t.column_groups, r = this._column_ids;
|
|
247
|
-
for (let
|
|
248
|
-
const _ = r[
|
|
244
|
+
for (let i = 0; i < r.length; i++) {
|
|
245
|
+
const _ = r[i], h = n[_];
|
|
249
246
|
if (!h) continue;
|
|
250
|
-
const
|
|
251
|
-
for (let c = 0; c <
|
|
252
|
-
|
|
247
|
+
const o = this.column_groups[_];
|
|
248
|
+
for (let c = 0; c < o.columns.length; c++)
|
|
249
|
+
o.columns[c][s] = h.columns[c][e];
|
|
253
250
|
}
|
|
254
251
|
}
|
|
255
252
|
/**
|
|
@@ -262,8 +259,8 @@ class H {
|
|
|
262
259
|
const s = this._column_ids;
|
|
263
260
|
for (let n = 0; n < s.length; n++) {
|
|
264
261
|
const r = this.column_groups[s[n]];
|
|
265
|
-
for (let
|
|
266
|
-
r.columns[
|
|
262
|
+
for (let i = 0; i < r.columns.length; i++)
|
|
263
|
+
r.columns[i].push(0);
|
|
267
264
|
}
|
|
268
265
|
return this.length++, e;
|
|
269
266
|
}
|
|
@@ -277,17 +274,17 @@ class H {
|
|
|
277
274
|
let s = -1;
|
|
278
275
|
const n = this._column_ids;
|
|
279
276
|
if (t !== e) {
|
|
280
|
-
this.entity_ids[t] = this.entity_ids[e], s =
|
|
277
|
+
this.entity_ids[t] = this.entity_ids[e], s = y(this.entity_ids[t]);
|
|
281
278
|
for (let r = 0; r < n.length; r++) {
|
|
282
|
-
const
|
|
283
|
-
for (let _ = 0; _ <
|
|
284
|
-
|
|
279
|
+
const i = this.column_groups[n[r]];
|
|
280
|
+
for (let _ = 0; _ < i.columns.length; _++)
|
|
281
|
+
i.columns[_][t] = i.columns[_][e], i.columns[_].pop();
|
|
285
282
|
}
|
|
286
283
|
} else
|
|
287
284
|
for (let r = 0; r < n.length; r++) {
|
|
288
|
-
const
|
|
289
|
-
for (let _ = 0; _ <
|
|
290
|
-
|
|
285
|
+
const i = this.column_groups[n[r]];
|
|
286
|
+
for (let _ = 0; _ < i.columns.length; _++)
|
|
287
|
+
i.columns[_].pop();
|
|
291
288
|
}
|
|
292
289
|
return this.entity_ids.pop(), this.length--, s;
|
|
293
290
|
}
|
|
@@ -300,7 +297,7 @@ class H {
|
|
|
300
297
|
remove_entity_tag(t) {
|
|
301
298
|
const e = this.length - 1;
|
|
302
299
|
let s = -1;
|
|
303
|
-
return t !== e && (this.entity_ids[t] = this.entity_ids[e], s =
|
|
300
|
+
return t !== e && (this.entity_ids[t] = this.entity_ids[e], s = y(this.entity_ids[t])), this.entity_ids.pop(), this.length--, s;
|
|
304
301
|
}
|
|
305
302
|
get_edge(t) {
|
|
306
303
|
return this.edges[t];
|
|
@@ -309,63 +306,63 @@ class H {
|
|
|
309
306
|
this.edges[t] = e;
|
|
310
307
|
}
|
|
311
308
|
}
|
|
312
|
-
function
|
|
309
|
+
function F(a, t, e) {
|
|
313
310
|
const s = a.get(t);
|
|
314
311
|
s !== void 0 ? s.push(e) : a.set(t, [e]);
|
|
315
312
|
}
|
|
316
|
-
const
|
|
317
|
-
class
|
|
313
|
+
const m = -1, V = Object.freeze(/* @__PURE__ */ Object.create(null));
|
|
314
|
+
class J {
|
|
315
|
+
// --- Entity ID management ---
|
|
316
|
+
// Generational slot allocator: entity_generations[index] holds the current
|
|
317
|
+
// generation for that slot. Free indices are recycled via a stack.
|
|
318
|
+
entity_generations = [];
|
|
319
|
+
entity_high_water = 0;
|
|
320
|
+
entity_free_indices = [];
|
|
321
|
+
entity_alive_count = 0;
|
|
322
|
+
// --- Component metadata ---
|
|
323
|
+
// Parallel array indexed by ComponentID: field_names and field_index
|
|
324
|
+
// for building archetype column layouts.
|
|
325
|
+
component_metas = [];
|
|
326
|
+
component_count = 0;
|
|
327
|
+
// --- Event channels ---
|
|
328
|
+
// Parallel array indexed by EventID: each channel holds SoA columns + reader.
|
|
329
|
+
event_channels = [];
|
|
330
|
+
event_count = 0;
|
|
331
|
+
// --- Archetype management ---
|
|
332
|
+
archetypes = [];
|
|
333
|
+
// Hash-bucketed lookup: BitSet.hash() → ArchetypeID[] for deduplication
|
|
334
|
+
archetype_map = /* @__PURE__ */ new Map();
|
|
335
|
+
next_archetype_id = 0;
|
|
336
|
+
// Inverted index: ComponentID → set of ArchetypeIDs containing that component.
|
|
337
|
+
// Used by get_matching_archetypes to start from the smallest set.
|
|
338
|
+
component_index = /* @__PURE__ */ new Map();
|
|
339
|
+
// Registered queries: the Store pushes newly-created archetypes into matching
|
|
340
|
+
// query result arrays, so queries are always up-to-date.
|
|
341
|
+
registered_queries = [];
|
|
342
|
+
empty_archetype_id;
|
|
343
|
+
// entity_index → ArchetypeID (UNASSIGNED = not in any archetype)
|
|
344
|
+
entity_archetype = [];
|
|
345
|
+
// entity_index → row within its archetype (UNASSIGNED = no row)
|
|
346
|
+
entity_row = [];
|
|
347
|
+
// --- Deferred operation buffers ---
|
|
348
|
+
// Flat parallel arrays: pending_add_ids[i], pending_add_defs[i], pending_add_values[i]
|
|
349
|
+
// describe one deferred add. No per-operation object allocation.
|
|
350
|
+
pending_destroy = [];
|
|
351
|
+
pending_add_ids = [];
|
|
352
|
+
pending_add_defs = [];
|
|
353
|
+
pending_add_values = [];
|
|
354
|
+
pending_remove_ids = [];
|
|
355
|
+
pending_remove_defs = [];
|
|
318
356
|
constructor() {
|
|
319
|
-
|
|
320
|
-
// Generational slot allocator: entity_generations[index] holds the current
|
|
321
|
-
// generation for that slot. Free indices are recycled via a stack.
|
|
322
|
-
l(this, "entity_generations", []);
|
|
323
|
-
l(this, "entity_high_water", 0);
|
|
324
|
-
l(this, "entity_free_indices", []);
|
|
325
|
-
l(this, "entity_alive_count", 0);
|
|
326
|
-
// --- Component metadata ---
|
|
327
|
-
// Parallel array indexed by ComponentID: field_names and field_index
|
|
328
|
-
// for building archetype column layouts.
|
|
329
|
-
l(this, "component_metas", []);
|
|
330
|
-
l(this, "component_count", 0);
|
|
331
|
-
// --- Event channels ---
|
|
332
|
-
// Parallel array indexed by EventID: each channel holds SoA columns + reader.
|
|
333
|
-
l(this, "event_channels", []);
|
|
334
|
-
l(this, "event_count", 0);
|
|
335
|
-
// --- Archetype management ---
|
|
336
|
-
l(this, "archetypes", []);
|
|
337
|
-
// Hash-bucketed lookup: BitSet.hash() → ArchetypeID[] for deduplication
|
|
338
|
-
l(this, "archetype_map", /* @__PURE__ */ new Map());
|
|
339
|
-
l(this, "next_archetype_id", 0);
|
|
340
|
-
// Inverted index: ComponentID → set of ArchetypeIDs containing that component.
|
|
341
|
-
// Used by get_matching_archetypes to start from the smallest set.
|
|
342
|
-
l(this, "component_index", /* @__PURE__ */ new Map());
|
|
343
|
-
// Registered queries: the Store pushes newly-created archetypes into matching
|
|
344
|
-
// query result arrays, so queries are always up-to-date.
|
|
345
|
-
l(this, "registered_queries", []);
|
|
346
|
-
l(this, "empty_archetype_id");
|
|
347
|
-
// entity_index → ArchetypeID (UNASSIGNED = not in any archetype)
|
|
348
|
-
l(this, "entity_archetype", []);
|
|
349
|
-
// entity_index → row within its archetype (UNASSIGNED = no row)
|
|
350
|
-
l(this, "entity_row", []);
|
|
351
|
-
// --- Deferred operation buffers ---
|
|
352
|
-
// Flat parallel arrays: pending_add_ids[i], pending_add_defs[i], pending_add_values[i]
|
|
353
|
-
// describe one deferred add. No per-operation object allocation.
|
|
354
|
-
l(this, "pending_destroy", []);
|
|
355
|
-
l(this, "pending_add_ids", []);
|
|
356
|
-
l(this, "pending_add_defs", []);
|
|
357
|
-
l(this, "pending_add_values", []);
|
|
358
|
-
l(this, "pending_remove_ids", []);
|
|
359
|
-
l(this, "pending_remove_defs", []);
|
|
360
|
-
this.empty_archetype_id = this.arch_get_or_create_from_mask(new T());
|
|
357
|
+
this.empty_archetype_id = this.arch_get_or_create_from_mask(new N());
|
|
361
358
|
}
|
|
362
359
|
// =======================================================
|
|
363
360
|
// Archetype graph
|
|
364
361
|
// =======================================================
|
|
365
362
|
arch_get(t) {
|
|
366
363
|
if (process.env.NODE_ENV !== "production" && (t < 0 || t >= this.archetypes.length))
|
|
367
|
-
throw new
|
|
368
|
-
|
|
364
|
+
throw new u(
|
|
365
|
+
d.ARCHETYPE_NOT_FOUND,
|
|
369
366
|
`Archetype with ID ${t} not found`
|
|
370
367
|
);
|
|
371
368
|
return this.archetypes[t];
|
|
@@ -381,25 +378,25 @@ class tt {
|
|
|
381
378
|
if (this.archetypes[s[h]].mask.equals(t))
|
|
382
379
|
return s[h];
|
|
383
380
|
}
|
|
384
|
-
const n =
|
|
381
|
+
const n = Q(this.next_archetype_id++), r = [];
|
|
385
382
|
t.for_each((h) => {
|
|
386
|
-
const
|
|
383
|
+
const o = h, c = this.component_metas[o];
|
|
387
384
|
c && c.field_names.length > 0 && r.push({
|
|
388
|
-
component_id:
|
|
385
|
+
component_id: o,
|
|
389
386
|
field_names: c.field_names,
|
|
390
387
|
field_index: c.field_index
|
|
391
388
|
});
|
|
392
389
|
});
|
|
393
|
-
const
|
|
394
|
-
this.archetypes.push(
|
|
395
|
-
const
|
|
396
|
-
let c = this.component_index.get(
|
|
397
|
-
c || (c = /* @__PURE__ */ new Set(), this.component_index.set(
|
|
390
|
+
const i = new K(n, t, r);
|
|
391
|
+
this.archetypes.push(i), F(this.archetype_map, e, n), t.for_each((h) => {
|
|
392
|
+
const o = h;
|
|
393
|
+
let c = this.component_index.get(o);
|
|
394
|
+
c || (c = /* @__PURE__ */ new Set(), this.component_index.set(o, c)), c.add(n);
|
|
398
395
|
});
|
|
399
396
|
const _ = this.registered_queries;
|
|
400
397
|
for (let h = 0; h < _.length; h++) {
|
|
401
|
-
const
|
|
402
|
-
|
|
398
|
+
const o = _[h];
|
|
399
|
+
i.matches(o.include_mask) && (!o.exclude_mask || !i.mask.overlaps(o.exclude_mask)) && (!o.any_of_mask || i.mask.overlaps(o.any_of_mask)) && o.result.push(i);
|
|
403
400
|
}
|
|
404
401
|
return n;
|
|
405
402
|
}
|
|
@@ -408,7 +405,7 @@ class tt {
|
|
|
408
405
|
const s = this.arch_get(t);
|
|
409
406
|
if (s.mask.has(e)) return t;
|
|
410
407
|
const n = s.get_edge(e);
|
|
411
|
-
if (
|
|
408
|
+
if (n?.add != null) return n.add;
|
|
412
409
|
const r = this.arch_get_or_create_from_mask(
|
|
413
410
|
s.mask.copy_with_set(e)
|
|
414
411
|
);
|
|
@@ -419,7 +416,7 @@ class tt {
|
|
|
419
416
|
const s = this.arch_get(t);
|
|
420
417
|
if (!s.mask.has(e)) return t;
|
|
421
418
|
const n = s.get_edge(e);
|
|
422
|
-
if (
|
|
419
|
+
if (n?.remove != null) return n.remove;
|
|
423
420
|
const r = this.arch_get_or_create_from_mask(
|
|
424
421
|
s.mask.copy_with_clear(e)
|
|
425
422
|
);
|
|
@@ -441,29 +438,29 @@ class tt {
|
|
|
441
438
|
create_entity() {
|
|
442
439
|
let t, e;
|
|
443
440
|
this.entity_free_indices.length > 0 ? (t = this.entity_free_indices.pop(), e = this.entity_generations[t]) : (t = this.entity_high_water++, this.entity_generations[t] = 0, e = 0), this.entity_alive_count++;
|
|
444
|
-
const s =
|
|
445
|
-
return this.entity_archetype[t] = this.empty_archetype_id, this.entity_row[t] =
|
|
441
|
+
const s = $(t, e);
|
|
442
|
+
return this.entity_archetype[t] = this.empty_archetype_id, this.entity_row[t] = m, s;
|
|
446
443
|
}
|
|
447
444
|
/** Immediately destroy an entity, removing it from its archetype. */
|
|
448
445
|
destroy_entity(t) {
|
|
449
446
|
if (!this.is_alive(t)) {
|
|
450
|
-
if (process.env.NODE_ENV !== "production") throw new
|
|
447
|
+
if (process.env.NODE_ENV !== "production") throw new u(d.ENTITY_NOT_ALIVE);
|
|
451
448
|
return;
|
|
452
449
|
}
|
|
453
|
-
const e =
|
|
454
|
-
if (s !==
|
|
455
|
-
const
|
|
456
|
-
|
|
450
|
+
const e = y(t), s = this.entity_row[e];
|
|
451
|
+
if (s !== m) {
|
|
452
|
+
const i = this.arch_get(this.entity_archetype[e]).remove_entity(s);
|
|
453
|
+
i !== -1 && (this.entity_row[i] = s);
|
|
457
454
|
}
|
|
458
|
-
this.entity_archetype[e] =
|
|
459
|
-
const n =
|
|
460
|
-
if (process.env.NODE_ENV !== "production" && n >=
|
|
461
|
-
throw new
|
|
462
|
-
this.entity_generations[e] = n + 1 &
|
|
455
|
+
this.entity_archetype[e] = m, this.entity_row[e] = m;
|
|
456
|
+
const n = q(t);
|
|
457
|
+
if (process.env.NODE_ENV !== "production" && n >= D)
|
|
458
|
+
throw new u(d.EID_MAX_GEN_OVERFLOW);
|
|
459
|
+
this.entity_generations[e] = n + 1 & D, this.entity_free_indices.push(e), this.entity_alive_count--;
|
|
463
460
|
}
|
|
464
461
|
is_alive(t) {
|
|
465
|
-
const e =
|
|
466
|
-
return e < this.entity_high_water && this.entity_generations[e] ===
|
|
462
|
+
const e = y(t);
|
|
463
|
+
return e < this.entity_high_water && this.entity_generations[e] === q(t);
|
|
467
464
|
}
|
|
468
465
|
get entity_count() {
|
|
469
466
|
return this.entity_alive_count;
|
|
@@ -473,25 +470,25 @@ class tt {
|
|
|
473
470
|
// =======================================================
|
|
474
471
|
destroy_entity_deferred(t) {
|
|
475
472
|
if (process.env.NODE_ENV !== "production" && !this.is_alive(t))
|
|
476
|
-
throw new
|
|
473
|
+
throw new u(d.ENTITY_NOT_ALIVE);
|
|
477
474
|
this.pending_destroy.push(t);
|
|
478
475
|
}
|
|
479
476
|
/** Flush all buffered entity destructions in batch. */
|
|
480
477
|
flush_destroyed() {
|
|
481
478
|
const t = this.pending_destroy;
|
|
482
479
|
if (t.length === 0) return;
|
|
483
|
-
const e = this.entity_archetype, s = this.entity_row, n = this.entity_generations, r = this.archetypes,
|
|
480
|
+
const e = this.entity_archetype, s = this.entity_row, n = this.entity_generations, r = this.archetypes, i = this.entity_high_water;
|
|
484
481
|
for (let _ = 0; _ < t.length; _++) {
|
|
485
|
-
const h = t[_],
|
|
486
|
-
if (
|
|
487
|
-
const
|
|
488
|
-
if (
|
|
489
|
-
const
|
|
490
|
-
|
|
482
|
+
const h = t[_], o = h & k, c = h >> I;
|
|
483
|
+
if (o >= i || n[o] !== c) continue;
|
|
484
|
+
const l = s[o];
|
|
485
|
+
if (l !== m) {
|
|
486
|
+
const p = r[e[o]], g = p.has_columns ? p.remove_entity(l) : p.remove_entity_tag(l);
|
|
487
|
+
g !== -1 && (s[g] = l);
|
|
491
488
|
}
|
|
492
|
-
if (e[
|
|
493
|
-
throw new
|
|
494
|
-
n[
|
|
489
|
+
if (e[o] = m, s[o] = m, process.env.NODE_ENV !== "production" && c >= D)
|
|
490
|
+
throw new u(d.EID_MAX_GEN_OVERFLOW);
|
|
491
|
+
n[o] = c + 1 & D, this.entity_free_indices.push(o), this.entity_alive_count--;
|
|
495
492
|
}
|
|
496
493
|
t.length = 0;
|
|
497
494
|
}
|
|
@@ -500,12 +497,12 @@ class tt {
|
|
|
500
497
|
}
|
|
501
498
|
add_component_deferred(t, e, s) {
|
|
502
499
|
if (process.env.NODE_ENV !== "production" && !this.is_alive(t))
|
|
503
|
-
throw new
|
|
504
|
-
this.pending_add_ids.push(t), this.pending_add_defs.push(e), this.pending_add_values.push(s ??
|
|
500
|
+
throw new u(d.ENTITY_NOT_ALIVE);
|
|
501
|
+
this.pending_add_ids.push(t), this.pending_add_defs.push(e), this.pending_add_values.push(s ?? V);
|
|
505
502
|
}
|
|
506
503
|
remove_component_deferred(t, e) {
|
|
507
504
|
if (process.env.NODE_ENV !== "production" && !this.is_alive(t))
|
|
508
|
-
throw new
|
|
505
|
+
throw new u(d.ENTITY_NOT_ALIVE);
|
|
509
506
|
this.pending_remove_ids.push(t), this.pending_remove_defs.push(e);
|
|
510
507
|
}
|
|
511
508
|
flush_structural() {
|
|
@@ -513,37 +510,37 @@ class tt {
|
|
|
513
510
|
}
|
|
514
511
|
/** Batch-apply all deferred component additions. */
|
|
515
512
|
_flush_adds() {
|
|
516
|
-
const t = this.pending_add_ids, e = this.pending_add_defs, s = this.pending_add_values, n = t.length, r = this.entity_archetype,
|
|
517
|
-
for (let
|
|
518
|
-
const
|
|
519
|
-
if (
|
|
520
|
-
const
|
|
521
|
-
if (
|
|
522
|
-
|
|
513
|
+
const t = this.pending_add_ids, e = this.pending_add_defs, s = this.pending_add_values, n = t.length, r = this.entity_archetype, i = this.entity_row, _ = this.entity_generations, h = this.archetypes, o = this.component_metas, c = this.entity_high_water;
|
|
514
|
+
for (let l = 0; l < n; l++) {
|
|
515
|
+
const p = t[l], g = p & k, w = p >> I;
|
|
516
|
+
if (g >= c || _[g] !== w) continue;
|
|
517
|
+
const T = r[g], v = e[l], f = h[T];
|
|
518
|
+
if (f.mask.has(v)) {
|
|
519
|
+
o[v].field_names.length > 0 && f.write_fields(i[g], v, s[l]);
|
|
523
520
|
continue;
|
|
524
521
|
}
|
|
525
|
-
const
|
|
526
|
-
if (
|
|
527
|
-
|
|
528
|
-
const
|
|
529
|
-
|
|
522
|
+
const O = this.arch_resolve_add(T, v), E = h[O], x = i[g], A = !E.has_columns && !f.has_columns, S = A ? E.add_entity_tag(p) : E.add_entity(p);
|
|
523
|
+
if (x !== m) {
|
|
524
|
+
A || E.copy_shared_from(f, x, S);
|
|
525
|
+
const U = A ? f.remove_entity_tag(x) : f.remove_entity(x);
|
|
526
|
+
U !== -1 && (i[U] = x);
|
|
530
527
|
}
|
|
531
|
-
|
|
528
|
+
o[v].field_names.length > 0 && E.write_fields(S, v, s[l]), r[g] = O, i[g] = S;
|
|
532
529
|
}
|
|
533
530
|
t.length = 0, e.length = 0, s.length = 0;
|
|
534
531
|
}
|
|
535
532
|
/** Batch-apply all deferred component removals. */
|
|
536
533
|
_flush_removes() {
|
|
537
|
-
const t = this.pending_remove_ids, e = this.pending_remove_defs, s = t.length, n = this.entity_archetype, r = this.entity_row,
|
|
538
|
-
for (let
|
|
539
|
-
const c = t[
|
|
540
|
-
if (
|
|
541
|
-
const
|
|
542
|
-
if (!
|
|
543
|
-
const
|
|
544
|
-
|
|
545
|
-
const
|
|
546
|
-
|
|
534
|
+
const t = this.pending_remove_ids, e = this.pending_remove_defs, s = t.length, n = this.entity_archetype, r = this.entity_row, i = this.entity_generations, _ = this.archetypes, h = this.entity_high_water;
|
|
535
|
+
for (let o = 0; o < s; o++) {
|
|
536
|
+
const c = t[o], l = c & k, p = c >> I;
|
|
537
|
+
if (l >= h || i[l] !== p) continue;
|
|
538
|
+
const g = n[l], w = e[o], T = _[g];
|
|
539
|
+
if (!T.mask.has(w)) continue;
|
|
540
|
+
const v = this.arch_resolve_remove(g, w), f = _[v], O = r[l], E = !f.has_columns && !T.has_columns, x = E ? f.add_entity_tag(c) : f.add_entity(c);
|
|
541
|
+
E || f.copy_shared_from(T, O, x);
|
|
542
|
+
const A = E ? T.remove_entity_tag(O) : T.remove_entity(O);
|
|
543
|
+
A !== -1 && (r[A] = O), n[l] = v, r[l] = x;
|
|
547
544
|
}
|
|
548
545
|
t.length = 0, e.length = 0;
|
|
549
546
|
}
|
|
@@ -554,19 +551,19 @@ class tt {
|
|
|
554
551
|
// Component registration
|
|
555
552
|
// =======================================================
|
|
556
553
|
register_component(t) {
|
|
557
|
-
const e =
|
|
554
|
+
const e = z(this.component_count++), s = t, n = /* @__PURE__ */ Object.create(null);
|
|
558
555
|
for (let r = 0; r < s.length; r++)
|
|
559
556
|
n[s[r]] = r;
|
|
560
557
|
return this.component_metas.push({ field_names: s, field_index: n }), e;
|
|
561
558
|
}
|
|
562
559
|
add_component(t, e, s) {
|
|
563
560
|
if (!this.is_alive(t)) {
|
|
564
|
-
if (process.env.NODE_ENV !== "production") throw new
|
|
561
|
+
if (process.env.NODE_ENV !== "production") throw new u(d.ENTITY_NOT_ALIVE);
|
|
565
562
|
return;
|
|
566
563
|
}
|
|
567
|
-
const n =
|
|
568
|
-
if (
|
|
569
|
-
|
|
564
|
+
const n = y(t), r = this.entity_archetype[n], i = this.arch_get(r);
|
|
565
|
+
if (i.has_component(e)) {
|
|
566
|
+
i.write_fields(
|
|
570
567
|
this.entity_row[n],
|
|
571
568
|
e,
|
|
572
569
|
s
|
|
@@ -576,11 +573,11 @@ class tt {
|
|
|
576
573
|
const _ = this.arch_resolve_add(
|
|
577
574
|
r,
|
|
578
575
|
e
|
|
579
|
-
), h = this.arch_get(_),
|
|
580
|
-
if (
|
|
581
|
-
h.copy_shared_from(
|
|
582
|
-
const
|
|
583
|
-
|
|
576
|
+
), h = this.arch_get(_), o = this.entity_row[n], c = h.add_entity(t);
|
|
577
|
+
if (o !== m) {
|
|
578
|
+
h.copy_shared_from(i, o, c);
|
|
579
|
+
const l = i.remove_entity(o);
|
|
580
|
+
l !== -1 && (this.entity_row[l] = o);
|
|
584
581
|
}
|
|
585
582
|
h.write_fields(
|
|
586
583
|
c,
|
|
@@ -591,80 +588,80 @@ class tt {
|
|
|
591
588
|
/** Add multiple components in one transition (resolves final archetype, then moves once). */
|
|
592
589
|
add_components(t, e) {
|
|
593
590
|
if (!this.is_alive(t)) {
|
|
594
|
-
if (process.env.NODE_ENV !== "production") throw new
|
|
591
|
+
if (process.env.NODE_ENV !== "production") throw new u(d.ENTITY_NOT_ALIVE);
|
|
595
592
|
return;
|
|
596
593
|
}
|
|
597
|
-
const s =
|
|
594
|
+
const s = y(t), n = this.entity_archetype[s];
|
|
598
595
|
let r = n;
|
|
599
|
-
for (let
|
|
596
|
+
for (let i = 0; i < e.length; i++)
|
|
600
597
|
r = this.arch_resolve_add(
|
|
601
598
|
r,
|
|
602
|
-
e[
|
|
599
|
+
e[i].def
|
|
603
600
|
);
|
|
604
601
|
if (r !== n) {
|
|
605
|
-
const
|
|
606
|
-
if (h !==
|
|
607
|
-
_.copy_shared_from(
|
|
608
|
-
const c =
|
|
602
|
+
const i = this.arch_get(n), _ = this.arch_get(r), h = this.entity_row[s], o = _.add_entity(t);
|
|
603
|
+
if (h !== m) {
|
|
604
|
+
_.copy_shared_from(i, h, o);
|
|
605
|
+
const c = i.remove_entity(h);
|
|
609
606
|
c !== -1 && (this.entity_row[c] = h);
|
|
610
607
|
}
|
|
611
608
|
for (let c = 0; c < e.length; c++)
|
|
612
609
|
_.write_fields(
|
|
613
|
-
|
|
610
|
+
o,
|
|
614
611
|
e[c].def,
|
|
615
|
-
e[c].values ??
|
|
612
|
+
e[c].values ?? V
|
|
616
613
|
);
|
|
617
|
-
this.entity_archetype[s] = r, this.entity_row[s] =
|
|
614
|
+
this.entity_archetype[s] = r, this.entity_row[s] = o;
|
|
618
615
|
} else {
|
|
619
|
-
const
|
|
616
|
+
const i = this.arch_get(n), _ = this.entity_row[s];
|
|
620
617
|
for (let h = 0; h < e.length; h++)
|
|
621
|
-
|
|
618
|
+
i.write_fields(
|
|
622
619
|
_,
|
|
623
620
|
e[h].def,
|
|
624
|
-
e[h].values ??
|
|
621
|
+
e[h].values ?? V
|
|
625
622
|
);
|
|
626
623
|
}
|
|
627
624
|
}
|
|
628
625
|
remove_component(t, e) {
|
|
629
626
|
if (!this.is_alive(t)) {
|
|
630
|
-
if (process.env.NODE_ENV !== "production") throw new
|
|
627
|
+
if (process.env.NODE_ENV !== "production") throw new u(d.ENTITY_NOT_ALIVE);
|
|
631
628
|
return;
|
|
632
629
|
}
|
|
633
|
-
const s =
|
|
630
|
+
const s = y(t), n = this.entity_archetype[s], r = this.arch_get(n);
|
|
634
631
|
if (!r.has_component(e)) return;
|
|
635
|
-
const
|
|
632
|
+
const i = this.arch_resolve_remove(
|
|
636
633
|
n,
|
|
637
634
|
e
|
|
638
|
-
), _ = this.arch_get(
|
|
639
|
-
_.copy_shared_from(r, h,
|
|
635
|
+
), _ = this.arch_get(i), h = this.entity_row[s], o = _.add_entity(t);
|
|
636
|
+
_.copy_shared_from(r, h, o);
|
|
640
637
|
const c = r.remove_entity(h);
|
|
641
|
-
c !== -1 && (this.entity_row[c] = h), this.entity_archetype[s] =
|
|
638
|
+
c !== -1 && (this.entity_row[c] = h), this.entity_archetype[s] = i, this.entity_row[s] = o;
|
|
642
639
|
}
|
|
643
640
|
/** Remove multiple components in one transition (resolves final archetype, then moves once). */
|
|
644
641
|
remove_components(t, e) {
|
|
645
642
|
if (!this.is_alive(t)) {
|
|
646
|
-
if (process.env.NODE_ENV !== "production") throw new
|
|
643
|
+
if (process.env.NODE_ENV !== "production") throw new u(d.ENTITY_NOT_ALIVE);
|
|
647
644
|
return;
|
|
648
645
|
}
|
|
649
|
-
const s =
|
|
646
|
+
const s = y(t), n = this.entity_archetype[s];
|
|
650
647
|
let r = n;
|
|
651
|
-
for (let
|
|
648
|
+
for (let l = 0; l < e.length; l++)
|
|
652
649
|
r = this.arch_resolve_remove(
|
|
653
650
|
r,
|
|
654
|
-
e[
|
|
651
|
+
e[l]
|
|
655
652
|
);
|
|
656
653
|
if (r === n) return;
|
|
657
|
-
const
|
|
658
|
-
_.copy_shared_from(
|
|
659
|
-
const c =
|
|
660
|
-
c !== -1 && (this.entity_row[c] = h), this.entity_archetype[s] = r, this.entity_row[s] =
|
|
654
|
+
const i = this.arch_get(n), _ = this.arch_get(r), h = this.entity_row[s], o = _.add_entity(t);
|
|
655
|
+
_.copy_shared_from(i, h, o);
|
|
656
|
+
const c = i.remove_entity(h);
|
|
657
|
+
c !== -1 && (this.entity_row[c] = h), this.entity_archetype[s] = r, this.entity_row[s] = o;
|
|
661
658
|
}
|
|
662
659
|
has_component(t, e) {
|
|
663
660
|
if (!this.is_alive(t)) {
|
|
664
|
-
if (process.env.NODE_ENV !== "production") throw new
|
|
661
|
+
if (process.env.NODE_ENV !== "production") throw new u(d.ENTITY_NOT_ALIVE);
|
|
665
662
|
return !1;
|
|
666
663
|
}
|
|
667
|
-
const s =
|
|
664
|
+
const s = y(t);
|
|
668
665
|
return this.arch_get(
|
|
669
666
|
this.entity_archetype[s]
|
|
670
667
|
).has_component(e);
|
|
@@ -674,11 +671,11 @@ class tt {
|
|
|
674
671
|
// =======================================================
|
|
675
672
|
get_entity_archetype(t) {
|
|
676
673
|
return this.arch_get(
|
|
677
|
-
this.entity_archetype[
|
|
674
|
+
this.entity_archetype[y(t)]
|
|
678
675
|
);
|
|
679
676
|
}
|
|
680
677
|
get_entity_row(t) {
|
|
681
|
-
return this.entity_row[
|
|
678
|
+
return this.entity_row[y(t)];
|
|
682
679
|
}
|
|
683
680
|
// =======================================================
|
|
684
681
|
// Query support
|
|
@@ -691,36 +688,36 @@ class tt {
|
|
|
691
688
|
get_matching_archetypes(t, e, s) {
|
|
692
689
|
const n = t._words;
|
|
693
690
|
let r = !1;
|
|
694
|
-
for (let
|
|
695
|
-
if (n[
|
|
691
|
+
for (let o = 0; o < n.length; o++)
|
|
692
|
+
if (n[o] !== 0) {
|
|
696
693
|
r = !0;
|
|
697
694
|
break;
|
|
698
695
|
}
|
|
699
696
|
if (!r)
|
|
700
697
|
return this.archetypes.filter(
|
|
701
|
-
(
|
|
698
|
+
(o) => (!e || !o.mask.overlaps(e)) && (!s || o.mask.overlaps(s))
|
|
702
699
|
);
|
|
703
|
-
let
|
|
704
|
-
for (let
|
|
705
|
-
let c = n[
|
|
700
|
+
let i, _ = !1;
|
|
701
|
+
for (let o = 0; o < n.length; o++) {
|
|
702
|
+
let c = n[o];
|
|
706
703
|
if (c === 0) continue;
|
|
707
|
-
const
|
|
704
|
+
const l = o << 5;
|
|
708
705
|
for (; c !== 0; ) {
|
|
709
|
-
const
|
|
710
|
-
c ^=
|
|
711
|
-
const
|
|
712
|
-
if (!
|
|
706
|
+
const p = c & -c >>> 0, g = l + (31 - Math.clz32(p));
|
|
707
|
+
c ^= p;
|
|
708
|
+
const w = this.component_index.get(g);
|
|
709
|
+
if (!w || w.size === 0) {
|
|
713
710
|
_ = !0;
|
|
714
711
|
break;
|
|
715
712
|
}
|
|
716
|
-
(!
|
|
713
|
+
(!i || w.size < i.size) && (i = w);
|
|
717
714
|
}
|
|
718
715
|
if (_) break;
|
|
719
716
|
}
|
|
720
|
-
if (_ || !
|
|
717
|
+
if (_ || !i) return [];
|
|
721
718
|
const h = [];
|
|
722
|
-
for (const
|
|
723
|
-
const c = this.arch_get(
|
|
719
|
+
for (const o of i) {
|
|
720
|
+
const c = this.arch_get(o);
|
|
724
721
|
c.matches(t) && (!e || !c.mask.overlaps(e)) && (!s || c.mask.overlaps(s)) && h.push(c);
|
|
725
722
|
}
|
|
726
723
|
return h;
|
|
@@ -749,7 +746,7 @@ class tt {
|
|
|
749
746
|
// Event channels
|
|
750
747
|
// =======================================================
|
|
751
748
|
register_event(t) {
|
|
752
|
-
const e =
|
|
749
|
+
const e = W(this.event_count++), s = new B(t);
|
|
753
750
|
return this.event_channels.push(s), e;
|
|
754
751
|
}
|
|
755
752
|
emit_event(t, e) {
|
|
@@ -767,44 +764,45 @@ class tt {
|
|
|
767
764
|
t[e].clear();
|
|
768
765
|
}
|
|
769
766
|
}
|
|
770
|
-
var
|
|
771
|
-
const
|
|
767
|
+
var Z = /* @__PURE__ */ ((a) => (a.PRE_STARTUP = "PRE_STARTUP", a.STARTUP = "STARTUP", a.POST_STARTUP = "POST_STARTUP", a.FIXED_UPDATE = "FIXED_UPDATE", a.PRE_UPDATE = "PRE_UPDATE", a.UPDATE = "UPDATE", a.POST_UPDATE = "POST_UPDATE", a))(Z || {});
|
|
768
|
+
const M = [
|
|
772
769
|
"PRE_STARTUP",
|
|
773
770
|
"STARTUP",
|
|
774
771
|
"POST_STARTUP"
|
|
775
772
|
/* POST_STARTUP */
|
|
776
|
-
],
|
|
773
|
+
], L = [
|
|
777
774
|
"PRE_UPDATE",
|
|
778
775
|
"UPDATE",
|
|
779
776
|
"POST_UPDATE"
|
|
780
777
|
/* POST_UPDATE */
|
|
781
778
|
];
|
|
782
|
-
class
|
|
779
|
+
class H {
|
|
780
|
+
label_systems = /* @__PURE__ */ new Map();
|
|
781
|
+
sorted_cache = /* @__PURE__ */ new Map();
|
|
782
|
+
system_index = /* @__PURE__ */ new Map();
|
|
783
|
+
next_insertion_order = 0;
|
|
783
784
|
constructor() {
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
l(this, "next_insertion_order", 0);
|
|
785
|
+
for (let t = 0; t < M.length; t++)
|
|
786
|
+
this.label_systems.set(M[t], []);
|
|
787
|
+
this.label_systems.set("FIXED_UPDATE", []);
|
|
788
788
|
for (let t = 0; t < L.length; t++)
|
|
789
789
|
this.label_systems.set(L[t], []);
|
|
790
|
-
for (let t = 0; t < U.length; t++)
|
|
791
|
-
this.label_systems.set(U[t], []);
|
|
792
790
|
}
|
|
793
791
|
add_systems(t, ...e) {
|
|
794
792
|
for (const s of e) {
|
|
795
793
|
const n = "system" in s ? s.system : s, r = "system" in s ? s.ordering : void 0;
|
|
796
794
|
if (process.env.NODE_ENV !== "production" && this.system_index.has(n))
|
|
797
|
-
throw new
|
|
798
|
-
|
|
795
|
+
throw new u(
|
|
796
|
+
d.DUPLICATE_SYSTEM,
|
|
799
797
|
`System ${n.id} is already scheduled`
|
|
800
798
|
);
|
|
801
|
-
const
|
|
799
|
+
const i = {
|
|
802
800
|
descriptor: n,
|
|
803
801
|
insertion_order: this.next_insertion_order++,
|
|
804
|
-
before: new Set(
|
|
805
|
-
after: new Set(
|
|
802
|
+
before: new Set(r?.before ?? []),
|
|
803
|
+
after: new Set(r?.after ?? [])
|
|
806
804
|
};
|
|
807
|
-
this.label_systems.get(t).push(
|
|
805
|
+
this.label_systems.get(t).push(i), this.system_index.set(n, t), this.sorted_cache.delete(t);
|
|
808
806
|
}
|
|
809
807
|
}
|
|
810
808
|
remove_system(t) {
|
|
@@ -814,19 +812,28 @@ class st {
|
|
|
814
812
|
if (n !== -1) {
|
|
815
813
|
const r = s.length - 1;
|
|
816
814
|
n !== r && (s[n] = s[r]), s.pop();
|
|
817
|
-
for (const
|
|
818
|
-
|
|
815
|
+
for (const i of s)
|
|
816
|
+
i.before.delete(t), i.after.delete(t);
|
|
819
817
|
}
|
|
820
818
|
this.system_index.delete(t), this.sorted_cache.delete(e);
|
|
821
819
|
}
|
|
822
820
|
run_startup(t) {
|
|
823
|
-
for (const e of
|
|
821
|
+
for (const e of M)
|
|
824
822
|
this.run_label(e, t, 0);
|
|
825
823
|
}
|
|
826
824
|
run_update(t, e) {
|
|
827
|
-
for (const s of
|
|
825
|
+
for (const s of L)
|
|
828
826
|
this.run_label(s, t, e);
|
|
829
827
|
}
|
|
828
|
+
run_fixed_update(t, e) {
|
|
829
|
+
this.run_label("FIXED_UPDATE", t, e);
|
|
830
|
+
}
|
|
831
|
+
has_fixed_systems() {
|
|
832
|
+
return this.label_systems.get(
|
|
833
|
+
"FIXED_UPDATE"
|
|
834
|
+
/* FIXED_UPDATE */
|
|
835
|
+
).length > 0;
|
|
836
|
+
}
|
|
830
837
|
get_all_systems() {
|
|
831
838
|
const t = [];
|
|
832
839
|
for (const e of this.label_systems.values())
|
|
@@ -860,52 +867,52 @@ class st {
|
|
|
860
867
|
*/
|
|
861
868
|
topological_sort(t, e) {
|
|
862
869
|
if (t.length === 0) return [];
|
|
863
|
-
const s = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(),
|
|
864
|
-
for (const
|
|
865
|
-
s.set(
|
|
866
|
-
for (const
|
|
867
|
-
for (const c of
|
|
868
|
-
|
|
869
|
-
for (const c of
|
|
870
|
-
|
|
870
|
+
const s = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Set();
|
|
871
|
+
for (const o of t)
|
|
872
|
+
s.set(o.descriptor, /* @__PURE__ */ new Set()), n.set(o.descriptor, 0), r.set(o.descriptor, o.insertion_order), i.add(o.descriptor);
|
|
873
|
+
for (const o of t) {
|
|
874
|
+
for (const c of o.before)
|
|
875
|
+
i.has(c) && (s.get(o.descriptor).add(c), n.set(c, n.get(c) + 1));
|
|
876
|
+
for (const c of o.after)
|
|
877
|
+
i.has(c) && (s.get(c).add(o.descriptor), n.set(o.descriptor, n.get(o.descriptor) + 1));
|
|
871
878
|
}
|
|
872
879
|
let _ = [];
|
|
873
|
-
for (const
|
|
874
|
-
n.get(
|
|
875
|
-
_.sort((
|
|
880
|
+
for (const o of t)
|
|
881
|
+
n.get(o.descriptor) === 0 && _.push(o.descriptor);
|
|
882
|
+
_.sort((o, c) => r.get(c) - r.get(o));
|
|
876
883
|
const h = [];
|
|
877
884
|
for (; _.length > 0; ) {
|
|
878
|
-
const
|
|
879
|
-
h.push(
|
|
880
|
-
for (const c of s.get(
|
|
881
|
-
const
|
|
882
|
-
n.set(c,
|
|
885
|
+
const o = _.pop();
|
|
886
|
+
h.push(o);
|
|
887
|
+
for (const c of s.get(o)) {
|
|
888
|
+
const l = n.get(c) - 1;
|
|
889
|
+
n.set(c, l), l === 0 && _.push(c);
|
|
883
890
|
}
|
|
884
|
-
_.sort((c,
|
|
891
|
+
_.sort((c, l) => r.get(l) - r.get(c));
|
|
885
892
|
}
|
|
886
893
|
if (h.length !== t.length) {
|
|
887
|
-
const
|
|
888
|
-
throw new
|
|
889
|
-
|
|
894
|
+
const o = new Set(h), c = t.filter((l) => !o.has(l.descriptor)).map((l) => `system_${l.descriptor.id}`);
|
|
895
|
+
throw new u(
|
|
896
|
+
d.CIRCULAR_SYSTEM_DEPENDENCY,
|
|
890
897
|
`Circular system dependency detected in ${e}: [${c.join(", ")}]`
|
|
891
898
|
);
|
|
892
899
|
}
|
|
893
900
|
return h;
|
|
894
901
|
}
|
|
895
902
|
}
|
|
896
|
-
const
|
|
897
|
-
class
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
this._archetypes = t, this._defs = e, this._resolver = s, this._include = n, this._exclude = r, this._any_of =
|
|
903
|
+
const tt = Object.freeze(/* @__PURE__ */ Object.create(null));
|
|
904
|
+
class et {
|
|
905
|
+
_archetypes;
|
|
906
|
+
_defs;
|
|
907
|
+
_resolver;
|
|
908
|
+
_include;
|
|
909
|
+
_exclude;
|
|
910
|
+
_any_of;
|
|
911
|
+
// Pre-allocated args buffer for each() — avoids allocating a new array per
|
|
912
|
+
// archetype. Holds [columnGroup0, columnGroup1, ..., entityCount].
|
|
913
|
+
_args_buf;
|
|
914
|
+
constructor(t, e, s, n, r, i) {
|
|
915
|
+
this._archetypes = t, this._defs = e, this._resolver = s, this._include = n, this._exclude = r, this._any_of = i, this._args_buf = new Array(e.length + 1);
|
|
909
916
|
}
|
|
910
917
|
/** Number of matching archetypes (including empty ones). */
|
|
911
918
|
get length() {
|
|
@@ -935,10 +942,10 @@ class rt {
|
|
|
935
942
|
each(t) {
|
|
936
943
|
const e = this._archetypes, s = this._defs, n = this._args_buf;
|
|
937
944
|
for (let r = 0; r < e.length; r++) {
|
|
938
|
-
const
|
|
945
|
+
const i = e[r], _ = i.entity_count;
|
|
939
946
|
if (_ !== 0) {
|
|
940
947
|
for (let h = 0; h < s.length; h++)
|
|
941
|
-
n[h] =
|
|
948
|
+
n[h] = i.get_column_group(s[h]);
|
|
942
949
|
n[s.length] = _, t.apply(null, n);
|
|
943
950
|
}
|
|
944
951
|
}
|
|
@@ -957,7 +964,7 @@ class rt {
|
|
|
957
964
|
}
|
|
958
965
|
/** Exclude archetypes that have any of these components. */
|
|
959
966
|
not(...t) {
|
|
960
|
-
const e = this._exclude ? this._exclude.copy() : new
|
|
967
|
+
const e = this._exclude ? this._exclude.copy() : new N();
|
|
961
968
|
for (let s = 0; s < t.length; s++) e.set(t[s]);
|
|
962
969
|
return this._resolver._resolve_query(
|
|
963
970
|
this._include,
|
|
@@ -968,7 +975,7 @@ class rt {
|
|
|
968
975
|
}
|
|
969
976
|
/** Require at least one of these components. */
|
|
970
977
|
or(...t) {
|
|
971
|
-
const e = this._any_of ? this._any_of.copy() : new
|
|
978
|
+
const e = this._any_of ? this._any_of.copy() : new N();
|
|
972
979
|
for (let s = 0; s < t.length; s++) e.set(t[s]);
|
|
973
980
|
return this._resolver._resolve_query(
|
|
974
981
|
this._include,
|
|
@@ -978,19 +985,19 @@ class rt {
|
|
|
978
985
|
);
|
|
979
986
|
}
|
|
980
987
|
}
|
|
981
|
-
class
|
|
988
|
+
class st {
|
|
982
989
|
constructor(t) {
|
|
983
990
|
this._resolver = t;
|
|
984
991
|
}
|
|
985
992
|
every(...t) {
|
|
986
|
-
const e = new
|
|
993
|
+
const e = new N();
|
|
987
994
|
for (let s = 0; s < t.length; s++) e.set(t[s]);
|
|
988
995
|
return this._resolver._resolve_query(e, null, null, t);
|
|
989
996
|
}
|
|
990
997
|
}
|
|
991
|
-
class
|
|
998
|
+
class nt {
|
|
999
|
+
store;
|
|
992
1000
|
constructor(t) {
|
|
993
|
-
l(this, "store");
|
|
994
1001
|
this.store = t;
|
|
995
1002
|
}
|
|
996
1003
|
create_entity() {
|
|
@@ -1001,8 +1008,8 @@ class it {
|
|
|
1001
1008
|
return n.read_field(r, t, s);
|
|
1002
1009
|
}
|
|
1003
1010
|
set_field(t, e, s, n) {
|
|
1004
|
-
const r = this.store.get_entity_archetype(e),
|
|
1005
|
-
_[
|
|
1011
|
+
const r = this.store.get_entity_archetype(e), i = this.store.get_entity_row(e), _ = r.get_column(t, s);
|
|
1012
|
+
_[i] = n;
|
|
1006
1013
|
}
|
|
1007
1014
|
/** Buffer an entity for deferred destruction (applied at phase flush). */
|
|
1008
1015
|
destroy_entity(t) {
|
|
@@ -1012,7 +1019,7 @@ class it {
|
|
|
1012
1019
|
this.store.flush_destroyed();
|
|
1013
1020
|
}
|
|
1014
1021
|
add_component(t, e, s) {
|
|
1015
|
-
return this.store.add_component_deferred(t, e, s ??
|
|
1022
|
+
return this.store.add_component_deferred(t, e, s ?? tt), this;
|
|
1016
1023
|
}
|
|
1017
1024
|
remove_component(t, e) {
|
|
1018
1025
|
return this.store.remove_component_deferred(t, e), this;
|
|
@@ -1028,24 +1035,37 @@ class it {
|
|
|
1028
1035
|
return this.store.get_event_reader(t);
|
|
1029
1036
|
}
|
|
1030
1037
|
}
|
|
1031
|
-
const
|
|
1038
|
+
const rt = (a) => b(
|
|
1032
1039
|
a,
|
|
1033
1040
|
P,
|
|
1034
1041
|
"SystemID must be a non-negative integer"
|
|
1035
|
-
),
|
|
1036
|
-
class
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1042
|
+
), it = Object.freeze(/* @__PURE__ */ Object.create(null));
|
|
1043
|
+
class ot {
|
|
1044
|
+
store;
|
|
1045
|
+
schedule;
|
|
1046
|
+
ctx;
|
|
1047
|
+
systems = /* @__PURE__ */ new Set();
|
|
1048
|
+
next_system_id = 0;
|
|
1049
|
+
// Fixed timestep accumulator
|
|
1050
|
+
_fixed_timestep;
|
|
1051
|
+
_accumulator = 0;
|
|
1052
|
+
_max_fixed_steps;
|
|
1053
|
+
// Query deduplication: hash(include, exclude, any_of) → bucket of cache entries.
|
|
1054
|
+
// Multiple queries can share the same hash (collision), so each bucket is an array.
|
|
1055
|
+
query_cache = /* @__PURE__ */ new Map();
|
|
1056
|
+
// Reusable BitSet for building query masks — avoids allocation per query() call
|
|
1057
|
+
scratch_mask = new N();
|
|
1058
|
+
constructor(t) {
|
|
1059
|
+
this.store = new J(), this.schedule = new H(), this.ctx = new nt(this.store), this._fixed_timestep = t?.fixed_timestep ?? 1 / 60, this._max_fixed_steps = t?.max_fixed_steps ?? 4;
|
|
1060
|
+
}
|
|
1061
|
+
get fixed_timestep() {
|
|
1062
|
+
return this._fixed_timestep;
|
|
1063
|
+
}
|
|
1064
|
+
set fixed_timestep(t) {
|
|
1065
|
+
this._fixed_timestep = t;
|
|
1066
|
+
}
|
|
1067
|
+
get fixed_alpha() {
|
|
1068
|
+
return this._accumulator / this._fixed_timestep;
|
|
1049
1069
|
}
|
|
1050
1070
|
register_component(t) {
|
|
1051
1071
|
return this.store.register_component(t);
|
|
@@ -1072,7 +1092,7 @@ class at {
|
|
|
1072
1092
|
return this.store.entity_count;
|
|
1073
1093
|
}
|
|
1074
1094
|
add_component(t, e, s) {
|
|
1075
|
-
this.store.add_component(t, e, s ??
|
|
1095
|
+
this.store.add_component(t, e, s ?? it);
|
|
1076
1096
|
}
|
|
1077
1097
|
add_components(t, e) {
|
|
1078
1098
|
this.store.add_components(t, e);
|
|
@@ -1102,32 +1122,32 @@ class at {
|
|
|
1102
1122
|
}
|
|
1103
1123
|
/** QueryResolver implementation — creates or retrieves a cached Query. */
|
|
1104
1124
|
_resolve_query(t, e, s, n) {
|
|
1105
|
-
const r = t.hash(),
|
|
1106
|
-
if (
|
|
1125
|
+
const r = t.hash(), i = e ? e.hash() : 0, _ = s ? s.hash() : 0, h = r ^ Math.imul(i, 2654435769) ^ Math.imul(_, 1367130551) | 0, o = this._find_cached(h, t, e, s);
|
|
1126
|
+
if (o !== void 0) return o.query;
|
|
1107
1127
|
const c = this.store.register_query(
|
|
1108
1128
|
t,
|
|
1109
1129
|
e ?? void 0,
|
|
1110
1130
|
s ?? void 0
|
|
1111
|
-
),
|
|
1131
|
+
), l = new et(
|
|
1112
1132
|
c,
|
|
1113
1133
|
n,
|
|
1114
1134
|
this,
|
|
1115
1135
|
t.copy(),
|
|
1116
|
-
|
|
1117
|
-
|
|
1136
|
+
e?.copy() ?? null,
|
|
1137
|
+
s?.copy() ?? null
|
|
1118
1138
|
);
|
|
1119
|
-
return
|
|
1139
|
+
return F(this.query_cache, h, {
|
|
1120
1140
|
include_mask: t.copy(),
|
|
1121
|
-
exclude_mask:
|
|
1122
|
-
any_of_mask:
|
|
1123
|
-
query:
|
|
1124
|
-
}),
|
|
1141
|
+
exclude_mask: e?.copy() ?? null,
|
|
1142
|
+
any_of_mask: s?.copy() ?? null,
|
|
1143
|
+
query: l
|
|
1144
|
+
}), l;
|
|
1125
1145
|
}
|
|
1126
1146
|
_find_cached(t, e, s, n) {
|
|
1127
1147
|
const r = this.query_cache.get(t);
|
|
1128
1148
|
if (r)
|
|
1129
|
-
for (let
|
|
1130
|
-
const _ = r[
|
|
1149
|
+
for (let i = 0; i < r.length; i++) {
|
|
1150
|
+
const _ = r[i];
|
|
1131
1151
|
if (!(!_.include_mask.equals(e) || !(s === null ? _.exclude_mask === null : _.exclude_mask !== null && _.exclude_mask.equals(s)) || !(n === null ? _.any_of_mask === null : _.any_of_mask !== null && _.any_of_mask.equals(n))))
|
|
1132
1152
|
return _;
|
|
1133
1153
|
}
|
|
@@ -1135,11 +1155,11 @@ class at {
|
|
|
1135
1155
|
register_system(t, e) {
|
|
1136
1156
|
let s;
|
|
1137
1157
|
if (typeof t == "function") {
|
|
1138
|
-
const
|
|
1139
|
-
s = { fn: (h,
|
|
1158
|
+
const i = e(new st(this)), _ = this.ctx;
|
|
1159
|
+
s = { fn: (h, o) => t(i, _, o) };
|
|
1140
1160
|
} else
|
|
1141
1161
|
s = t;
|
|
1142
|
-
const n =
|
|
1162
|
+
const n = rt(this.next_system_id++), r = Object.freeze(
|
|
1143
1163
|
Object.assign({ id: n }, s)
|
|
1144
1164
|
);
|
|
1145
1165
|
return this.systems.add(r), r;
|
|
@@ -1148,35 +1168,38 @@ class at {
|
|
|
1148
1168
|
return this.schedule.add_systems(t, ...e), this;
|
|
1149
1169
|
}
|
|
1150
1170
|
remove_system(t) {
|
|
1151
|
-
|
|
1152
|
-
this.schedule.remove_system(t), (e = t.on_removed) == null || e.call(t), this.systems.delete(t);
|
|
1171
|
+
this.schedule.remove_system(t), t.on_removed?.(), this.systems.delete(t);
|
|
1153
1172
|
}
|
|
1154
1173
|
get system_count() {
|
|
1155
1174
|
return this.systems.size;
|
|
1156
1175
|
}
|
|
1157
1176
|
startup() {
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
(t = e.on_added) == null || t.call(e, this.store);
|
|
1177
|
+
for (const t of this.systems.values())
|
|
1178
|
+
t.on_added?.(this.store);
|
|
1161
1179
|
this.schedule.run_startup(this.ctx);
|
|
1162
1180
|
}
|
|
1163
1181
|
update(t) {
|
|
1164
|
-
this.store.clear_events(), this.schedule.
|
|
1182
|
+
if (this.store.clear_events(), this.schedule.has_fixed_systems()) {
|
|
1183
|
+
this._accumulator += t;
|
|
1184
|
+
const e = this._max_fixed_steps * this._fixed_timestep;
|
|
1185
|
+
for (this._accumulator > e && (this._accumulator = e); this._accumulator >= this._fixed_timestep; )
|
|
1186
|
+
this.schedule.run_fixed_update(this.ctx, this._fixed_timestep), this._accumulator -= this._fixed_timestep;
|
|
1187
|
+
}
|
|
1188
|
+
this.schedule.run_update(this.ctx, t);
|
|
1165
1189
|
}
|
|
1166
1190
|
flush() {
|
|
1167
1191
|
this.ctx.flush();
|
|
1168
1192
|
}
|
|
1169
1193
|
dispose() {
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
(t = s.dispose) == null || t.call(s), (e = s.on_removed) == null || e.call(s);
|
|
1194
|
+
for (const t of this.systems.values())
|
|
1195
|
+
t.dispose?.(), t.on_removed?.();
|
|
1173
1196
|
this.systems.clear(), this.schedule.clear();
|
|
1174
1197
|
}
|
|
1175
1198
|
}
|
|
1176
1199
|
export {
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1200
|
+
et as Query,
|
|
1201
|
+
st as QueryBuilder,
|
|
1202
|
+
Z as SCHEDULE,
|
|
1203
|
+
nt as SystemContext,
|
|
1204
|
+
ot as World
|
|
1182
1205
|
};
|