@oasys/oecs 0.1.0 → 0.1.2

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