@daneren2005/shared-memory-ecs 1.5.1 → 1.7.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.
Files changed (32) hide show
  1. package/README.md +222 -44
  2. package/dist/actions/add-component-worker.d.ts +3 -0
  3. package/dist/actions/build-worker-entity.d.ts +4 -2
  4. package/dist/actions/create-entity-worker.d.ts +2 -2
  5. package/dist/actions/kill-entity-worker.d.ts +2 -2
  6. package/dist/actions/remove-component-worker.d.ts +3 -0
  7. package/dist/component-definition.d.ts +2 -0
  8. package/dist/create-system-worker-DURlIMia.js +345 -0
  9. package/dist/create-system-worker-DURlIMia.js.map +1 -0
  10. package/dist/entity-class.d.ts +51 -0
  11. package/dist/entity-component.d.ts +7 -2
  12. package/dist/entity-factory.d.ts +21 -5
  13. package/dist/entity.d.ts +11 -2
  14. package/dist/index.d.ts +15 -8
  15. package/dist/index.js +379 -166
  16. package/dist/index.js.map +1 -1
  17. package/dist/systems/{component-system.d.ts → entity-worker-system.d.ts} +39 -18
  18. package/dist/systems/system.d.ts +1 -1
  19. package/dist/systems/worker-system.d.ts +22 -0
  20. package/dist/systems/workers/apply-query-delta.d.ts +1 -1
  21. package/dist/systems/workers/create-entity-system-worker.d.ts +8 -0
  22. package/dist/systems/workers/create-system-worker.d.ts +9 -0
  23. package/dist/systems/workers/entity-system-web-worker.d.ts +18 -0
  24. package/dist/systems/workers/{component-worker-message.d.ts → entity-system-worker-message.d.ts} +8 -4
  25. package/dist/worker.d.ts +10 -6
  26. package/dist/worker.js +2 -2
  27. package/dist/world.d.ts +17 -17
  28. package/package.json +2 -1
  29. package/dist/create-component-worker-BM942gjg.js +0 -288
  30. package/dist/create-component-worker-BM942gjg.js.map +0 -1
  31. package/dist/systems/workers/component-web-worker.d.ts +0 -17
  32. package/dist/systems/workers/create-component-worker.d.ts +0 -8
package/dist/index.js CHANGED
@@ -1,17 +1,17 @@
1
- import { a as e, c as t, d as n, f as r, i, l as a, n as o, o as s, r as c, s as l, t as u, u as d } from "./create-component-worker-BM942gjg.js";
2
- import f from "@daneren2005/shared-memory-objects/memory-heap";
3
- import { MAX_BYTE_OFFSET_LENGTH as p } 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 h, u as g, v as _ } from "./create-system-worker-DURlIMia.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";
4
4
  //#region \0rolldown/runtime.js
