@daneren2005/shared-memory-ecs 1.8.2 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,17 +1,17 @@
1
- import { _ as e, a as t, c as n, d as r, f as i, g as a, h as o, i as s, l as c, m as l, n as u, o as d, p as f, r as p, s as m, t as h, u as g, v as _ } from "./create-system-worker-C4aS3-3R.js";
2
- import v from "@daneren2005/shared-memory-objects/memory-heap";
3
- import { MAX_BYTE_OFFSET_LENGTH as y } from "@daneren2005/shared-memory-objects/utils/pointer";
1
+ import { _ as e, a as t, c as n, d as r, f as i, g as a, h as o, i as s, l as c, m as l, n as u, o as d, p as f, r as p, s as m, t as ee, u as te, v as h, y as g } from "./create-system-worker-CNpRs2FO.js";
2
+ import ne from "@daneren2005/shared-memory-objects/memory-heap";
3
+ import { MAX_BYTE_OFFSET_LENGTH as _ } from "@daneren2005/shared-memory-objects/utils/pointer";
4
4
  //#region \0rolldown/runtime.js
5
- var b = Object.create, x = Object.defineProperty, S = Object.getOwnPropertyDescriptor, C = Object.getOwnPropertyNames, w = Object.getPrototypeOf, T = Object.prototype.hasOwnProperty, E = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t.exports), D = (e, t, n, r) => {
6
- if (t && typeof t == "object" || typeof t == "function") for (var i = C(t), a = 0, o = i.length, s; a < o; a++) s = i[a], !T.call(e, s) && s !== n && x(e, s, {
5
+ var v = Object.create, y = Object.defineProperty, re = Object.getOwnPropertyDescriptor, b = Object.getOwnPropertyNames, x = Object.getPrototypeOf, S = Object.prototype.hasOwnProperty, ie = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t.exports), ae = (e, t, n, r) => {
6
+ if (t && typeof t == "object" || typeof t == "function") for (var i = b(t), a = 0, o = i.length, s; a < o; a++) s = i[a], !S.call(e, s) && s !== n && y(e, s, {
7
7
  get: ((e) => t[e]).bind(null, s),
8
- enumerable: !(r = S(t, s)) || r.enumerable
8
+ enumerable: !(r = re(t, s)) || r.enumerable
9
9
  });
10
10
  return e;
11
- }, O = /* @__PURE__ */ ((e, t, n) => (n = e == null ? {} : b(w(e)), D(t || !e || !e.__esModule || !T.call(e, "default") ? x(n, "default", {
11
+ }, C = /* @__PURE__ */ ((e, t, n) => (n = e == null ? {} : v(x(e)), ae(t || !e || !e.__esModule || !S.call(e, "default") ? y(n, "default", {
12
12
  value: e,
13
13
  enumerable: !0
14
- }) : n, e)))((/* @__PURE__ */ E(((e, t) => {
14
+ }) : n, e)))((/* @__PURE__ */ ie(((e, t) => {
15
15
  var n = Object.prototype.hasOwnProperty, r = "~";
16
16
  function i() {}
17
17
  Object.create && (i.prototype = Object.create(null), new i().__proto__ || (r = !1));
@@ -98,14 +98,18 @@ var b = Object.create, x = Object.defineProperty, S = Object.getOwnPropertyDescr
98
98
  var t;
99
99
  return e ? (t = r ? r + e : e, this._events[t] && s(this, t)) : (this._events = new i(), this._eventsCount = 0), this;
100
100
  }, c.prototype.off = c.prototype.removeListener, c.prototype.addListener = c.prototype.on, c.prefixed = r, c.EventEmitter = c, t !== void 0 && (t.exports = c);
101
- })))(), 1), k = class extends O.default {
101
+ })))(), 1), w = class extends C.default {
102
102
  world;
103
103
  name;
104
104
  currentDelta = 0;
105
105
  deltaBetweenRuns;
106
106
  firstRun;
107
+ reads;
108
+ writes;
109
+ exclusive;
110
+ scheduledGameTime;
107
111
  constructor(e, t = { name: "System" }) {
108
- super(), this.name = t.name, this.world = e, this.deltaBetweenRuns = t.deltaBetweenRuns ?? 0, this.firstRun = t.firstRun !== void 0 && t.firstRun;
112
+ super(), this.name = t.name, this.world = e, this.reads = t.reads, this.writes = t.writes, this.exclusive = t.exclusive ?? !1, this.deltaBetweenRuns = t.deltaBetweenRuns ?? 0, this.firstRun = t.firstRun !== void 0 && t.firstRun;
109
113
  }
110
114
  init() {}
111
115
  clear() {
@@ -113,6 +117,18 @@ var b = Object.create, x = Object.defineProperty, S = Object.getOwnPropertyDescr
113
117
  }
114
118
  finishLoading() {}
115
119
  addEntities(e) {}
120
+ get gameTime() {
121
+ return this.scheduledGameTime ?? this.world.gameTime;
122
+ }
123
+ withGameTime(e, t) {
124
+ let n = this.scheduledGameTime;
125
+ this.scheduledGameTime = e;
126
+ try {
127
+ return t();
128
+ } finally {
129
+ this.scheduledGameTime = n;
130
+ }
131
+ }
116
132
  update(e) {
117
133
  if (this.currentDelta += e, this.currentDelta >= this.deltaBetweenRuns || this.firstRun) {
118
134
  let e = 0;
@@ -141,17 +157,30 @@ var b = Object.create, x = Object.defineProperty, S = Object.getOwnPropertyDescr
141
157
  shouldRun() {
142
158
  return !0;
143
159
  }
160
+ get readComponents() {
161
+ return this.reads;
162
+ }
163
+ get requiresExclusiveScheduling() {
164
+ return this.exclusive;
165
+ }
166
+ get createdComponents() {
167
+ return [];
168
+ }
169
+ get creationReadComponents() {
170
+ return this.readComponents;
171
+ }
172
+ get creationReadQueries() {}
144
173
  destroy() {
145
174
  this.removeAllListeners();
146
175
  }
147
176
  };
148
- function A(e, t, n) {
177
+ function T(e, t, n) {
149
178
  let r = e.groups.map(t);
150
179
  for (let t = 0; t < e.entities.length; t++) r[e.groupIndexes[t]] && n(e.entities[t]);
151
180
  }
152
181
  //#endregion
153
182
  //#region src/systems/iterable-system.ts
154
- var j = class extends k {
183
+ var E = class extends w {
155
184
  remainingInstancesToRun = [];
156
185
  remainingInstancesStartTime = null;
157
186
  iterationsPerCheck;
@@ -201,7 +230,7 @@ var j = class extends k {
201
230
  }
202
231
  beforeRunIterables() {}
203
232
  getIterableEntityId(e) {}
204
- }, M = class e extends j {
233
+ }, D = class e extends E {
205
234
  entities = /* @__PURE__ */ new Map();
206
235
  options;
207
236
  constructor(e, t = { name: "EntitySystem" }) {
@@ -239,7 +268,7 @@ var j = class extends k {
239
268
  t.entities.forEach((e) => this.onEntityAdded(e));
240
269
  return;
241
270
  }
242
- A(t, (e) => this.hasComponents(e), (e) => {
271
+ T(t, (e) => this.hasComponents(e), (e) => {
243
272
  this.filterEntity(e) && (this.entities.set(e.eid, e), this.options.updateEntityOnAdd && this.updateEntity(e, 0));
244
273
  });
245
274
  }
@@ -255,11 +284,28 @@ var j = class extends k {
255
284
  shouldRun() {
256
285
  return this.isCurrentlyRunning() || this.entities.size > 0;
257
286
  }
258
- }, N = class {
287
+ get creationReadComponents() {
288
+ if (!this.options.components) return this.reads ? ["entity", ...this.reads] : void 0;
289
+ let e = this.options.components.filter((e) => e !== "entity");
290
+ return [...this.reads ?? [], ...e.length ? e : ["entity"]];
291
+ }
292
+ get creationReadQueries() {
293
+ if (this.checkAddEntity === e.prototype.checkAddEntity) return [this.options.components ?? []];
294
+ }
295
+ get readComponents() {
296
+ let e = this.options.components ?? this.reads;
297
+ return e ? [
298
+ "entity",
299
+ ...e,
300
+ ...this.reads ?? []
301
+ ] : void 0;
302
+ }
303
+ }, O = class {
259
304
  onmessage(e, t = []) {}
260
- }, P = class extends N {
305
+ }, k = class extends O {
261
306
  updateFunction;
262
307
  entities = [];
308
+ workState = new a();
263
309
  queryEntities = {};
264
310
  worldExtension;
265
311
  world;
@@ -274,57 +320,67 @@ var j = class extends k {
274
320
  allocateComponentBlock: (e, t) => i[e].memoryComponent.create(t)
275
321
  };
276
322
  }
277
- postMessage(e) {
278
- if (e.type === "init") this.onMessageTyped({ type: "init-complete" });
279
- else if (e.type === "load") this.worldExtension = this.updateFunction.init?.(e.data) ?? void 0, this.onMessageTyped({ type: "loaded" });
280
- else if (e.type === "reset") this.entities = [], this.queryEntities = {};
281
- else if (e.type === "run") {
282
- if (this.worldExtension && Object.assign(e.world, this.worldExtension), e.world.getString = (e) => this.world.constantStrings.getString(e) ?? "", e.world.heap = this.world.heap, e.world.allocate = this.allocator, this.createsEntities) {
283
- let t = this.world.registry;
284
- e.world.buildEntityDescriptor = (e) => o(e, this.world.factory.configs, t, this.allocator, this.world.factory.getWorkerClasses());
323
+ getString = (e) => this.world.constantStrings.getString(e) ?? "";
324
+ postMessage(t) {
325
+ if (t.type === "init") this.onMessageTyped({ type: "init-complete" });
326
+ else if (t.type === "load") {
327
+ this.entities = e(this.entities, t.entities), Object.entries(t.queries).forEach(([t, n]) => {
328
+ this.queryEntities[t] = e(this.queryEntities[t] ?? [], n);
329
+ });
330
+ let n = {
331
+ gameTime: t.gameTime,
332
+ getString: this.getString,
333
+ heap: this.world.heap
334
+ };
335
+ this.worldExtension = this.updateFunction.init?.(n, t.data, this.entities, this.queryEntities) ?? void 0, this.onMessageTyped({ type: "loaded" });
336
+ } else if (t.type === "reset") this.workState.clear(), this.entities = [], this.queryEntities = {};
337
+ else if (t.type === "run") {
338
+ if (t.world = this.workState.getWorld(t.world, t.workBatch), this.worldExtension && Object.assign(t.world, this.worldExtension), t.world.getString = this.getString, t.world.heap = this.world.heap, t.world.allocate = this.allocator, this.createsEntities) {
339
+ let e = this.world.registry;
340
+ t.world.buildEntityDescriptor = (t) => o(t, this.world.factory.configs, e, this.allocator, this.world.factory.getWorkerClasses());
285
341
  }
286
342
  if (this.addsComponents) {
287
- let t = this.world.registry;
288
- e.world.buildComponentDescriptor = (e, n) => l(e, n, t, this.allocator);
343
+ let e = this.world.registry;
344
+ t.world.buildComponentDescriptor = (t, n) => l(t, n, e, this.allocator);
289
345
  }
290
- let t = performance.now(), n = [], r = {}, i = [], s = [], c = [];
291
- this.entities = a(this.entities, e.entities);
292
- let u = {};
293
- Object.entries(e.queries).forEach(([e, t]) => {
294
- let n = a(this.queryEntities[e] ?? [], t);
295
- this.queryEntities[e] = n, u[e] = n;
346
+ let n = performance.now(), r = [], i = {}, a = [], s = [], c = [];
347
+ this.entities = e(this.entities, t.entities);
348
+ let u = this.workState.getEntities(this.entities, t.entities, t.workBatch), d = {};
349
+ Object.entries(t.queries).forEach(([t, n]) => {
350
+ let r = e(this.queryEntities[t] ?? [], n);
351
+ this.queryEntities[t] = r, d[t] = r;
296
352
  });
297
- let d = {
298
- entityComponentChanged(e, t, r, i) {
299
- n.push({
353
+ let f = {
354
+ entityComponentChanged(e, t, n, i) {
355
+ r.push({
300
356
  entityId: e,
301
357
  event: "component-property-updated",
302
358
  args: [
303
359
  t,
304
- r,
360
+ n,
305
361
  i
306
362
  ]
307
363
  });
308
364
  },
309
- emitEntityEvent(e, t, ...r) {
310
- n.push({
365
+ emitEntityEvent(e, t, ...n) {
366
+ r.push({
311
367
  entityId: e,
312
368
  event: t,
313
- args: r
369
+ args: n
314
370
  });
315
371
  },
316
372
  emitSystemEvent(e, t) {
317
- (r[e] ?? (r[e] = [])).push(t);
373
+ (i[e] ?? (i[e] = [])).push(t);
318
374
  },
319
375
  entityDied(e) {
320
- n.push({
376
+ r.push({
321
377
  entityId: e,
322
378
  event: "death",
323
379
  args: []
324
380
  });
325
381
  },
326
382
  createEntity(e) {
327
- i.push(e);
383
+ a.push(e);
328
384
  },
329
385
  addComponent(e, t) {
330
386
  s.push({
@@ -342,8 +398,8 @@ var j = class extends k {
342
398
  }
343
399
  };
344
400
  if (this.updateFunction.queryChanged) {
345
- for (let [t, n] of Object.entries(e.queries)) if (n.added.length || n.removed.length) try {
346
- this.updateFunction.queryChanged(e.world, t, n, d);
401
+ for (let [e, n] of Object.entries(t.queries)) if (n.added.length || n.removed.length) try {
402
+ this.updateFunction.queryChanged(t.world, e, n, f);
347
403
  } catch (e) {
348
404
  c.push({
349
405
  error: e,
@@ -351,65 +407,80 @@ var j = class extends k {
351
407
  });
352
408
  }
353
409
  }
354
- let f = !1;
355
- if (this.updateFunction.preRun) try {
356
- this.updateFunction.preRun(e.world, this.entities, u, d);
410
+ let p = !1;
411
+ if (this.updateFunction.preRun && (!t.workBatch || t.workBatch.first)) try {
412
+ this.updateFunction.preRun(t.world, this.entities, d, f);
357
413
  } catch (e) {
358
- f = !0, c.push({
414
+ p = !0, c.push({
359
415
  error: e,
360
416
  phase: "preRun"
361
417
  });
362
418
  }
363
- if (f || this.entities.forEach((t) => {
419
+ if (!p && this.updateFunction.preBatch) try {
420
+ this.updateFunction.preBatch(t.world, u, d, f);
421
+ } catch (e) {
422
+ p = !0, c.push({
423
+ error: e,
424
+ phase: "preBatch"
425
+ });
426
+ }
427
+ if (p || u.forEach((e) => {
364
428
  try {
365
- this.updateFunction(e.world, t.entityId, t.components, u, d);
366
- } catch (e) {
429
+ this.updateFunction(t.world, e.entityId, e.components, d, f);
430
+ } catch (t) {
367
431
  c.push({
368
- error: e,
432
+ error: t,
369
433
  phase: "update",
370
- entityId: t.entityId
434
+ entityId: e.entityId
371
435
  });
372
436
  }
373
- }), this.updateFunction.entityRemoved) for (let t of e.entities.removed) try {
374
- this.updateFunction.entityRemoved(e.world, t, d);
375
- } catch (e) {
437
+ }), this.updateFunction.entityRemoved) for (let e of t.entities.removed) try {
438
+ this.updateFunction.entityRemoved(t.world, e, f);
439
+ } catch (t) {
376
440
  c.push({
377
- error: e,
441
+ error: t,
378
442
  phase: "entityRemoved",
379
- entityId: t
443
+ entityId: e
380
444
  });
381
445
  }
382
- let p = performance.now() - t;
383
- this.onMessageTyped({
446
+ let m = performance.now() - n;
447
+ this.workState.finish(t.workBatch, p), this.onMessageTyped({
384
448
  type: "run-complete",
385
- generation: e.generation,
386
- runTime: p,
387
- events: n,
388
- systemEvents: r,
389
- created: i,
449
+ generation: t.generation,
450
+ runTime: m,
451
+ events: r,
452
+ systemEvents: i,
453
+ created: a,
390
454
  componentChanges: s,
391
- errors: c
455
+ errors: c,
456
+ workFailed: p
392
457
  });
393
458
  }
394
459
  }
395
460
  onMessageTyped(e) {
396
461
  this.onmessage({ data: e });
397
462
  }
398
- }, F = "___main", I = class e extends k {
463
+ }, A = "___main", j = class e extends w {
399
464
  entities = /* @__PURE__ */ new Map();
400
465
  options;
401
466
  worker;
402
467
  isWorkerThread;
403
468
  initialized = !1;
404
469
  initPromise = null;
470
+ initError = null;
405
471
  loadingPromise = null;
406
472
  runCompletePromise = null;
407
473
  isRunning = !1;
474
+ workPass;
475
+ timingBatch;
476
+ pendingEffects;
477
+ completeEffects;
408
478
  generation = 0;
409
479
  queryEntities = {};
410
480
  queryDeltas = {};
411
481
  constructor(e, t) {
412
- super(e, t), this.options = t, Object.keys(this.options.queries ?? {}).forEach((e) => {
482
+ if (super(e, t), t.workBatchSize !== void 0 && (!Number.isSafeInteger(t.workBatchSize) || t.workBatchSize <= 0)) throw Error("workBatchSize must be a positive safe integer");
483
+ this.options = t, Object.keys(this.options.queries ?? {}).forEach((e) => {
413
484
  this.queryEntities[e] = /* @__PURE__ */ new Map();
414
485
  }), e.on("entity-added", (t) => {
415
486
  e.isBulkLoading || this.checkAddEntity(t);
@@ -422,55 +493,102 @@ var j = class extends k {
422
493
  type: "grow-buffer",
423
494
  buffer: e
424
495
  });
425
- })) : (this.worker = new P(t.updateFunction, e, !!t.createsEntities, !!t.addsComponents), this.isWorkerThread = !1), this.initWorker();
496
+ })) : (this.worker = new k(t.updateFunction, e, !!t.createsEntities, !!t.addsComponents), this.isWorkerThread = !1), this.initWorker();
426
497
  }
427
498
  initWorker() {
428
- this.worker.onmessage = (e) => {
429
- let t = e.data;
430
- if (t.type === "init-complete") this.initialized = !0, this.initPromise &&= (this.initPromise.resolve(), null);
431
- else if (t.type === "loaded") this.loadingPromise &&= (this.loadingPromise.resolve(), null);
432
- else if (t.type === "grow-buffer-from-worker") this.world.addGrownBuffer(t.buffer);
433
- else if (t.type === "run-complete") {
434
- if (t.generation !== this.generation) return;
435
- this.isRunning = !1, this.world.emit(`system-${this.name}-worker-finished`, t.runTime), t.errors.forEach(({ error: e, entityId: t, phase: n }) => {
436
- this.onError(e, {
437
- entityId: t,
438
- phase: n
439
- });
440
- }), (t.componentChanges ?? []).forEach((e) => {
441
- let t = this.world.getEntityByEid(e.entityId);
442
- if (e.type === "add") {
443
- let n = this.world.registry[e.component.name];
444
- if (!t || !n || e.component.name === "entity") {
445
- n?.memoryComponent.delete(e.component.index);
446
- return;
499
+ let e = (e) => {
500
+ console.error(e, e.cause), this.initialized || (this.initError = e, this.initPromise?.reject(e));
501
+ };
502
+ if (!(this.worker instanceof k)) {
503
+ let t = (t) => {
504
+ e(Error(`Worker ${this.name} failed to load`, { cause: t }));
505
+ };
506
+ this.worker.onerror = t, this.worker.onmessageerror = t;
507
+ }
508
+ this.worker.onmessage = (t) => {
509
+ let n = t.data;
510
+ if (n.type === "unhandled-rejection") e(Error(`Worker ${this.name} had an unhandled promise rejection`, { cause: n.error }));
511
+ else if (n.type === "init-complete") this.initialized = !0, this.initPromise &&= (this.initPromise.resolve(), null);
512
+ else if (n.type === "loaded") this.loadingPromise &&= (this.loadingPromise.resolve(), null);
513
+ else if (n.type === "grow-buffer-from-worker") this.world.addGrownBuffer(n.buffer);
514
+ else if (n.type === "run-complete") {
515
+ if (n.generation !== this.generation) {
516
+ this.world.scheduler.prepareEffects && this.discardWorkerAllocations(n);
517
+ return;
518
+ }
519
+ let e = this.timingBatch && {
520
+ ...this.timingBatch,
521
+ last: this.timingBatch.last || !!n.workFailed
522
+ };
523
+ if (n.workFailed && (this.workPass = void 0), !this.completeEffects) {
524
+ this.applyWorkerEffects(n, !0, e);
525
+ return;
526
+ }
527
+ this.world.emit(`system-${this.name}-worker-finished`, n.runTime, e);
528
+ let t = this.generation, r = !1, i = () => {
529
+ this.pendingEffects = void 0, this.isRunning = !1, this.runCompletePromise?.resolve(), this.runCompletePromise = null;
530
+ }, a = {
531
+ apply: () => {
532
+ if (!r) {
533
+ if (t !== this.generation) {
534
+ a.discard();
535
+ return;
536
+ }
537
+ r = !0, this.pendingEffects = void 0;
538
+ try {
539
+ this.applyWorkerEffects(n, !1, e);
540
+ } catch (e) {
541
+ this.onError(e, { phase: "run" }), this.world.notifySystemRunCompleted(this);
542
+ } finally {
543
+ i();
544
+ }
447
545
  }
448
- let r = e.component.name;
449
- t.removeComponent(r), t.attachComponent(r, e.component.index, !0);
450
- } else t && e.componentName !== "entity" && t.removeComponent(e.componentName);
451
- });
452
- for (let e of Object.keys(t.systemEvents)) this.emit(e, t.systemEvents[e]);
453
- t.events.forEach((e) => {
454
- let t = this.world.getEntityByEid(e.entityId);
455
- if (!t) {
456
- console.warn(`${this.name}-event ${e.event}: Could not find entity with id ${e.entityId}`);
457
- return;
546
+ },
547
+ discard: () => {
548
+ r || (r = !0, this.discardWorkerAllocations(n), i());
458
549
  }
459
- t.emit(e.event, ...e.args);
460
- }), t.created.forEach((e) => {
461
- this.world.adoptEntity(e);
462
- }), this.world.emit(`system-${this.name}-worker-events-finished`, t.runTime), this.world.notifySystemRunCompleted(this), this.runCompletePromise &&= (this.runCompletePromise.resolve(), null);
550
+ };
551
+ this.pendingEffects = a, this.completeEffects(a);
463
552
  }
464
553
  }, this.worker.postMessage({ type: "init" });
465
554
  }
555
+ applyWorkerEffects(e, t, n) {
556
+ this.isRunning = !1, t && this.world.emit(`system-${this.name}-worker-finished`, e.runTime, n), e.errors.forEach(({ error: e, entityId: t, phase: n }) => {
557
+ this.onError(e, {
558
+ entityId: t,
559
+ phase: n
560
+ });
561
+ }), (e.componentChanges ?? []).forEach((e) => {
562
+ let t = this.world.getEntityByEid(e.entityId);
563
+ if (e.type === "add") {
564
+ let n = this.world.registry[e.component.name];
565
+ if (!t || !n || e.component.name === "entity") {
566
+ n?.memoryComponent.delete(e.component.index);
567
+ return;
568
+ }
569
+ let r = e.component.name;
570
+ t.removeComponent(r), t.attachComponent(r, e.component.index, !0);
571
+ } else t && e.componentName !== "entity" && t.removeComponent(e.componentName);
572
+ });
573
+ for (let t of Object.keys(e.systemEvents)) this.emit(t, e.systemEvents[t]);
574
+ e.events.forEach((e) => {
575
+ let t = this.world.getEntityByEid(e.entityId);
576
+ if (!t) {
577
+ console.warn(`${this.name}-event ${e.event}: Could not find entity with id ${e.entityId}`);
578
+ return;
579
+ }
580
+ t.emit(e.event, ...e.args);
581
+ }), e.created.forEach((e) => {
582
+ this.world.adoptEntity(e);
583
+ }), this.world.emit(`system-${this.name}-worker-events-finished`, e.runTime, n), this.world.notifySystemRunCompleted(this), this.runCompletePromise &&= (this.runCompletePromise.resolve(), null);
584
+ }
585
+ discardWorkerAllocations(e) {
586
+ for (let t of e.created) for (let [e, n] of Object.entries(t.components)) this.world.registry[e]?.memoryComponent.delete(n);
587
+ for (let t of e.componentChanges ?? []) t.type === "add" && this.world.registry[t.component.name]?.memoryComponent.delete(t.component.index);
588
+ }
466
589
  init() {
467
- if (this.initialized) return;
468
- if (this.initPromise) return this.initPromise.promise;
469
- let { promise: e, resolve: t } = Promise.withResolvers();
470
- return this.initPromise = {
471
- promise: e,
472
- resolve: t
473
- }, e;
590
+ if (this.initError) return Promise.reject(this.initError);
591
+ if (!this.initialized) return this.initPromise ||= Promise.withResolvers(), this.initPromise.promise;
474
592
  }
475
593
  finishLoading() {
476
594
  let { promise: e, resolve: t } = Promise.withResolvers();
@@ -478,34 +596,72 @@ var j = class extends k {
478
596
  promise: e,
479
597
  resolve: t
480
598
  };
481
- let n = {
599
+ let n = {};
600
+ Object.entries(this.options.queries ?? {}).forEach(([e, t]) => {
601
+ n[e] = this.buildQueryDelta(e, t);
602
+ });
603
+ let r = {
482
604
  type: "load",
483
605
  data: this.options.getInitData?.(),
606
+ gameTime: this.gameTime,
607
+ entities: this.buildQueryDelta(A, this.options),
608
+ queries: n,
484
609
  heap: this.isWorkerThread ? this.world.heap.getSharedMemory() : void 0,
485
610
  sharedMemory: this.isWorkerThread ? this.world.getSharedComponentMemory() : void 0,
486
611
  factoryConfigs: this.isWorkerThread && this.options.createsEntities ? this.world.factory.configs : void 0,
487
612
  factoryClasses: this.isWorkerThread && this.options.createsEntities ? this.world.factory.getWorkerClasses() : void 0,
488
613
  addsComponents: !!this.options.addsComponents
489
614
  };
490
- return this.worker.postMessage(n), e;
615
+ return this.worker.postMessage(r), e;
491
616
  }
492
617
  clear() {
493
- if (super.clear(), this.isRunning && !this.runCompletePromise) {
618
+ if (super.clear(), this.pendingEffects?.discard(), this.isRunning && !this.runCompletePromise) {
494
619
  let { promise: e, resolve: t } = Promise.withResolvers();
495
620
  this.runCompletePromise = {
496
621
  promise: e,
497
622
  resolve: t
498
623
  };
499
624
  }
500
- this.isRunning = !1, this.generation++, this.entities.clear(), Object.values(this.queryEntities).forEach((e) => e.clear()), this.queryDeltas = {}, this.worker.postMessage({ type: "reset" });
625
+ this.isRunning = !1, this.generation++, this.entities.clear(), Object.values(this.queryEntities).forEach((e) => e.clear()), this.queryDeltas = {}, this.workPass = void 0, this.timingBatch = void 0, this.worker.postMessage({ type: "reset" });
501
626
  }
502
627
  update(e) {
503
- return this.isRunning ? (this.currentDelta += e, !1) : super.update(e);
628
+ return this.isRunning ? (this.currentDelta += e, !1) : this.workPass ? (this.currentDelta += e, this.run(this.workPass.elapsedTime), !0) : super.update(e);
504
629
  }
505
630
  onRunFinished() {}
506
631
  isCurrentlyRunning() {
507
632
  return this.isRunning;
508
633
  }
634
+ get readComponents() {
635
+ let e = [this.options, ...Object.values(this.options.queries ?? {})];
636
+ return [
637
+ "entity",
638
+ ...this.reads ?? [],
639
+ ...e.flatMap((e) => [...e.required, ...e.optional ?? []])
640
+ ];
641
+ }
642
+ get requiresExclusiveScheduling() {
643
+ return super.requiresExclusiveScheduling || this.options.createsEntities === !0 || !!this.options.addsComponents;
644
+ }
645
+ get createdComponents() {
646
+ let e = this.options.createsEntities;
647
+ return e && typeof e != "boolean" ? ["entity", ...e] : [];
648
+ }
649
+ get creationReadComponents() {
650
+ let e = Object.values(this.options.queries ?? {});
651
+ return this.tracksMainQuery && e.push(this.options), [...this.reads ?? [], ...e.flatMap((e) => {
652
+ let t = e.required.filter((e) => e !== "entity"), n = e.optional?.filter((e) => e !== "entity") ?? [];
653
+ return [
654
+ ...t.length ? t : ["entity"],
655
+ ...n,
656
+ ...e.not ?? []
657
+ ];
658
+ })];
659
+ }
660
+ get creationReadQueries() {
661
+ if (this.checkAddEntity !== e.prototype.checkAddEntity || this.matchesQuery !== e.prototype.matchesQuery) return;
662
+ let t = Object.values(this.options.queries ?? {});
663
+ return this.tracksMainQuery && t.push(this.options), t.map((e) => e.required);
664
+ }
509
665
  waitForRunToComplete() {
510
666
  if (this.isRunning) {
511
667
  if (!this.runCompletePromise) {
@@ -519,23 +675,48 @@ var j = class extends k {
519
675
  }
520
676
  }
521
677
  run(e) {
522
- let t = {
523
- gameTime: this.world.gameTime,
678
+ let t, n = this.gameTime;
679
+ if (this.options.workBatchSize !== void 0 && this.tracksMainQuery) {
680
+ let r = !this.workPass, i = this.workPass ??= {
681
+ entities: Array.from(this.entities.values()),
682
+ cursor: 0,
683
+ elapsedTime: e,
684
+ gameTime: n
685
+ };
686
+ n = i.gameTime, e = i.elapsedTime;
687
+ let a = Math.min(i.cursor + this.options.workBatchSize, i.entities.length), o = [];
688
+ for (; i.cursor < a; i.cursor++) {
689
+ let e = i.entities[i.cursor];
690
+ this.entities.get(e.eid) === e && o.push(e.eid);
691
+ }
692
+ let s = i.cursor === i.entities.length;
693
+ t = {
694
+ entityIds: o,
695
+ first: r,
696
+ last: s
697
+ }, s && (this.workPass = void 0);
698
+ }
699
+ let r = {
700
+ gameTime: n,
524
701
  elapsedTime: e
525
702
  };
526
- this.addDataToWorld?.(t), this.isRunning = !0;
527
- let n = this.buildQueryDelta(F, this.options), r = {};
703
+ (!t || t.first) && this.addDataToWorld?.(r), this.timingBatch = t && {
704
+ first: t.first,
705
+ last: t.last
706
+ }, this.isRunning = !0, this.completeEffects = this.world.scheduler.prepareEffects?.(this.world, this);
707
+ let i = this.buildQueryDelta(A, this.options), a = {};
528
708
  Object.entries(this.options.queries ?? {}).forEach(([e, t]) => {
529
- r[e] = this.buildQueryDelta(e, t);
709
+ a[e] = this.buildQueryDelta(e, t);
530
710
  });
531
- let i = {
711
+ let o = {
532
712
  type: "run",
533
713
  generation: this.generation,
534
- world: t,
535
- entities: n,
536
- queries: r
714
+ world: r,
715
+ entities: i,
716
+ queries: a,
717
+ workBatch: t
537
718
  };
538
- this.worker.postMessage(i);
719
+ this.worker.postMessage(o);
539
720
  }
540
721
  buildQueryDelta(e, t) {
541
722
  let n = this.getQueryDelta(e), r = [];
@@ -592,7 +773,7 @@ var j = class extends k {
592
773
  }
593
774
  checkAddEntity(e) {
594
775
  let t = this.tracksMainQuery && this.matchesQuery(e, this.options);
595
- return this.updateEntityList(F, this.entities, e, t), Object.entries(this.options.queries ?? {}).forEach(([t, n]) => {
776
+ return this.updateEntityList(A, this.entities, e, t), Object.entries(this.options.queries ?? {}).forEach(([t, n]) => {
596
777
  let r = this.queryEntities[t] ?? (this.queryEntities[t] = /* @__PURE__ */ new Map());
597
778
  this.updateEntityList(t, r, e, this.matchesQuery(e, n));
598
779
  }), t;
@@ -602,19 +783,19 @@ var j = class extends k {
602
783
  t.entities.forEach((e) => this.checkAddEntity(e));
603
784
  return;
604
785
  }
605
- this.tracksMainQuery && this.addBatchToQuery(F, this.entities, this.options, t), Object.entries(this.options.queries ?? {}).forEach(([e, n]) => {
786
+ this.tracksMainQuery && this.addBatchToQuery(A, this.entities, this.options, t), Object.entries(this.options.queries ?? {}).forEach(([e, n]) => {
606
787
  let r = this.queryEntities[e] ?? (this.queryEntities[e] = /* @__PURE__ */ new Map());
607
788
  this.addBatchToQuery(e, r, n, t);
608
789
  });
609
790
  }
610
791
  addBatchToQuery(e, t, n, r) {
611
792
  let i = this.getQueryDelta(e);
612
- A(r, (e) => this.matchesComponents(e, n), (e) => {
793
+ T(r, (e) => this.matchesComponents(e, n), (e) => {
613
794
  e.components.entity.dead || n.filter && !n.filter(e) || (t.set(e.eid, e), this.markAdded(i, e));
614
795
  });
615
796
  }
616
797
  removeEntity(e) {
617
- this.updateEntityList(F, this.entities, e, !1), Object.entries(this.queryEntities).forEach(([t, n]) => {
798
+ this.updateEntityList(A, this.entities, e, !1), Object.entries(this.queryEntities).forEach(([t, n]) => {
618
799
  this.updateEntityList(t, n, e, !1);
619
800
  });
620
801
  }
@@ -624,12 +805,12 @@ var j = class extends k {
624
805
  });
625
806
  }
626
807
  shouldRun() {
627
- return this.entities.size > 0;
808
+ return this.workPass !== void 0 || this.entities.size > 0;
628
809
  }
629
810
  destroy() {
630
- super.destroy(), "terminate" in this.worker && this.worker.terminate();
811
+ super.destroy(), this.pendingEffects?.discard(), "terminate" in this.worker && this.worker.terminate();
631
812
  }
632
- }, L = class extends O.default {
813
+ }, M = class extends C.default {
633
814
  eid;
634
815
  config;
635
816
  world;
@@ -730,7 +911,7 @@ var j = class extends k {
730
911
  assertComponentPropertyMutable(e, t) {
731
912
  if (e === "entity" && (t === "type" || t === "class")) throw Error(`Entity ${t} is immutable`);
732
913
  }
733
- }, R = class e {
914
+ }, N = class e {
734
915
  world;
735
916
  configs;
736
917
  classes;
@@ -747,7 +928,7 @@ var j = class extends k {
747
928
  this.world = e, this.forbiddenProperties.clear();
748
929
  for (let t of Object.keys(this.classes)) {
749
930
  let n = this.classes[t].entity;
750
- if (n !== L && !(n.prototype instanceof L)) throw Error(`Entity class ${t} must extend BaseEntity`);
931
+ if (n !== M && !(n.prototype instanceof M)) throw Error(`Entity class ${t} must extend BaseEntity`);
751
932
  for (let n of this.classes[t].components) if (n === "entity" || !(n in e.registry)) throw Error(`Entity class ${t} contains unknown or reserved component ${n}`);
752
933
  }
753
934
  for (let e of Object.keys(this.configs)) this.validateTemplate(e, this.configs[e]);
@@ -773,7 +954,7 @@ var j = class extends k {
773
954
  createAdoptedEntity(e, t, n) {
774
955
  if (!t) {
775
956
  if (this.hasClasses) throw Error(`Entity type ${e} has no class`);
776
- return new L(this.world, void 0, n);
957
+ return new M(this.world, void 0, n);
777
958
  }
778
959
  let r = this.classes[t];
779
960
  if (!r) throw Error(`Unknown entity class: ${t}`);
@@ -799,7 +980,7 @@ var j = class extends k {
799
980
  return e ? this.getAllowedComponents(e) : void 0;
800
981
  }
801
982
  createEntity(e) {
802
- return new L(this.world, e);
983
+ return new M(this.world, e);
803
984
  }
804
985
  get hasClasses() {
805
986
  return this.allowedComponents.size > 0;
@@ -864,7 +1045,183 @@ var j = class extends k {
864
1045
  }
865
1046
  throw Error(`Entity type ${e} class ${t} loads a component outside its class`);
866
1047
  }
867
- }, z = y, B = 1e4, V = class extends O.default {
1048
+ }, P = 45, F = "!", I = "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO", L = "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}", R = (/* @__PURE__ */ new Int8Array(128)).fill(-1);
1049
+ for (let e = 0; e < P; e++) R[I.charCodeAt(e)] = e, R[L.charCodeAt(e)] = e + P;
1050
+ function z(e) {
1051
+ let t = "";
1052
+ for (; e >= P;) t += L[e % P], e = Math.floor(e / P);
1053
+ return t + I[e];
1054
+ }
1055
+ var B = /* @__PURE__ */ new Float32Array(1), V = new Uint32Array(B.buffer);
1056
+ function oe(e, t) {
1057
+ switch (e.type) {
1058
+ case "boolean": return typeof t == "boolean" ? I[Number(t)] : void 0;
1059
+ case "string": return t === null ? I[0] : typeof t == "string" && t.length ? z(t.length) + t : void 0;
1060
+ case "float32": return typeof t != "number" || !Number.isFinite(t) || Math.fround(t) !== t ? void 0 : (B[0] = t, z(V[0]));
1061
+ default: {
1062
+ let n = se(e, t);
1063
+ return n === void 0 ? void 0 : z(n);
1064
+ }
1065
+ }
1066
+ }
1067
+ function se(e, t) {
1068
+ if (typeof t != "number") return;
1069
+ let n = Math.round((t - (e.offset ?? 0)) * 10 ** (e.decimals ?? 0) / (e.step ?? 1));
1070
+ if (!Number.isSafeInteger(n) || H(e, n) !== t) return;
1071
+ if (e.type === "uint") return n >= 0 ? n : void 0;
1072
+ let r = n >= 0 ? n * 2 : -n * 2 - 1;
1073
+ return Number.isSafeInteger(r) ? r : void 0;
1074
+ }
1075
+ function H(e, t) {
1076
+ return t * (e.step ?? 1) / 10 ** (e.decimals ?? 0) + (e.offset ?? 0);
1077
+ }
1078
+ function U(e, t) {
1079
+ switch (e.type) {
1080
+ case "boolean": return t !== 0;
1081
+ case "float32": return V[0] = t, B[0];
1082
+ case "uint": return H(e, t);
1083
+ default: return H(e, t % 2 == 0 ? t / 2 : -(t + 1) / 2);
1084
+ }
1085
+ }
1086
+ function W(e) {
1087
+ return e.types === void 0 ? [e.type] : e.types;
1088
+ }
1089
+ var G = class {
1090
+ encoders = /* @__PURE__ */ new Map();
1091
+ used = /* @__PURE__ */ new Set();
1092
+ constructor(e) {
1093
+ let t = 0;
1094
+ for (let n of e) {
1095
+ let e = {
1096
+ key: t,
1097
+ definition: n,
1098
+ indices: new Map(n.properties.map((e, t) => [e.name, t]))
1099
+ };
1100
+ for (let r of W(n)) {
1101
+ if (this.encoders.has(r)) throw Error(`Duplicate compressed entity definition for ${r}`);
1102
+ this.encoders.set(r, {
1103
+ prefix: z(t++),
1104
+ group: e
1105
+ });
1106
+ }
1107
+ }
1108
+ }
1109
+ get entityDefinitions() {
1110
+ let e = {};
1111
+ for (let t of this.used) e[t.key] = t.definition;
1112
+ return e;
1113
+ }
1114
+ compress(e) {
1115
+ let t = e.type === void 0 ? void 0 : this.encoders.get(e.type), n = t && this.encode(t, e);
1116
+ return !t || n === void 0 ? e : (this.used.add(t.group), n);
1117
+ }
1118
+ compressAll(e) {
1119
+ let t = e.map((e) => this.compress(e));
1120
+ return {
1121
+ entityDefinitions: this.entityDefinitions,
1122
+ entities: t
1123
+ };
1124
+ }
1125
+ encode(e, t) {
1126
+ let n = [];
1127
+ for (let [r, i] of Object.entries(t)) {
1128
+ if (r === "type" || i === void 0) continue;
1129
+ let t = e.group.indices.get(r);
1130
+ if (t === void 0) return;
1131
+ let a = oe(e.group.definition.properties[t], i);
1132
+ if (a === void 0) return;
1133
+ n[t] = a;
1134
+ }
1135
+ let r = e.prefix;
1136
+ for (let e = 0; e < n.length; e++) r += n[e] ?? F;
1137
+ return r;
1138
+ }
1139
+ };
1140
+ function ce(e, t) {
1141
+ return new G(t).compressAll(e);
1142
+ }
1143
+ var K = /* @__PURE__ */ new WeakMap();
1144
+ function le(e) {
1145
+ let t = K.get(e);
1146
+ if (t) return t;
1147
+ t = /* @__PURE__ */ new Map();
1148
+ for (let [n, r] of Object.entries(e)) {
1149
+ let e = W(r);
1150
+ for (let i = 0; i < e.length; i++) {
1151
+ if (t.has(Number(n) + i)) throw Error(`Compressed entity definitions overlap at key ${Number(n) + i}`);
1152
+ t.set(Number(n) + i, {
1153
+ type: e[i],
1154
+ properties: r.properties
1155
+ });
1156
+ }
1157
+ }
1158
+ return K.set(e, t), t;
1159
+ }
1160
+ function q(e, t) {
1161
+ let n = 0, r = () => {
1162
+ if (e[n] === F) {
1163
+ n++;
1164
+ return;
1165
+ }
1166
+ let t = 0, r = 1;
1167
+ for (; n < e.length;) {
1168
+ let i = e.charCodeAt(n++), a = i < 128 ? R[i] : -1;
1169
+ if (a < 0) throw Error(`Invalid compressed entity ${e}`);
1170
+ if (a < P) return t + a * r;
1171
+ t += (a - P) * r, r *= P;
1172
+ }
1173
+ throw Error(`Truncated compressed entity ${e}`);
1174
+ }, i = r(), a = i === void 0 ? void 0 : le(t).get(i);
1175
+ if (!a) throw Error(`No compressed entity definition for ${e}`);
1176
+ let o = { type: a.type };
1177
+ for (let t = 0; n < e.length; t++) {
1178
+ let i = a.properties[t];
1179
+ if (!i) throw Error(`Compressed entity ${e} has more values than ${a.type} defines`);
1180
+ let s = r();
1181
+ if (s !== void 0) {
1182
+ if (i.type !== "string") o[i.name] = U(i, s);
1183
+ else if (s === 0) o[i.name] = null;
1184
+ else {
1185
+ if (n + s > e.length) throw Error(`Truncated compressed entity ${e}`);
1186
+ o[i.name] = e.slice(n, n += s);
1187
+ }
1188
+ }
1189
+ }
1190
+ return o;
1191
+ }
1192
+ function J(e, t) {
1193
+ return e.map((e) => {
1194
+ if (typeof e != "string") return e;
1195
+ if (!t) throw Error("Compressed entities need entityDefinitions to load");
1196
+ return q(e, t);
1197
+ });
1198
+ }
1199
+ //#endregion
1200
+ //#region src/scheduling/default-scheduler.ts
1201
+ var Y = class {
1202
+ update(e, t) {
1203
+ let n = null;
1204
+ return e.systems.forEach((r) => {
1205
+ let i = !0, a = !1, o = !1;
1206
+ e.emit(`system-${r.name}-started`);
1207
+ try {
1208
+ i = r.shouldRun(), i && (a = r.update(t));
1209
+ } catch (t) {
1210
+ let i = t;
1211
+ console.error(i.message, i), o = !0, n = i, e.emit("system-error", {
1212
+ system: r.name,
1213
+ error: i,
1214
+ phase: "run"
1215
+ });
1216
+ }
1217
+ e.emit(`system-${r.name}-finished`, {
1218
+ ran: a,
1219
+ shouldRun: i,
1220
+ failed: o
1221
+ });
1222
+ }), { lastSystemError: n };
1223
+ }
1224
+ }, ue = _, X = 1e4, de = class extends C.default {
868
1225
  heap;
869
1226
  constantStrings;
870
1227
  eidCounter;
@@ -872,10 +1229,11 @@ var j = class extends k {
872
1229
  factory;
873
1230
  entities = /* @__PURE__ */ new Map();
874
1231
  systems = [];
1232
+ scheduler;
875
1233
  gameTime = 0;
876
1234
  playerTime = 0;
877
1235
  timeScale = 1;
878
- paused = !1;
1236
+ isPaused = !1;
879
1237
  destroyed = !1;
880
1238
  pristine = !0;
881
1239
  isBulkLoading = !1;
@@ -889,20 +1247,21 @@ var j = class extends k {
889
1247
  waitingSystems: /* @__PURE__ */ new Set(),
890
1248
  waitElapsed: 0
891
1249
  };
892
- constructor(t, n = {}) {
893
- super(), this.heap = new v({ bufferSize: n.heapSize ?? z }), this.constantStrings = new e(this.heap), this.eidCounter = this.heap.allocUI32(1), this.heap.addOnGrowBufferHandlers((e) => this.emit("grow-buffer", e));
894
- let r = {
895
- ...t,
1250
+ clearing = !1;
1251
+ constructor(e, t = {}) {
1252
+ super(), this.scheduler = t.scheduler ?? new Y(), this.heap = new ne({ bufferSize: t.heapSize ?? ue }), this.constantStrings = new h(this.heap), this.eidCounter = this.heap.allocUI32(1), this.heap.addOnGrowBufferHandlers((e) => this.emit("grow-buffer", e));
1253
+ let n = {
1254
+ ...e,
896
1255
  entity: i
897
- }, a = {};
898
- for (let e of Object.keys(r)) {
899
- let t = r[e];
900
- a[e] = {
1256
+ }, r = {};
1257
+ for (let e of Object.keys(n)) {
1258
+ let t = n[e];
1259
+ r[e] = {
901
1260
  ...t,
902
- memoryComponent: new _(this.heap, t.type, t.size)
1261
+ memoryComponent: new g(this.heap, t.type, t.size)
903
1262
  };
904
1263
  }
905
- this.registry = a, this.factory = n.factory ?? new R(), this.factory.setWorld(this);
1264
+ this.registry = r, this.factory = t.factory ?? new N(), this.factory.setWorld(this);
906
1265
  }
907
1266
  allocateEid() {
908
1267
  return Atomics.add(this.eidCounter.data, 0, 1) + 1;
@@ -919,13 +1278,13 @@ var j = class extends k {
919
1278
  this.heap.buffers[e.bufferPosition] === void 0 && this.heap.addSharedBuffer(e), this.emit("grow-buffer", e);
920
1279
  }
921
1280
  get needsSpareBuffer() {
922
- return this.systems.some((e) => e instanceof I && e.isWorkerThread && (!!e.options.createsEntities || !!e.options.addsComponents));
1281
+ return this.systems.some((e) => e instanceof j && e.isWorkerThread && (!!e.options.createsEntities || !!e.options.addsComponents));
923
1282
  }
924
1283
  async init() {
925
1284
  await Promise.all(this.systems.map((e) => e.init()).filter((e) => e instanceof Promise));
926
1285
  }
927
- finishLoadingSystems() {
928
- return Promise.all(this.systems.map((e) => e.finishLoading()).filter((e) => e instanceof Promise));
1286
+ async finishLoadingSystems() {
1287
+ await Promise.all(this.systems.map((e) => e.finishLoading()).filter((e) => e instanceof Promise));
929
1288
  }
930
1289
  addEntity(e, t = !0) {
931
1290
  return this.entities.set(e.eid, e), e.world = this, this.pristine = !1, e.on("component-added", (t) => {
@@ -960,29 +1319,34 @@ var j = class extends k {
960
1319
  }
961
1320
  }
962
1321
  load(e) {
963
- if (!this.pristine) {
1322
+ if (!this.pristine || this.scheduler.prepareEffects && this.systems.some((e) => e.isCurrentlyRunning())) {
964
1323
  for (let e of Array.from(this.entities.values())) this.removeEntity(e);
965
- this.systems.forEach((e) => e.clear()), this.consolidateFreeBuffersForReload();
1324
+ this.systems.forEach((e) => e.clear()), this.scheduler.reset?.(this), this.consolidateFreeBuffersForReload();
966
1325
  }
967
1326
  for (let e of Object.keys(this.factory.configs)) this.constantStrings.getOrCreate(e);
968
1327
  for (let e of Object.keys(this.factory.classes)) this.constantStrings.getOrCreate(e);
969
1328
  this.isBulkLoading = !0;
970
1329
  try {
971
- let t = e.entities.map((e) => this.loadEntity(e, !1));
1330
+ let t = ("entityDefinitions" in e ? J(e.entities, e.entityDefinitions) : e.entities).map((e) => this.loadEntity(e, !1));
972
1331
  for (let e of t) e.finishLoading(), this.emit("entity-added", e), e.on("death", () => {
973
1332
  this.onEntityDied(e);
974
1333
  });
975
1334
  } finally {
976
1335
  this.isBulkLoading = !1;
977
1336
  }
978
- let t = H(this.entities.values());
979
- this.systems.forEach((e) => e.addEntities(t)), this.gameTime = e.gameTime ?? 0, this.playerTime = e.playerTime ?? 0, this.timeScale = e.timeScale ?? 1, this.finishLoadingSystems();
1337
+ let t = fe(this.entities.values());
1338
+ return this.systems.forEach((e) => e.addEntities(t)), this.gameTime = e.gameTime ?? 0, this.playerTime = e.playerTime ?? 0, this.timeScale = e.timeScale ?? 1, this.finishLoadingSystems();
980
1339
  }
981
1340
  async clear() {
982
- if (!this.pristine) {
983
- await Promise.all(this.systems.map((e) => e.waitForRunToComplete()).filter((e) => e instanceof Promise));
984
- for (let e of Array.from(this.entities.values())) this.removeEntity(e);
985
- this.systems.forEach((e) => e.clear()), this.freeAllPendingBuffers(), this.pristine = !0;
1341
+ if (!this.pristine || this.scheduler.beforeClear) {
1342
+ this.clearing = !0;
1343
+ try {
1344
+ this.scheduler.beforeClear?.(this), await Promise.all(this.systems.map((e) => e.waitForRunToComplete()).filter((e) => e instanceof Promise));
1345
+ for (let e of Array.from(this.entities.values())) this.removeEntity(e);
1346
+ this.systems.forEach((e) => e.clear()), this.scheduler.reset?.(this), this.freeAllPendingBuffers(), this.pristine = !0;
1347
+ } finally {
1348
+ this.clearing = !1;
1349
+ }
986
1350
  }
987
1351
  }
988
1352
  removeEntity(e) {
@@ -1018,7 +1382,7 @@ var j = class extends k {
1018
1382
  });
1019
1383
  }
1020
1384
  notifySystemRunCompleted(e) {
1021
- this.activeFreeBuffer.waitingSystems.delete(e) && this.activeFreeBuffer.waitingSystems.size === 0 && this.processFreeBuffers();
1385
+ this.activeFreeBuffer.waitingSystems.delete(e) && this.activeFreeBuffer.waitingSystems.size === 0 && this.processFreeBuffers(), this.scheduler.runCompleted?.(this, e);
1022
1386
  }
1023
1387
  processFreeBuffers() {
1024
1388
  for (; this.activeFreeBuffer.waitingSystems.size === 0 && (this.activeFreeBuffer.frees.length > 0 && this.performFrees(this.activeFreeBuffer), this.nextFreeBuffer.frees.length !== 0);) this.promoteNextFreeBuffer();
@@ -1042,22 +1406,22 @@ var j = class extends k {
1042
1406
  }
1043
1407
  checkFreeBufferTimeout(e) {
1044
1408
  let t = this.activeFreeBuffer;
1045
- if (t.waitingSystems.size !== 0 && (t.waitElapsed += e, t.waitElapsed >= B)) {
1409
+ if (t.waitingSystems.size !== 0 && (t.waitElapsed += e, t.waitElapsed >= X)) {
1046
1410
  let e = Array.from(t.waitingSystems).map((e) => e.name).join(", ");
1047
- console.warn(`shared-memory-ecs: deferred component free waited over ${B}ms on system(s): ${e}; freeing anyway`), t.waitingSystems.clear(), this.processFreeBuffers();
1411
+ console.warn(`shared-memory-ecs: deferred component free waited over ${X}ms on system(s): ${e}; freeing anyway`), t.waitingSystems.clear(), this.processFreeBuffers();
1048
1412
  }
1049
1413
  }
1050
1414
  addSystem(e) {
1051
- return this.systems.push(e), this.emit("system-added", e), e;
1415
+ return this.systems.push(e), this.scheduler.systemAdded?.(this, e), this.emit("system-added", e), e;
1052
1416
  }
1053
1417
  addSystemIfNotExists(e) {
1054
- this.systems.findIndex((t) => e.name === t.name) === -1 && (this.systems.push(e), this.emit("system-added", e));
1418
+ this.systems.findIndex((t) => e.name === t.name) === -1 && (this.systems.push(e), this.scheduler.systemAdded?.(this, e), this.emit("system-added", e));
1055
1419
  }
1056
1420
  removeSystem(e) {
1057
1421
  let t = this.systems.findIndex((t) => t.name === e);
1058
1422
  if (t !== -1) {
1059
1423
  let [e] = this.systems.splice(t, 1);
1060
- this.emit("system-removed", e);
1424
+ this.scheduler.systemRemoved?.(this, e), this.emit("system-removed", e);
1061
1425
  }
1062
1426
  }
1063
1427
  update(e) {
@@ -1069,41 +1433,35 @@ var j = class extends k {
1069
1433
  if (this.playerTime += e, this.paused) return {};
1070
1434
  let t = e;
1071
1435
  e = this.timeScale * e, this.gameTime += e, this.processFreeBuffers(), this.needsSpareBuffer && this.heap.ensureSpareBuffer();
1072
- let n = null;
1073
- return this.systems.forEach((t) => {
1074
- let r = !0, i = !1, a = !1;
1075
- this.emit(`system-${t.name}-started`);
1076
- try {
1077
- r = t.shouldRun(), r && (i = t.update(e));
1078
- } catch (e) {
1079
- let r = e;
1080
- console.error(r.message, r), a = !0, n = r, this.emit("system-error", {
1081
- system: t.name,
1082
- error: r,
1083
- phase: "run"
1084
- });
1085
- }
1086
- this.emit(`system-${t.name}-finished`, {
1087
- ran: i,
1088
- shouldRun: r,
1089
- failed: a
1090
- });
1091
- }), this.checkFreeBufferTimeout(t), { lastSystemError: n };
1436
+ let n = this.scheduler.update(this, e);
1437
+ return this.checkFreeBufferTimeout(t), n;
1092
1438
  }
1093
1439
  pause() {
1094
1440
  this.paused = !0;
1095
1441
  }
1442
+ get paused() {
1443
+ return this.isPaused;
1444
+ }
1445
+ set paused(e) {
1446
+ this.isPaused !== e && (this.isPaused = e, e && this.scheduler.pause?.(this));
1447
+ }
1448
+ prepareForSystemDispatch() {
1449
+ return this.dispatchAllowed ? (this.needsSpareBuffer && this.heap.ensureSpareBuffer(), !0) : !1;
1450
+ }
1451
+ get dispatchAllowed() {
1452
+ return !this.clearing && !this.destroyed;
1453
+ }
1096
1454
  resume() {
1097
1455
  this.paused = !1;
1098
1456
  }
1099
1457
  addEntityToEntityWorkerSystem(e, t) {
1100
1458
  this.isBulkLoading || this.systems.forEach((n) => {
1101
- (n instanceof M && n.options.components?.includes(t) || n instanceof I && this.componentAffectsEntityWorkerSystem(n, t)) && n.checkAddEntity(e);
1459
+ (n instanceof D && n.options.components?.includes(t) || n instanceof j && this.componentAffectsEntityWorkerSystem(n, t)) && n.checkAddEntity(e);
1102
1460
  });
1103
1461
  }
1104
1462
  removeEntityFromEntityWorkerSystem(e, t) {
1105
1463
  this.isBulkLoading || this.systems.forEach((n) => {
1106
- n instanceof M && n.options.components?.includes(t) ? n.removeEntity(e) : n instanceof I && this.componentAffectsEntityWorkerSystem(n, t) && n.checkAddEntity(e);
1464
+ n instanceof D && n.options.components?.includes(t) ? n.removeEntity(e) : n instanceof j && this.componentAffectsEntityWorkerSystem(n, t) && n.checkAddEntity(e);
1107
1465
  });
1108
1466
  }
1109
1467
  componentAffectsEntityWorkerSystem(e, t) {
@@ -1113,10 +1471,10 @@ var j = class extends k {
1113
1471
  destroy() {
1114
1472
  this.destroyed ||= (this.systems.forEach((e) => {
1115
1473
  e.destroy();
1116
- }), !0);
1474
+ }), this.scheduler.destroy?.(this), !0);
1117
1475
  }
1118
1476
  };
1119
- function H(e) {
1477
+ function fe(e) {
1120
1478
  let t = {
1121
1479
  entities: [],
1122
1480
  groupIndexes: [],
@@ -1129,28 +1487,279 @@ function H(e) {
1129
1487
  return t;
1130
1488
  }
1131
1489
  //#endregion
1490
+ //#region src/scheduling/conflict-scheduler.ts
1491
+ var pe = class {
1492
+ compiled = Object.freeze({
1493
+ order: Object.freeze([]),
1494
+ batches: Object.freeze([])
1495
+ });
1496
+ registeredSystems = [];
1497
+ access = /* @__PURE__ */ new Map();
1498
+ nodes = /* @__PURE__ */ new Set();
1499
+ tails = /* @__PURE__ */ new Map();
1500
+ frontiers = /* @__PURE__ */ new Map();
1501
+ creators = /* @__PURE__ */ new Map();
1502
+ creationReaders = /* @__PURE__ */ new Map();
1503
+ exclusiveTail;
1504
+ running = /* @__PURE__ */ new Map();
1505
+ ready = [];
1506
+ readyIndex = 0;
1507
+ gameTime = 0;
1508
+ pumping = !1;
1509
+ resumeQueued = !1;
1510
+ continuationTimer;
1511
+ generation = 0;
1512
+ publications = /* @__PURE__ */ new Set();
1513
+ publicationReady = [];
1514
+ publishing = !1;
1515
+ get schedule() {
1516
+ return this.compiled;
1517
+ }
1518
+ rebuild(e) {
1519
+ let t = Array.from(new Set(e.systems)), n = t.map((e) => {
1520
+ let t = e.readComponents, n = e.creationReadQueries;
1521
+ return {
1522
+ reads: new Set(t),
1523
+ creationReads: new Set(n === void 0 ? e.creationReadComponents : e.reads),
1524
+ creationQueries: n?.map((e) => Array.from(e)),
1525
+ writes: new Set(e.writes),
1526
+ creates: new Set(e.createdComponents),
1527
+ exclusive: e.requiresExclusiveScheduling || t === void 0 || e.writes === void 0
1528
+ };
1529
+ });
1530
+ this.access = new Map(t.map((e, t) => [e, n[t]]));
1531
+ let r = [], i = [];
1532
+ for (let e = 0; e < t.length; e++) {
1533
+ let a = 0;
1534
+ for (let t = 0; t < e; t++) this.conflicts(n[t], n[e]) && (a = Math.max(a, i[t] + 1));
1535
+ i.push(a), (r[a] ??= []).push(t[e]);
1536
+ }
1537
+ return this.registeredSystems = e.systems.slice(), this.compiled = Object.freeze({
1538
+ order: Object.freeze(r.flat()),
1539
+ batches: Object.freeze(r.map((e) => Object.freeze(e)))
1540
+ }), this.compiled;
1541
+ }
1542
+ systemAdded(e) {
1543
+ this.rebuild(e);
1544
+ }
1545
+ systemRemoved(e) {
1546
+ this.rebuild(e);
1547
+ }
1548
+ update(e, t) {
1549
+ if (this.pumping) throw Error("ConflictScheduler does not support reentrant updates");
1550
+ this.refreshMembership(e), this.gameTime = e.gameTime ?? this.gameTime + t;
1551
+ for (let n of new Set(e.systems)) this.enqueue(n, this.access.get(n), t, this.gameTime);
1552
+ return this.pump(e, !0);
1553
+ }
1554
+ runCompleted(e, t) {
1555
+ let n = this.running.get(t);
1556
+ if (!n || (this.complete(n), this.pumping || this.resumeQueued)) return;
1557
+ this.resumeQueued = !0;
1558
+ let r = this.generation;
1559
+ queueMicrotask(() => {
1560
+ r === this.generation && (this.resumeQueued = !1, this.pump(e, !1));
1561
+ });
1562
+ }
1563
+ pause(e) {
1564
+ this.scheduleContinuation(e);
1565
+ }
1566
+ scheduleContinuation(e) {
1567
+ if (this.continuationTimer !== void 0 || !e.paused || !this.dispatchAllowed(e) || !Array.from(this.running.values()).some((e) => this.isSliced(e))) return;
1568
+ let t = this.generation;
1569
+ this.continuationTimer = setTimeout(() => {
1570
+ t === this.generation && (this.continuationTimer = void 0, e.paused && this.pump(e, "sliced"));
1571
+ }, 0);
1572
+ }
1573
+ isSliced(e) {
1574
+ return e.system instanceof E && e.system.remainingInstancesToRun.length > 0;
1575
+ }
1576
+ reset() {
1577
+ this.continuationTimer !== void 0 && (clearTimeout(this.continuationTimer), this.continuationTimer = void 0);
1578
+ let e = Array.from(this.publications, (e) => e.effects);
1579
+ this.publications.clear(), this.publicationReady = [], this.nodes.clear(), this.tails.clear(), this.frontiers.clear(), this.creators.clear(), this.creationReaders.clear(), this.exclusiveTail = void 0, this.running.clear(), this.ready = [], this.readyIndex = 0, this.gameTime = 0, this.resumeQueued = !1, this.generation++, e.forEach((e) => e.discard());
1580
+ }
1581
+ beforeClear() {
1582
+ this.reset();
1583
+ }
1584
+ prepareEffects(e, t) {
1585
+ let n = this.running.get(t), r = this.generation;
1586
+ return (e) => {
1587
+ if (!n || r !== this.generation || !this.nodes.has(n)) {
1588
+ e.discard();
1589
+ return;
1590
+ }
1591
+ n.effects = e, this.publications.add(n), n.publicationDependencies === 0 && this.publicationReady.push(n), this.publish();
1592
+ };
1593
+ }
1594
+ publish() {
1595
+ if (this.publishing) return;
1596
+ this.publishing = !0;
1597
+ let e = this.generation;
1598
+ try {
1599
+ for (; this.publicationReady.length && e === this.generation;) {
1600
+ let e = this.publicationReady.pop();
1601
+ this.publications.delete(e);
1602
+ let t = e.effects;
1603
+ e.effects = void 0, t.apply();
1604
+ }
1605
+ } finally {
1606
+ this.publishing = !1;
1607
+ }
1608
+ }
1609
+ destroy() {
1610
+ this.reset();
1611
+ }
1612
+ refreshMembership(e) {
1613
+ (e.systems.length !== this.registeredSystems.length || e.systems.some((e, t) => e !== this.registeredSystems[t])) && this.rebuild(e);
1614
+ }
1615
+ pump(e, t) {
1616
+ this.pumping = !0;
1617
+ let n = null, r = this.generation;
1618
+ try {
1619
+ if (t) for (let i of Array.from(this.running.values())) {
1620
+ if (!i.system.isCurrentlyRunning() || t === "sliced" && !this.isSliced(i)) continue;
1621
+ if (!this.prepare(e)) return { lastSystemError: n };
1622
+ let a = this.dispatch(e, i, !0);
1623
+ if (n = a?.lastSystemError ?? n, !a || r !== this.generation) return { lastSystemError: n };
1624
+ }
1625
+ for (; this.readyIndex < this.ready.length && r === this.generation && this.prepare(e);) {
1626
+ let t = this.ready[this.readyIndex++], r = this.dispatch(e, t, !1);
1627
+ if (n = r?.lastSystemError ?? n, !r) {
1628
+ this.nodes.has(t) && t.state === "pending" && this.ready.push(t);
1629
+ break;
1630
+ }
1631
+ }
1632
+ } finally {
1633
+ this.ready = this.ready.slice(this.readyIndex), this.readyIndex = 0, this.pumping = !1, this.scheduleContinuation(e);
1634
+ }
1635
+ return { lastSystemError: n };
1636
+ }
1637
+ enqueue(e, t, n, r) {
1638
+ let i = {
1639
+ system: e,
1640
+ access: t,
1641
+ elapsedTime: n,
1642
+ gameTime: r,
1643
+ state: "pending",
1644
+ dependencies: 0,
1645
+ dependents: [],
1646
+ publicationDependencies: 0,
1647
+ publicationDependents: []
1648
+ }, a = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Set(), s = (e) => {
1649
+ e && e.state !== "complete" && a.add(e);
1650
+ };
1651
+ if (s(this.tails.get(e)), s(this.exclusiveTail), t.exclusive) this.tails.forEach(s), this.exclusiveTail = i;
1652
+ else {
1653
+ let n = (e) => {
1654
+ e && e.state !== "complete" && o.add(e);
1655
+ };
1656
+ for (let e of t.creates) {
1657
+ let t = this.frontier(e);
1658
+ n(t.writer), n(t.creator);
1659
+ }
1660
+ if (t.creates.size) for (let e of this.creationReaders.values()) this.observesCreation(t, e.access) && n(e);
1661
+ for (let n of t.reads) if (!t.writes.has(n)) {
1662
+ let t = this.frontier(n);
1663
+ s(t.writer), t.readers.set(e, i);
1664
+ }
1665
+ for (let e of this.creators.values()) this.observesCreation(e.access, t) && s(e);
1666
+ (t.creationReads.size || t.creationQueries?.length) && this.creationReaders.set(t, i);
1667
+ for (let e of t.writes) {
1668
+ let t = this.frontier(e);
1669
+ s(t.writer), s(t.creator), t.readers.forEach(s), t.readers.clear(), t.writer = i;
1670
+ }
1671
+ for (let e of t.creates) this.frontier(e).creator = i;
1672
+ t.creates.size && this.creators.set(t, i);
1673
+ }
1674
+ for (let e of a) e.dependents.push(i);
1675
+ i.dependencies = a.size;
1676
+ for (let e of o) e.publicationDependents.push(i);
1677
+ i.publicationDependencies = o.size, this.nodes.add(i), this.tails.set(e, i), i.dependencies || this.ready.push(i);
1678
+ }
1679
+ frontier(e) {
1680
+ let t = this.frontiers.get(e);
1681
+ return t || (t = { readers: /* @__PURE__ */ new Map() }, this.frontiers.set(e, t)), t;
1682
+ }
1683
+ complete(e) {
1684
+ if (e.state !== "complete") {
1685
+ e.state = "complete", this.nodes.delete(e), this.running.delete(e.system), this.tails.get(e.system) === e && this.tails.delete(e.system), this.exclusiveTail === e && (this.exclusiveTail = void 0), this.creators.get(e.access) === e && this.creators.delete(e.access), this.creationReaders.get(e.access) === e && this.creationReaders.delete(e.access);
1686
+ for (let t of /* @__PURE__ */ new Set([
1687
+ ...e.access.reads,
1688
+ ...e.access.writes,
1689
+ ...e.access.creates
1690
+ ])) {
1691
+ let n = this.frontiers.get(t);
1692
+ n?.writer === e && (n.writer = void 0), n?.creator === e && (n.creator = void 0), n?.readers.get(e.system) === e && n.readers.delete(e.system), n && !n.writer && !n.creator && !n.readers.size && this.frontiers.delete(t);
1693
+ }
1694
+ for (let t of e.dependents) --t.dependencies === 0 && this.ready.push(t);
1695
+ e.dependents.length = 0;
1696
+ for (let t of e.publicationDependents) t.publicationDependencies--, t.publicationDependencies === 0 && t.effects && this.publicationReady.push(t);
1697
+ e.publicationDependents.length = 0, this.publish();
1698
+ }
1699
+ }
1700
+ dispatch(e, t, n) {
1701
+ let r = t.system;
1702
+ if (!n && !e.systems.includes(r)) return this.complete(t), {};
1703
+ let i = this.generation, a = !0, o = !1, s = !1, c = null;
1704
+ if (e.emit(`system-${r.name}-started`), this.nodes.has(t) && this.dispatchAllowed(e)) {
1705
+ try {
1706
+ if (!r.withGameTime(t.gameTime, () => (a = n || r.shouldRun(), !this.nodes.has(t) || !this.dispatchAllowed(e) ? !1 : (a ? (t.state = "running", this.running.set(r, t), o = r.update(n ? 0 : t.elapsedTime), i === this.generation && !r.isCurrentlyRunning() && this.complete(t)) : this.complete(t), !0)))) return;
1707
+ } catch (n) {
1708
+ let a = n;
1709
+ console.error(a.message, a), s = !0, c = a, i === this.generation && (r.isCurrentlyRunning() ? (t.state = "running", this.running.set(r, t)) : this.complete(t)), e.emit("system-error", {
1710
+ system: r.name,
1711
+ error: a,
1712
+ phase: "run"
1713
+ });
1714
+ }
1715
+ return e.emit(`system-${r.name}-finished`, {
1716
+ ran: o,
1717
+ shouldRun: a,
1718
+ failed: s
1719
+ }), { lastSystemError: c };
1720
+ }
1721
+ }
1722
+ prepare(e) {
1723
+ return this.dispatchAllowed(e) && e.prepareForSystemDispatch?.() !== !1;
1724
+ }
1725
+ dispatchAllowed(e) {
1726
+ return e.dispatchAllowed !== !1;
1727
+ }
1728
+ observesCreation(e, t) {
1729
+ for (let n of t.creationReads) if (e.creates.has(n)) return !0;
1730
+ return t.creationQueries?.some((t) => t.every((t) => e.creates.has(t))) ?? !1;
1731
+ }
1732
+ conflicts(e, t) {
1733
+ if (e.exclusive || t.exclusive) return !0;
1734
+ for (let n of e.writes) if (t.reads.has(n) || t.writes.has(n)) return !0;
1735
+ for (let n of t.writes) if (e.reads.has(n)) return !0;
1736
+ for (let n of e.creates) if (t.writes.has(n)) return !0;
1737
+ return e.creates.size > 0 && this.observesCreation(e, t);
1738
+ }
1739
+ };
1740
+ //#endregion
1132
1741
  //#region src/entity-class.ts
1133
- function U(e, t) {
1742
+ function me(e, t) {
1134
1743
  return t;
1135
1744
  }
1136
- function W(e, t) {
1745
+ function Z(e, t) {
1137
1746
  return t;
1138
1747
  }
1139
1748
  //#endregion
1140
1749
  //#region src/actions/kill-entity.ts
1141
- function G(e) {
1750
+ function he(e) {
1142
1751
  e.components.entity.dead = !0, e.emit("death");
1143
1752
  }
1144
1753
  //#endregion
1145
1754
  //#region src/performance-timing.ts
1146
- var K = 1e3, q = {
1755
+ var ge = 1e3, Q = {
1147
1756
  avg: 0,
1148
1757
  min: 0,
1149
1758
  max: 0,
1150
1759
  samples: 0
1151
1760
  };
1152
- function J(e) {
1153
- if (!e.length) return { ...q };
1761
+ function $(e) {
1762
+ if (!e.length) return { ...Q };
1154
1763
  let t = 0, n = Infinity, r = 0;
1155
1764
  for (let i of e) t += i, i < n && (n = i), i > r && (r = i);
1156
1765
  return {
@@ -1160,13 +1769,13 @@ function J(e) {
1160
1769
  samples: e.length
1161
1770
  };
1162
1771
  }
1163
- var Y = class extends O.default {
1772
+ var _e = class extends C.default {
1164
1773
  world;
1165
1774
  ticksBetweenUpdates;
1166
1775
  stats = {
1167
- update: { ...q },
1776
+ update: { ...Q },
1168
1777
  systems: [],
1169
- events: { ...q }
1778
+ events: { ...Q }
1170
1779
  };
1171
1780
  autoUpdate;
1172
1781
  ticks = 0;
@@ -1182,11 +1791,11 @@ var Y = class extends O.default {
1182
1791
  }
1183
1792
  reset() {
1184
1793
  this.ticks = 0, this.updateTimes = [], this.systemTimings.forEach((e) => {
1185
- e.run = [], e.events = [], e.eventStart = -1;
1794
+ e.run = [], e.events = [], e.eventStart = -1, e.pendingRun = 0, e.pendingEvents = 0;
1186
1795
  }), this.stats = {
1187
- update: { ...q },
1796
+ update: { ...Q },
1188
1797
  systems: [],
1189
- events: { ...q }
1798
+ events: { ...Q }
1190
1799
  };
1191
1800
  }
1192
1801
  destroy() {
@@ -1210,11 +1819,13 @@ var Y = class extends O.default {
1210
1819
  run: [],
1211
1820
  events: [],
1212
1821
  eventStart: -1,
1213
- onRunFinished: (e) => {
1214
- t.run.push(e), t.eventStart = performance.now();
1822
+ pendingRun: 0,
1823
+ pendingEvents: 0,
1824
+ onRunFinished: (e, n) => {
1825
+ (!n || n.first) && (t.pendingRun = 0, t.pendingEvents = 0), t.pendingRun += e, (!n || n.last) && (t.run.push(t.pendingRun), t.pendingRun = 0), t.eventStart = performance.now();
1215
1826
  },
1216
- onEventsFinished: () => {
1217
- t.eventStart < 0 || (t.events.push(performance.now() - t.eventStart), t.eventStart = -1);
1827
+ onEventsFinished: (e, n) => {
1828
+ t.eventStart < 0 || (t.pendingEvents += performance.now() - t.eventStart, (!n || n.last) && (t.events.push(t.pendingEvents), t.pendingEvents = 0), t.eventStart = -1);
1218
1829
  }
1219
1830
  };
1220
1831
  this.world.on(`system-${e.name}-worker-finished`, t.onRunFinished), this.world.on(`system-${e.name}-worker-events-finished`, t.onEventsFinished), this.systemTimings.set(e.name, t);
@@ -1229,21 +1840,21 @@ var Y = class extends O.default {
1229
1840
  let t = this.systemTimings.get(e.name);
1230
1841
  return {
1231
1842
  name: e.name,
1232
- run: J(t?.run ?? []),
1233
- events: J(t?.events ?? [])
1843
+ run: $(t?.run ?? []),
1844
+ events: $(t?.events ?? [])
1234
1845
  };
1235
- }), t = { ...q };
1846
+ }), t = { ...Q };
1236
1847
  return e.forEach((e) => {
1237
1848
  t.avg += e.events.avg, t.min += e.events.min, t.max += e.events.max, t.samples += e.events.samples;
1238
1849
  }), this.stats = {
1239
- update: J(this.updateTimes),
1850
+ update: $(this.updateTimes),
1240
1851
  systems: e,
1241
1852
  events: t
1242
1853
  }, this.ticks = 0, this.updateTimes = [], this.systemTimings.forEach((e) => {
1243
1854
  e.run = [], e.events = [];
1244
1855
  }), this.emit("stats-updated", this.stats), this.stats;
1245
1856
  }
1246
- }, X = class extends I {
1857
+ }, ve = class extends j {
1247
1858
  constructor(e, t) {
1248
1859
  super(e, {
1249
1860
  ...t,
@@ -1259,6 +1870,6 @@ var Y = class extends O.default {
1259
1870
  }
1260
1871
  };
1261
1872
  //#endregion
1262
- export { L as BaseEntity, V as BaseWorld, n as CLASS_INDEX, f as Component, e as ConstantStringCache, c as DEAD_INDEX, K as DEFAULT_TICKS_BETWEEN_UPDATES, R as EntityFactory, M as EntitySystem, P as EntitySystemWebWorker, I as EntityWorkerSystem, j as IterableSystem, _ as MemoryComponent, Y as PerformanceTiming, g as STATIC_INDEX, k as System, r as TYPE_INDEX, N as WebWorker, X as WorkerSystem, t as addComponentWorker, p as createEntitySystemWorker, d as createEntityWorker, h as createSystemWorker, U as defineEntityClasses, W as defineEntityConfigs, i as entityDefinition, G as killEntity, m as killEntityWorker, s as removeComponentWorker };
1873
+ export { M as BaseEntity, de as BaseWorld, n as CLASS_INDEX, f as Component, pe as ConflictScheduler, h as ConstantStringCache, c as DEAD_INDEX, ge as DEFAULT_TICKS_BETWEEN_UPDATES, Y as DefaultScheduler, G as EntityCompressor, N as EntityFactory, D as EntitySystem, k as EntitySystemWebWorker, j as EntityWorkerSystem, E as IterableSystem, g as MemoryComponent, _e as PerformanceTiming, te as STATIC_INDEX, w as System, r as TYPE_INDEX, O as WebWorker, ve as WorkerSystem, t as addComponentWorker, ce as compressEntities, p as createEntitySystemWorker, d as createEntityWorker, ee as createSystemWorker, J as decompressEntities, q as decompressEntity, me as defineEntityClasses, Z as defineEntityConfigs, i as entityDefinition, he as killEntity, m as killEntityWorker, s as removeComponentWorker };
1263
1874
 
1264
1875
  //# sourceMappingURL=index.js.map