5
- var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescriptor, _ = Object.getOwnPropertyNames, v = Object.getPrototypeOf, y = Object.prototype.hasOwnProperty, b = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t.exports), x = (e, t, n, r) => {
6
- if (t && typeof t == "object" || typeof t == "function") for (var i = _(t), a = 0, o = i.length, s; a < o; a++) s = i[a], !y.call(e, s) && s !== n && h(e, s, {
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, {
7
7
  get: ((e) => t[e]).bind(null, s),
8
- enumerable: !(r = g(t, s)) || r.enumerable
8
+ enumerable: !(r = S(t, s)) || r.enumerable
9
9
  });
10
10
  return e;
11
- }, S = /* @__PURE__ */ ((e, t, n) => (n = e == null ? {} : m(v(e)), x(t || !e || !e.__esModule ? h(n, "default", {
11
+ }, O = /* @__PURE__ */ ((e, t, n) => (n = e == null ? {} : b(w(e)), D(t || !e || !e.__esModule ? x(n, "default", {
12
12
  value: e,
13
13
  enumerable: !0
14
- }) : n, e)))((/* @__PURE__ */ b(((e, t) => {
14
+ }) : n, e)))((/* @__PURE__ */ E(((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,76 +98,7 @@ var m = Object.create, h = Object.defineProperty, g = 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), C = class extends S.default {
102
- eid;
103
- config;
104
- world;
105
- components = {};
106
- constructor(e, t, n) {
107
- super(), this.world = e, this.eid = n ?? e.allocateEid(), n === void 0 && (this.loadComponent("entity", t ?? {}, !1), t && this.load(t));
108
- }
109
- loadComponent(e, t, n = !0) {
110
- let r = this.world.registry[e], i = r.memoryComponent, a = i.create(r.toBlock(t, this)), o = r.attach(this, i, a);
111
- return o.block ??= i.getBlock(a), this.components[e] = o, n && this.emit("component-added", e, o), o;
112
- }
113
- attachComponent(e, t) {
114
- let n = this.world.registry[e], r = n.attach(this, n.memoryComponent, t);
115
- return r.block ??= n.memoryComponent.getBlock(t), this.components[e] = r, r;
116
- }
117
- removeComponent(e) {
118
- let t = this.components[e];
119
- if (t) {
120
- let n = this.world.registry[e];
121
- this.world.deferComponentMemoryFree(n.memoryComponent, t.index, n.free ? () => n.free(t) : void 0), delete this.components[e], this.emit("component-removed", e);
122
- }
123
- }
124
- setComponent(e, t, n) {
125
- let r = this.components[e];
126
- r && (r[t] = n, this.emit("component-property-updated", e, t, n));
127
- }
128
- setComponentBulk(e, t) {
129
- let n = this.components[e];
130
- n && Object.assign(n, t);
131
- }
132
- deleteComponent(e, t) {
133
- let n = this.components[e];
134
- n && (delete n[t], this.emit("component-property-deleted", e, t));
135
- }
136
- deleteAllComponentMemory() {
137
- let e = this.world.registry, t = this.components;
138
- for (let n of Object.keys(t)) {
139
- let r = e[n], i = t[n];
140
- i && this.world.deferComponentMemoryFree(r.memoryComponent, i.index, r.free ? () => r.free(i) : void 0);
141
- }
142
- }
143
- load(e) {
144
- let t = e, n = this.world.registry;
145
- for (let r of Object.keys(n)) {
146
- if (r === "entity") continue;
147
- let i = n[r];
148
- i.loadInFinishLoading || i.loadProperties.some((e) => e in t) && this.loadComponent(r, e, !1);
149
- }
150
- this.config = e;
151
- }
152
- save() {
153
- let e = {}, t = this.world.registry, n = this.components;
154
- for (let r of Object.keys(n)) {
155
- let i = t[r], a = n[r];
156
- i.save && a && Object.assign(e, i.save(a));
157
- }
158
- return e;
159
- }
160
- finishLoading() {
161
- let e = this.config;
162
- if (!e) return;
163
- let t = e, n = this.world.registry;
164
- for (let r of Object.keys(n)) {
165
- if (r === "entity") continue;
166
- let i = n[r];
167
- i.loadInFinishLoading && i.loadProperties.some((e) => e in t) && this.loadComponent(r, e, !1);
168
- }
169
- }
170
- }, w = class extends S.default {
101
+ })))(), 1), k = class extends O.default {
171
102
  world;
172
103
  name;
173
104
  currentDelta = 0;
@@ -211,7 +142,7 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
211
142
  destroy() {
212
143
  this.removeAllListeners();
213
144
  }
214
- }, T = class extends w {
145
+ }, A = class extends k {
215
146
  remainingInstancesToRun = [];
216
147
  remainingInstancesStartTime = null;
217
148
  iterationsPerCheck;
@@ -261,7 +192,7 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
261
192
  }
262
193
  beforeRunIterables() {}
263
194
  getIterableEntityId(e) {}
264
- }, E = class extends T {
195
+ }, j = class extends A {
265
196
  entities = /* @__PURE__ */ new Map();
266
197
  options;
267
198
  constructor(e, t = { name: "EntitySystem" }) {
@@ -280,7 +211,7 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
280
211
  }), e;
281
212
  }
282
213
  updateIterable(e, t) {
283
- e.components.entity.dead || this.updateEntity(e, t);
214
+ e.components.entity.dead || this.entities.get(e.eid) !== e || this.updateEntity(e, t);
284
215
  }
285
216
  filterEntity(e) {
286
217
  return !e.components.entity.isStatic;
@@ -298,11 +229,11 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
298
229
  this.entities.delete(e.eid);
299
230
  }
300
231
  shouldRun() {
301
- return this.entities.size > 0;
232
+ return this.isCurrentlyRunning() || this.entities.size > 0;
302
233
  }
303
- }, D = class {
234
+ }, M = class {
304
235
  onmessage(e, t = []) {}
305
- }, O = class extends D {
236
+ }, N = class extends M {
306
237
  updateFunction;
307
238
  entities = [];
308
239
  queryEntities = {};
@@ -310,12 +241,13 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
310
241
  world;
311
242
  allocator;
312
243
  createsEntities;
313
- constructor(e, t, n = !1) {
314
- super(), this.updateFunction = e, this.world = t, this.createsEntities = n;
315
- let r = t.registry;
244
+ addsComponents;
245
+ constructor(e, t, n = !1, r = !1) {
246
+ super(), this.updateFunction = e, this.world = t, this.createsEntities = n, this.addsComponents = r;
247
+ let i = t.registry;
316
248
  this.allocator = {
317
249
  allocateEid: () => t.allocateEid(),
318
- allocateComponentBlock: (e, t) => r[e].memoryComponent.create(t)
250
+ allocateComponentBlock: (e, t) => i[e].memoryComponent.create(t)
319
251
  };
320
252
  }
321
253
  postMessage(e) {
@@ -325,16 +257,20 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
325
257
  else if (e.type === "run") {
326
258
  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) {
327
259
  let t = this.world.registry;
328
- e.world.buildEntityDescriptor = (e) => a(e, this.world.factory.configs, t, this.allocator);
260
+ e.world.buildEntityDescriptor = (e) => o(e, this.world.factory.configs, t, this.allocator, this.world.factory.getWorkerClasses());
329
261
  }
330
- let t = performance.now(), n = [], r = {}, i = [], o = [];
331
- this.entities = d(this.entities, e.entities);
332
- let s = {};
262
+ if (this.addsComponents) {
263
+ let t = this.world.registry;
264
+ e.world.buildComponentDescriptor = (e, n) => l(e, n, t, this.allocator);
265
+ }
266
+ let t = performance.now(), n = [], r = {}, i = [], s = [], c = [];
267
+ this.entities = a(this.entities, e.entities);
268
+ let u = {};
333
269
  Object.entries(e.queries).forEach(([e, t]) => {
334
- let n = d(this.queryEntities[e] ?? [], t);
335
- this.queryEntities[e] = n, s[e] = n;
270
+ let n = a(this.queryEntities[e] ?? [], t);
271
+ this.queryEntities[e] = n, u[e] = n;
336
272
  });
337
- let c = {
273
+ let d = {
338
274
  entityComponentChanged(e, t, r, i) {
339
275
  n.push({
340
276
  entityId: e,
@@ -365,51 +301,66 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
365
301
  },
366
302
  createEntity(e) {
367
303
  i.push(e);
304
+ },
305
+ addComponent(e, t) {
306
+ s.push({
307
+ type: "add",
308
+ entityId: e,
309
+ component: t
310
+ });
311
+ },
312
+ removeComponent(e, t) {
313
+ s.push({
314
+ type: "remove",
315
+ entityId: e,
316
+ componentName: String(t)
317
+ });
368
318
  }
369
- }, l = !1;
319
+ }, f = !1;
370
320
  if (this.updateFunction.preRun) try {
371
- this.updateFunction.preRun(e.world, this.entities, s, c);
321
+ this.updateFunction.preRun(e.world, this.entities, u, d);
372
322
  } catch (e) {
373
- l = !0, o.push({
323
+ f = !0, c.push({
374
324
  error: e,
375
325
  phase: "preRun"
376
326
  });
377
327
  }
378
- if (l || this.entities.forEach((t) => {
328
+ if (f || this.entities.forEach((t) => {
379
329
  try {
380
- this.updateFunction(e.world, t.entityId, t.components, s, c);
330
+ this.updateFunction(e.world, t.entityId, t.components, u, d);
381
331
  } catch (e) {
382
- o.push({
332
+ c.push({
383
333
  error: e,
384
334
  phase: "update",
385
335
  entityId: t.entityId
386
336
  });
387
337
  }
388
338
  }), this.updateFunction.entityRemoved) for (let t of e.entities.removed) try {
389
- this.updateFunction.entityRemoved(e.world, t, c);
339
+ this.updateFunction.entityRemoved(e.world, t, d);
390
340
  } catch (e) {
391
- o.push({
341
+ c.push({
392
342
  error: e,
393
343
  phase: "entityRemoved",
394
344
  entityId: t
395
345
  });
396
346
  }
397
- let u = performance.now() - t;
347
+ let p = performance.now() - t;
398
348
  this.onMessageTyped({
399
349
  type: "run-complete",
400
350
  generation: e.generation,
401
- runTime: u,
351
+ runTime: p,
402
352
  events: n,
403
353
  systemEvents: r,
404
354
  created: i,
405
- errors: o
355
+ componentChanges: s,
356
+ errors: c
406
357
  });
407
358
  }
408
359
  }
409
360
  onMessageTyped(e) {
410
361
  this.onmessage({ data: e });
411
362
  }
412
- }, k = "___main", A = class extends w {
363
+ }, P = "___main", F = class extends k {
413
364
  entities = /* @__PURE__ */ new Map();
414
365
  options;
415
366
  worker;
@@ -436,7 +387,7 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
436
387
  type: "grow-buffer",
437
388
  buffer: e
438
389
  });
439
- })) : (this.worker = new O(t.updateFunction, e, !!t.createsEntities), this.isWorkerThread = !1), this.initWorker();
390
+ })) : (this.worker = new N(t.updateFunction, e, !!t.createsEntities, !!t.addsComponents), this.isWorkerThread = !1), this.initWorker();
440
391
  }
441
392
  initWorker() {
442
393
  this.worker.onmessage = (e) => {
@@ -451,6 +402,17 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
451
402
  entityId: t,
452
403
  phase: n
453
404
  });
405
+ }), (t.componentChanges ?? []).forEach((e) => {
406
+ let t = this.world.getEntityByEid(e.entityId);
407
+ if (e.type === "add") {
408
+ let n = this.world.registry[e.component.name];
409
+ if (!t || !n || e.component.name === "entity") {
410
+ n?.memoryComponent.delete(e.component.index);
411
+ return;
412
+ }
413
+ let r = e.component.name;
414
+ t.removeComponent(r), t.attachComponent(r, e.component.index, !0);
415
+ } else t && e.componentName !== "entity" && t.removeComponent(e.componentName);
454
416
  });
455
417
  for (let e of Object.keys(t.systemEvents)) this.emit(e, t.systemEvents[e]);
456
418
  t.events.forEach((e) => {
@@ -486,7 +448,9 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
486
448
  data: this.options.getInitData?.(),
487
449
  heap: this.isWorkerThread ? this.world.heap.getSharedMemory() : void 0,
488
450
  sharedMemory: this.isWorkerThread ? this.world.getSharedComponentMemory() : void 0,
489
- factoryConfigs: this.isWorkerThread && this.options.createsEntities ? this.world.factory.configs : void 0
451
+ factoryConfigs: this.isWorkerThread && this.options.createsEntities ? this.world.factory.configs : void 0,
452
+ factoryClasses: this.isWorkerThread && this.options.createsEntities ? this.world.factory.getWorkerClasses() : void 0,
453
+ addsComponents: !!this.options.addsComponents
490
454
  };
491
455
  return this.worker.postMessage(n), e;
492
456
  }
@@ -525,7 +489,7 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
525
489
  elapsedTime: e
526
490
  };
527
491
  this.addDataToWorld?.(t), this.isRunning = !0;
528
- let n = this.buildQueryDelta(k, this.options), r = {};
492
+ let n = this.buildQueryDelta(P, this.options), r = {};
529
493
  Object.entries(this.options.queries ?? {}).forEach(([e, t]) => {
530
494
  r[e] = this.buildQueryDelta(e, t);
531
495
  });
@@ -587,13 +551,13 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
587
551
  }
588
552
  checkAddEntity(e) {
589
553
  let t = this.matchesQuery(e, this.options);
590
- return this.updateEntityList(k, this.entities, e, t), Object.entries(this.options.queries ?? {}).forEach(([t, n]) => {
554
+ return this.updateEntityList(P, this.entities, e, t), Object.entries(this.options.queries ?? {}).forEach(([t, n]) => {
591
555
  let r = this.queryEntities[t] ?? (this.queryEntities[t] = /* @__PURE__ */ new Map());
592
556
  this.updateEntityList(t, r, e, this.matchesQuery(e, n));
593
557
  }), t;
594
558
  }
595
559
  removeEntity(e) {
596
- this.updateEntityList(k, this.entities, e, !1), Object.entries(this.queryEntities).forEach(([t, n]) => {
560
+ this.updateEntityList(P, this.entities, e, !1), Object.entries(this.queryEntities).forEach(([t, n]) => {
597
561
  this.updateEntityList(t, n, e, !1);
598
562
  });
599
563
  }
@@ -608,30 +572,225 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
608
572
  destroy() {
609
573
  super.destroy(), "terminate" in this.worker && this.worker.terminate();
610
574
  }
611
- }, j = class {
575
+ }, I = class extends O.default {
576
+ eid;
577
+ config;
578
+ world;
579
+ componentMemoryDeletionScheduled = !1;
580
+ allowedComponents;
581
+ components = {};
582
+ constructor(e, t, n, r) {
583
+ super(), this.world = e, this.eid = n ?? e.allocateEid(), this.allowedComponents = r ?? e.factory.getAllowedComponentsForConfig(t), n === void 0 && (this.loadComponent("entity", t ?? {}, !1), t && this.load(t));
584
+ }
585
+ get id() {
586
+ return this.eid;
587
+ }
588
+ get dead() {
589
+ return this.components.entity.dead;
590
+ }
591
+ get type() {
592
+ return this.components.entity.type;
593
+ }
594
+ loadComponent(e, t, n = !0) {
595
+ this.assertComponentAllowed(e);
596
+ let r = this.world.registry[e], i = r.memoryComponent, a = i.create(r.toBlock(t, this)), o = r.attach(this, i, a);
597
+ return o.block ??= i.getBlock(a), this.components[e] = o, n && this.emit("component-added", e, o), o;
598
+ }
599
+ attachComponent(e, t, n = !1) {
600
+ this.assertComponentAllowed(e);
601
+ let r = this.world.registry[e], i = r.attach(this, r.memoryComponent, t);
602
+ return i.block ??= r.memoryComponent.getBlock(t), this.components[e] = i, n && this.emit("component-added", e, i), i;
603
+ }
604
+ removeComponent(e) {
605
+ if (this.componentMemoryDeletionScheduled) return;
606
+ let t = this.components[e];
607
+ if (t) {
608
+ let n = this.world.registry[e];
609
+ this.world.deferComponentMemoryFree(n.memoryComponent, t.index, n.free ? () => n.free(t) : void 0), delete this.components[e], this.emit("component-removed", e);
610
+ }
611
+ }
612
+ setComponent(e, t, n) {
613
+ this.assertComponentPropertyMutable(e, t);
614
+ let r = this.components[e];
615
+ r && (r[t] = n, this.emit("component-property-updated", e, t, n));
616
+ }
617
+ setComponentBulk(e, t) {
618
+ for (let n of Object.keys(t)) this.assertComponentPropertyMutable(e, n);
619
+ let n = this.components[e];
620
+ n && Object.assign(n, t);
621
+ }
622
+ deleteComponent(e, t) {
623
+ this.assertComponentPropertyMutable(e, t);
624
+ let n = this.components[e];
625
+ n && (delete n[t], this.emit("component-property-deleted", e, t));
626
+ }
627
+ deleteAllComponentMemory() {
628
+ if (this.componentMemoryDeletionScheduled) return;
629
+ this.componentMemoryDeletionScheduled = !0;
630
+ let e = this.world.registry, t = this.components;
631
+ for (let n of Object.keys(t)) {
632
+ let r = e[n], i = t[n];
633
+ i && this.world.deferComponentMemoryFree(r.memoryComponent, i.index, r.free ? () => r.free(i) : void 0);
634
+ }
635
+ }
636
+ load(e) {
637
+ let t = e, n = this.world.registry;
638
+ for (let r of Object.keys(n)) {
639
+ if (r === "entity" || !this.isComponentAllowed(r)) continue;
640
+ let i = n[r];
641
+ i.loadInFinishLoading || i.loadProperties.some((e) => e in t) && this.loadComponent(r, e, !1);
642
+ }
643
+ this.config = e;
644
+ }
645
+ save() {
646
+ let e = {}, t = this.world.registry, n = this.components;
647
+ for (let r of Object.keys(n)) {
648
+ let i = t[r], a = n[r];
649
+ i.save && a && Object.assign(e, i.save(a));
650
+ }
651
+ return e;
652
+ }
653
+ finishLoading() {
654
+ let e = this.config;
655
+ if (!e) return;
656
+ let t = e, n = this.world.registry;
657
+ for (let r of Object.keys(n)) {
658
+ if (r === "entity" || !this.isComponentAllowed(r)) continue;
659
+ let i = n[r];
660
+ i.loadInFinishLoading && i.loadProperties.some((e) => e in t) && this.loadComponent(r, e, !1);
661
+ }
662
+ }
663
+ isComponentAllowed(e) {
664
+ return e === "entity" || !this.allowedComponents || this.allowedComponents.has(String(e));
665
+ }
666
+ setAllowedComponents(e) {
667
+ if (this.allowedComponents && this.allowedComponents !== e) throw Error("Entity component allowlist is immutable");
668
+ this.allowedComponents = e;
669
+ }
670
+ assertComponentAllowed(e) {
671
+ if (!this.isComponentAllowed(e)) throw Error(`Component ${String(e)} is not allowed for entity type ${this.type}`);
672
+ }
673
+ assertComponentPropertyMutable(e, t) {
674
+ if (e === "entity" && (t === "type" || t === "class")) throw Error(`Entity ${t} is immutable`);
675
+ }
676
+ }, L = class {
612
677
  world;
613
678
  configs;
614
- constructor(e = {}) {
615
- this.configs = e;
679
+ classes;
680
+ allowedComponents = /* @__PURE__ */ new Map();
681
+ constructor(e = {}, t = {}) {
682
+ this.configs = e, this.classes = t;
683
+ for (let e of Object.keys(t)) this.allowedComponents.set(e, new Set(t[e].components));
616
684
  }
617
685
  register(e, t) {
618
- this.configs[e] = t;
686
+ this.world && this.validateTemplate(e, t), this.configs[e] = t;
687
+ }
688
+ setWorld(e) {
689
+ this.world = e;
690
+ for (let t of Object.keys(this.classes)) {
691
+ let n = this.classes[t].entity;
692
+ if (n !== I && !(n.prototype instanceof I)) throw Error(`Entity class ${t} must extend BaseEntity`);
693
+ 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}`);
694
+ }
695
+ for (let e of Object.keys(this.configs)) this.validateTemplate(e, this.configs[e]);
619
696
  }
620
697
  getConfig(e) {
621
- let t = e?.type, n = t ? this.configs[t] : void 0;
622
- return n ? {
623
- ...n,
698
+ let t = e, n = t?.type, r = n ? this.configs[n] : void 0;
699
+ if (this.hasClasses) {
700
+ if (!n || !r) throw Error(`Unknown entity type: ${n ?? ""}`);
701
+ if (Object.prototype.hasOwnProperty.call(t, "class")) throw Error("Entity class comes from its type template and cannot be supplied by an instance config");
702
+ }
703
+ let i = r ? {
704
+ ...r,
624
705
  ...e
625
706
  } : e;
707
+ return this.hasClasses && n && this.validateResolvedConfig(n, i), i;
626
708
  }
627
709
  loadEntity(e, t = !0) {
628
- let n = this.createEntity(this.getConfig(e));
629
- return this.world.addEntity(n, t);
710
+ let n = e.type, r = this.getConfig(e);
711
+ this.hasClasses && n && this.validateResolvedConfig(n, r);
712
+ let i = this.getClassDefinition(r), a = i ? this.constructEntity(i, r) : this.createEntity(r);
713
+ return this.world.addEntity(a, t);
714
+ }
715
+ createAdoptedEntity(e, t, n) {
716
+ if (!t) {
717
+ if (this.hasClasses) throw Error(`Entity type ${e} has no class`);
718
+ return new I(this.world, void 0, n);
719
+ }
720
+ let r = this.classes[t];
721
+ if (!r) throw Error(`Unknown entity class: ${t}`);
722
+ this.validateTypeClass(e, t);
723
+ let i = Reflect.construct(r.entity, [
724
+ this.world,
725
+ void 0,
726
+ n,
727
+ this.allowedComponents.get(t)
728
+ ]);
729
+ return i.setAllowedComponents(this.allowedComponents.get(t)), i;
730
+ }
731
+ isComponentAllowed(e, t) {
732
+ return !e || !this.hasClasses || this.allowedComponents.get(e)?.has(t) === !0;
733
+ }
734
+ getWorkerClasses() {
735
+ if (!this.hasClasses) return;
736
+ let e = {};
737
+ for (let t of Object.keys(this.classes)) e[t] = { components: [...this.classes[t].components] };
738
+ return e;
739
+ }
740
+ getAllowedComponentsForConfig(e) {
741
+ return e ? this.getAllowedComponents(e) : void 0;
630
742
  }
631
743
  createEntity(e) {
632
- return new C(this.world, e);
744
+ return new I(this.world, e);
745
+ }
746
+ get hasClasses() {
747
+ return this.allowedComponents.size > 0;
748
+ }
749
+ getClassDefinition(e) {
750
+ let t = e.class;
751
+ return t ? this.classes[t] : void 0;
752
+ }
753
+ getAllowedComponents(e) {
754
+ let t = e.class;
755
+ return t ? this.allowedComponents.get(t) : void 0;
756
+ }
757
+ constructEntity(e, t) {
758
+ let n = t.class;
759
+ return Reflect.construct(e.entity, [
760
+ this.world,
761
+ t,
762
+ void 0,
763
+ this.allowedComponents.get(n ?? "")
764
+ ]);
765
+ }
766
+ validateTemplate(e, t) {
767
+ if (!this.hasClasses) return;
768
+ let n = t;
769
+ if (n.type !== e) throw Error(`Entity template ${e} must declare the same type`);
770
+ if (!n.class || !this.classes[n.class]) throw Error(`Entity template ${e} has unknown class ${n.class ?? ""}`);
771
+ this.validateComponentTriggers(e, n.class, t);
772
+ }
773
+ validateResolvedConfig(e, t) {
774
+ let n = t;
775
+ if (n.type !== e) throw Error(`Entity type ${e} is immutable`);
776
+ if (!n.class || !this.classes[n.class]) throw Error(`Entity type ${e} has unknown class ${n.class ?? ""}`);
777
+ this.validateTypeClass(e, n.class), this.validateComponentTriggers(e, n.class, t);
778
+ }
779
+ validateTypeClass(e, t) {
780
+ let n = this.configs[e];
781
+ if (!n || n.class !== t) throw Error(`Entity type ${e} does not belong to class ${t}`);
782
+ }
783
+ validateComponentTriggers(e, t, n) {
784
+ let r = this.allowedComponents.get(t), i = /* @__PURE__ */ new Set();
785
+ for (let e of r) for (let t of this.world.registry[e].loadProperties) i.add(t);
786
+ let a = n;
787
+ for (let n of Object.keys(this.world.registry)) {
788
+ if (n === "entity" || r.has(n)) continue;
789
+ let o = this.world.registry[n].loadProperties.find((e) => e in a && !i.has(e));
790
+ if (o) throw Error(`Entity type ${e} class ${t} cannot load component ${n} from property ${o}`);
791
+ }
633
792
  }
634
- }, M = p, N = 1e4, P = class extends S.default {
793
+ }, R = y, z = 1e4, B = class extends O.default {
635
794
  heap;
636
795
  constantStrings;
637
796
  eidCounter;
@@ -655,20 +814,20 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
655
814
  waitingSystems: /* @__PURE__ */ new Set(),
656
815
  waitElapsed: 0
657
816
  };
658
- constructor(e, t = {}) {
659
- super(), this.heap = new f({ bufferSize: t.heapSize ?? M }), this.constantStrings = new n(this.heap), this.eidCounter = this.heap.allocUI32(1), this.heap.addOnGrowBufferHandlers((e) => this.emit("grow-buffer", e));
660
- let i = {
661
- ...e,
662
- entity: l
817
+ constructor(t, n = {}) {
818
+ super(), this.heap = new v({ bufferSize: n.heapSize ?? R }), this.constantStrings = new e(this.heap), this.eidCounter = this.heap.allocUI32(1), this.heap.addOnGrowBufferHandlers((e) => this.emit("grow-buffer", e));
819
+ let r = {
820
+ ...t,
821
+ entity: i
663
822
  }, a = {};
664
- for (let e of Object.keys(i)) {
665
- let t = i[e];
823
+ for (let e of Object.keys(r)) {
824
+ let t = r[e];
666
825
  a[e] = {
667
826
  ...t,
668
- memoryComponent: new r(this.heap, t.type, t.size)
827
+ memoryComponent: new _(this.heap, t.type, t.size)
669
828
  };
670
829
  }
671
- this.registry = a, this.factory = t.factory ?? new j(), this.factory.world = this;
830
+ this.registry = a, this.factory = n.factory ?? new L(), this.factory.setWorld(this);
672
831
  }
673
832
  allocateEid() {
674
833
  return Atomics.add(this.eidCounter.data, 0, 1) + 1;
@@ -685,7 +844,7 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
685
844
  this.heap.buffers[e.bufferPosition] === void 0 && this.heap.addSharedBuffer(e), this.emit("grow-buffer", e);
686
845
  }
687
846
  get needsSpareBuffer() {
688
- return this.systems.some((e) => e instanceof A && e.isWorkerThread && !!e.options.createsEntities);
847
+ return this.systems.some((e) => e instanceof F && e.isWorkerThread && (!!e.options.createsEntities || !!e.options.addsComponents));
689
848
  }
690
849
  async init() {
691
850
  await Promise.all(this.systems.map((e) => e.init()).filter((e) => e instanceof Promise));
@@ -695,9 +854,9 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
695
854
  }
696
855
  addEntity(e, t = !0) {
697
856
  return this.entities.set(e.eid, e), e.world = this, this.pristine = !1, e.on("component-added", (t) => {
698
- this.addEntityToComponentSystem(e, t);
857
+ this.addEntityToEntityWorkerSystem(e, t);
699
858
  }), e.on("component-removed", (t) => {
700
- this.removeEntityFromComponentSystem(e, t);
859
+ this.removeEntityFromEntityWorkerSystem(e, t);
701
860
  }), t && (e.finishLoading(), this.emit("entity-added", e), e.on("death", () => {
702
861
  this.onEntityDied(e);
703
862
  })), e;
@@ -706,13 +865,24 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
706
865
  return this.factory.loadEntity(e, t);
707
866
  }
708
867
  adoptEntity(e) {
709
- let t = new C(this, void 0, e.eid);
710
- t.loadComponent("entity", {
711
- type: e.type,
712
- isStatic: e.isStatic
713
- }, !1);
714
- for (let n of Object.keys(e.components)) t.attachComponent(n, e.components[n]);
715
- return this.addEntity(t, !0);
868
+ let t, n = /* @__PURE__ */ new Set();
869
+ try {
870
+ for (let t of Object.keys(e.components)) {
871
+ if (!(t in this.registry)) throw Error(`Worker-created entity contains unknown component ${t}`);
872
+ if (!this.factory.isComponentAllowed(e.class, t)) throw Error(`Component ${t} is not allowed for entity class ${e.class ?? ""}`);
873
+ }
874
+ t = this.factory.createAdoptedEntity(e.type, e.class, e.eid), t.loadComponent("entity", {
875
+ type: e.type,
876
+ class: e.class,
877
+ isStatic: e.isStatic
878
+ }, !1);
879
+ for (let r of Object.keys(e.components)) t.attachComponent(r, e.components[r]), n.add(r);
880
+ return this.addEntity(t, !0);
881
+ } catch (r) {
882
+ t?.deleteAllComponentMemory();
883
+ for (let t of Object.keys(e.components)) !n.has(t) && t in this.registry && this.deferComponentMemoryFree(this.registry[t].memoryComponent, e.components[t]);
884
+ throw r;
885
+ }
716
886
  }
717
887
  load(e) {
718
888
  if (!this.pristine) {
@@ -720,6 +890,7 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
720
890
  this.systems.forEach((e) => e.clear()), this.consolidateFreeBuffersForReload();
721
891
  }
722
892
  for (let e of Object.keys(this.factory.configs)) this.constantStrings.getOrCreate(e);
893
+ for (let e of Object.keys(this.factory.classes)) this.constantStrings.getOrCreate(e);
723
894
  let t = e.entities.map((e) => this.loadEntity(e, !1));
724
895
  for (let e of t) e.finishLoading(), this.emit("entity-added", e), e.on("death", () => {
725
896
  this.onEntityDied(e);
@@ -728,15 +899,32 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
728
899
  }
729
900
  async clear() {
730
901
  if (!this.pristine) {
902
+ await Promise.all(this.systems.map((e) => e.waitForRunToComplete()).filter((e) => e instanceof Promise));
731
903
  for (let e of Array.from(this.entities.values())) this.removeEntity(e);
732
- this.systems.forEach((e) => e.clear()), await Promise.all(this.systems.map((e) => e.waitForRunToComplete()).filter((e) => e instanceof Promise)), this.freeAllPendingBuffers(), this.pristine = !0;
904
+ this.systems.forEach((e) => e.clear()), this.freeAllPendingBuffers(), this.pristine = !0;
733
905
  }
734
906
  }
735
907
  removeEntity(e) {
736
- this.entities.delete(e.eid) && this.emit("entity-removed", e), e.deleteAllComponentMemory();
908
+ this.entities.get(e.eid) === e && (this.entities.delete(e.eid), this.emit("entity-removed", e), e.deleteAllComponentMemory());
737
909
  }
738
910
  onEntityDied(e) {
739
- this.removeEntity(e);
911
+ if (this.entities.get(e.eid) !== e) return;
912
+ let t = this.registry, n = e.components;
913
+ for (let r of Object.keys(n)) {
914
+ let i = t[r], a = n[r];
915
+ if (i?.died && a) try {
916
+ i.died(a, e, this);
917
+ } catch (t) {
918
+ let n = t;
919
+ console.error(`Error in died hook for component ${String(r)} (entity ${e.eid}): ${n.message}`, n), this.emit("system-error", {
920
+ system: String(r),
921
+ error: n,
922
+ entityId: e.eid,
923
+ phase: "died"
924
+ });
925
+ }
926
+ }
927
+ this.emit("entity-died", e), this.removeEntity(e);
740
928
  }
741
929
  getEntityByEid(e) {
742
930
  return this.entities.get(e);
@@ -773,9 +961,9 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
773
961
  }
774
962
  checkFreeBufferTimeout(e) {
775
963
  let t = this.activeFreeBuffer;
776
- if (t.waitingSystems.size !== 0 && (t.waitElapsed += e, t.waitElapsed >= N)) {
964
+ if (t.waitingSystems.size !== 0 && (t.waitElapsed += e, t.waitElapsed >= z)) {
777
965
  let e = Array.from(t.waitingSystems).map((e) => e.name).join(", ");
778
- console.warn(`shared-memory-ecs: deferred component free waited over ${N}ms on system(s): ${e}; freeing anyway`), t.waitingSystems.clear(), this.processFreeBuffers();
966
+ console.warn(`shared-memory-ecs: deferred component free waited over ${z}ms on system(s): ${e}; freeing anyway`), t.waitingSystems.clear(), this.processFreeBuffers();
779
967
  }
780
968
  }
781
969
  addSystem(e) {
@@ -827,17 +1015,17 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
827
1015
  resume() {
828
1016
  this.paused = !1;
829
1017
  }
830
- addEntityToComponentSystem(e, t) {
1018
+ addEntityToEntityWorkerSystem(e, t) {
831
1019
  this.systems.forEach((n) => {
832
- (n instanceof E && n.options.components?.includes(t) || n instanceof A && this.componentAffectsComponentSystem(n, t)) && n.checkAddEntity(e);
1020
+ (n instanceof j && n.options.components?.includes(t) || n instanceof F && this.componentAffectsEntityWorkerSystem(n, t)) && n.checkAddEntity(e);
833
1021
  });
834
1022
  }
835
- removeEntityFromComponentSystem(e, t) {
1023
+ removeEntityFromEntityWorkerSystem(e, t) {
836
1024
  this.systems.forEach((n) => {
837
- n instanceof E && n.options.components?.includes(t) ? n.removeEntity(e) : n instanceof A && this.componentAffectsComponentSystem(n, t) && n.checkAddEntity(e);
1025
+ n instanceof j && n.options.components?.includes(t) ? n.removeEntity(e) : n instanceof F && this.componentAffectsEntityWorkerSystem(n, t) && n.checkAddEntity(e);
838
1026
  });
839
1027
  }
840
- componentAffectsComponentSystem(e, t) {
1028
+ componentAffectsEntityWorkerSystem(e, t) {
841
1029
  let n = e.options.required.includes(t) || !!e.options.not?.includes(t) || !!e.options.optional?.includes(t), r = Object.values(e.options.queries ?? {}).some((e) => e.required.includes(t) || !!e.not?.includes(t) || !!e.optional?.includes(t));
842
1030
  return n || r;
843
1031
  }
@@ -848,20 +1036,28 @@ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescr
848
1036
  }
849
1037
  };
850
1038
  //#endregion
1039
+ //#region src/entity-class.ts
1040
+ function V(e, t) {
1041
+ return t;
1042
+ }
1043
+ function H(e, t) {
1044
+ return t;
1045
+ }
1046
+ //#endregion
851
1047
  //#region src/actions/kill-entity.ts
852
- function F(e) {
1048
+ function U(e) {
853
1049
  e.components.entity.dead = !0, e.emit("death");
854
1050
  }
855
1051
  //#endregion
856
1052
  //#region src/performance-timing.ts
857
- var I = 1e3, L = {
1053
+ var W = 1e3, G = {
858
1054
  avg: 0,
859
1055
  min: 0,
860
1056
  max: 0,
861
1057
  samples: 0
862
1058
  };
863
- function R(e) {
864
- if (!e.length) return { ...L };
1059
+ function K(e) {
1060
+ if (!e.length) return { ...G };
865
1061
  let t = 0, n = Infinity, r = 0;
866
1062
  for (let i of e) t += i, i < n && (n = i), i > r && (r = i);
867
1063
  return {
@@ -871,13 +1067,13 @@ function R(e) {
871
1067
  samples: e.length
872
1068
  };
873
1069
  }
874
- var z = class extends S.default {
1070
+ var q = class extends O.default {
875
1071
  world;
876
1072
  ticksBetweenUpdates;
877
1073
  stats = {
878
- update: { ...L },
1074
+ update: { ...G },
879
1075
  systems: [],
880
- events: { ...L }
1076
+ events: { ...G }
881
1077
  };
882
1078
  ticks = 0;
883
1079
  updateStart = 0;
@@ -894,9 +1090,9 @@ var z = class extends S.default {
894
1090
  this.ticks = 0, this.updateTimes = [], this.systemTimings.forEach((e) => {
895
1091
  e.run = [], e.events = [], e.eventStart = -1;
896
1092
  }), this.stats = {
897
- update: { ...L },
1093
+ update: { ...G },
898
1094
  systems: [],
899
- events: { ...L }
1095
+ events: { ...G }
900
1096
  };
901
1097
  }
902
1098
  destroy() {
@@ -938,22 +1134,39 @@ var z = class extends S.default {
938
1134
  let t = this.systemTimings.get(e.name);
939
1135
  return {
940
1136
  name: e.name,
941
- run: R(t?.run ?? []),
942
- events: R(t?.events ?? [])
1137
+ run: K(t?.run ?? []),
1138
+ events: K(t?.events ?? [])
943
1139
  };
944
- }), t = { ...L };
1140
+ }), t = { ...G };
945
1141
  e.forEach((e) => {
946
1142
  t.avg += e.events.avg, t.min += e.events.min, t.max += e.events.max, t.samples += e.events.samples;
947
1143
  }), this.stats = {
948
- update: R(this.updateTimes),
1144
+ update: K(this.updateTimes),
949
1145
  systems: e,
950
1146
  events: t
951
1147
  }, this.ticks = 0, this.updateTimes = [], this.systemTimings.forEach((e) => {
952
1148
  e.run = [], e.events = [];
953
1149
  }), this.emit("stats-updated", this.stats);
954
1150
  }
1151
+ }, J = class extends F {
1152
+ constructor(e, t) {
1153
+ super(e, {
1154
+ ...t,
1155
+ required: [],
1156
+ updateFunction: u(t.updateFunction)
1157
+ });
1158
+ }
1159
+ checkAddEntity(e) {
1160
+ return Object.entries(this.options.queries ?? {}).forEach(([t, n]) => {
1161
+ let r = this.queryEntities[t] ?? (this.queryEntities[t] = /* @__PURE__ */ new Map());
1162
+ this.updateEntityList(t, r, e, this.matchesQuery(e, n));
1163
+ }), !1;
1164
+ }
1165
+ shouldRun() {
1166
+ return !0;
1167
+ }
955
1168
  };
956
1169
  //#endregion
957
- export { C as BaseEntity, P as BaseWorld, t as Component, A as ComponentSystem, O as ComponentWebWorker, n as ConstantStringCache, i as DEAD_INDEX, I as DEFAULT_TICKS_BETWEEN_UPDATES, j as EntityFactory, E as EntitySystem, T as IterableSystem, r as MemoryComponent, z as PerformanceTiming, e as STATIC_INDEX, w as System, s as TYPE_INDEX, D as WebWorker, u as createComponentWorker, o as createEntityWorker, l as entityDefinition, F as killEntity, c as killEntityWorker };
1170
+ export { I as BaseEntity, B as BaseWorld, n as CLASS_INDEX, f as Component, e as ConstantStringCache, c as DEAD_INDEX, W as DEFAULT_TICKS_BETWEEN_UPDATES, L as EntityFactory, j as EntitySystem, N as EntitySystemWebWorker, F as EntityWorkerSystem, A as IterableSystem, _ as MemoryComponent, q as PerformanceTiming, g as STATIC_INDEX, k as System, r as TYPE_INDEX, M as WebWorker, J as WorkerSystem, t as addComponentWorker, p as createEntitySystemWorker, d as createEntityWorker, h as createSystemWorker, V as defineEntityClasses, H as defineEntityConfigs, i as entityDefinition, U as killEntity, m as killEntityWorker, s as removeComponentWorker };
958
1171
 
959
1172
  //# sourceMappingURL=index.js.map