@daneren2005/shared-memory-ecs 1.6.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,17 +1,17 @@
1
- import { a as e, c as t, d as n, f as r, i, l as a, m as o, n as s, o as c, p as l, r as u, s as d, t as f, u as p } from "./create-system-worker-BM5E-S92.js";
2
- import m from "@daneren2005/shared-memory-objects/memory-heap";
3
- import { MAX_BYTE_OFFSET_LENGTH as h } 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 g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescriptor, y = Object.getOwnPropertyNames, b = Object.getPrototypeOf, x = Object.prototype.hasOwnProperty, S = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t.exports), C = (e, t, n, r) => {
6
- if (t && typeof t == "object" || typeof t == "function") for (var i = y(t), a = 0, o = i.length, s; a < o; a++) s = i[a], !x.call(e, s) && s !== n && _(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 = v(t, s)) || r.enumerable
8
+ enumerable: !(r = S(t, s)) || r.enumerable
9
9
  });
10
10
  return e;
11
- }, w = /* @__PURE__ */ ((e, t, n) => (n = e == null ? {} : g(b(e)), C(t || !e || !e.__esModule ? _(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__ */ S(((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,80 +98,7 @@ var g = Object.create, _ = Object.defineProperty, v = 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), T = class extends w.default {
102
- eid;
103
- config;
104
- world;
105
- componentMemoryDeletionScheduled = !1;
106
- components = {};
107
- constructor(e, t, n) {
108
- super(), this.world = e, this.eid = n ?? e.allocateEid(), n === void 0 && (this.loadComponent("entity", t ?? {}, !1), t && this.load(t));
109
- }
110
- loadComponent(e, t, n = !0) {
111
- let r = this.world.registry[e], i = r.memoryComponent, a = i.create(r.toBlock(t, this)), o = r.attach(this, i, a);
112
- return o.block ??= i.getBlock(a), this.components[e] = o, n && this.emit("component-added", e, o), o;
113
- }
114
- attachComponent(e, t) {
115
- let n = this.world.registry[e], r = n.attach(this, n.memoryComponent, t);
116
- return r.block ??= n.memoryComponent.getBlock(t), this.components[e] = r, r;
117
- }
118
- removeComponent(e) {
119
- if (this.componentMemoryDeletionScheduled) return;
120
- let t = this.components[e];
121
- if (t) {
122
- let n = this.world.registry[e];
123
- this.world.deferComponentMemoryFree(n.memoryComponent, t.index, n.free ? () => n.free(t) : void 0), delete this.components[e], this.emit("component-removed", e);
124
- }
125
- }
126
- setComponent(e, t, n) {
127
- let r = this.components[e];
128
- r && (r[t] = n, this.emit("component-property-updated", e, t, n));
129
- }
130
- setComponentBulk(e, t) {
131
- let n = this.components[e];
132
- n && Object.assign(n, t);
133
- }
134
- deleteComponent(e, t) {
135
- let n = this.components[e];
136
- n && (delete n[t], this.emit("component-property-deleted", e, t));
137
- }
138
- deleteAllComponentMemory() {
139
- if (this.componentMemoryDeletionScheduled) return;
140
- this.componentMemoryDeletionScheduled = !0;
141
- let e = this.world.registry, t = this.components;
142
- for (let n of Object.keys(t)) {
143
- let r = e[n], i = t[n];
144
- i && this.world.deferComponentMemoryFree(r.memoryComponent, i.index, r.free ? () => r.free(i) : void 0);
145
- }
146
- }
147
- load(e) {
148
- let t = e, n = this.world.registry;
149
- for (let r of Object.keys(n)) {
150
- if (r === "entity") continue;
151
- let i = n[r];
152
- i.loadInFinishLoading || i.loadProperties.some((e) => e in t) && this.loadComponent(r, e, !1);
153
- }
154
- this.config = e;
155
- }
156
- save() {
157
- let e = {}, t = this.world.registry, n = this.components;
158
- for (let r of Object.keys(n)) {
159
- let i = t[r], a = n[r];
160
- i.save && a && Object.assign(e, i.save(a));
161
- }
162
- return e;
163
- }
164
- finishLoading() {
165
- let e = this.config;
166
- if (!e) return;
167
- let t = e, n = this.world.registry;
168
- for (let r of Object.keys(n)) {
169
- if (r === "entity") continue;
170
- let i = n[r];
171
- i.loadInFinishLoading && i.loadProperties.some((e) => e in t) && this.loadComponent(r, e, !1);
172
- }
173
- }
174
- }, E = class extends w.default {
101
+ })))(), 1), k = class extends O.default {
175
102
  world;
176
103
  name;
177
104
  currentDelta = 0;
@@ -215,7 +142,7 @@ var g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescr
215
142
  destroy() {
216
143
  this.removeAllListeners();
217
144
  }
218
- }, D = class extends E {
145
+ }, A = class extends k {
219
146
  remainingInstancesToRun = [];
220
147
  remainingInstancesStartTime = null;
221
148
  iterationsPerCheck;
@@ -265,7 +192,7 @@ var g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescr
265
192
  }
266
193
  beforeRunIterables() {}
267
194
  getIterableEntityId(e) {}
268
- }, O = class extends D {
195
+ }, j = class extends A {
269
196
  entities = /* @__PURE__ */ new Map();
270
197
  options;
271
198
  constructor(e, t = { name: "EntitySystem" }) {
@@ -304,9 +231,9 @@ var g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescr
304
231
  shouldRun() {
305
232
  return this.isCurrentlyRunning() || this.entities.size > 0;
306
233
  }
307
- }, k = class {
234
+ }, M = class {
308
235
  onmessage(e, t = []) {}
309
- }, A = class extends k {
236
+ }, N = class extends M {
310
237
  updateFunction;
311
238
  entities = [];
312
239
  queryEntities = {};
@@ -314,12 +241,13 @@ var g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescr
314
241
  world;
315
242
  allocator;
316
243
  createsEntities;
317
- constructor(e, t, n = !1) {
318
- super(), this.updateFunction = e, this.world = t, this.createsEntities = n;
319
- 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;
320
248
  this.allocator = {
321
249
  allocateEid: () => t.allocateEid(),
322
- allocateComponentBlock: (e, t) => r[e].memoryComponent.create(t)
250
+ allocateComponentBlock: (e, t) => i[e].memoryComponent.create(t)
323
251
  };
324
252
  }
325
253
  postMessage(e) {
@@ -329,91 +257,110 @@ var g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescr
329
257
  else if (e.type === "run") {
330
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) {
331
259
  let t = this.world.registry;
332
- e.world.buildEntityDescriptor = (e) => n(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());
261
+ }
262
+ if (this.addsComponents) {
263
+ let t = this.world.registry;
264
+ e.world.buildComponentDescriptor = (e, n) => l(e, n, t, this.allocator);
333
265
  }
334
- let t = performance.now(), i = [], a = {}, o = [], s = [];
335
- this.entities = r(this.entities, e.entities);
336
- let c = {};
266
+ let t = performance.now(), n = [], r = {}, i = [], s = [], c = [];
267
+ this.entities = a(this.entities, e.entities);
268
+ let u = {};
337
269
  Object.entries(e.queries).forEach(([e, t]) => {
338
- let n = r(this.queryEntities[e] ?? [], t);
339
- this.queryEntities[e] = n, c[e] = n;
270
+ let n = a(this.queryEntities[e] ?? [], t);
271
+ this.queryEntities[e] = n, u[e] = n;
340
272
  });
341
- let l = {
342
- entityComponentChanged(e, t, n, r) {
343
- i.push({
273
+ let d = {
274
+ entityComponentChanged(e, t, r, i) {
275
+ n.push({
344
276
  entityId: e,
345
277
  event: "component-property-updated",
346
278
  args: [
347
279
  t,
348
- n,
349
- r
280
+ r,
281
+ i
350
282
  ]
351
283
  });
352
284
  },
353
- emitEntityEvent(e, t, ...n) {
354
- i.push({
285
+ emitEntityEvent(e, t, ...r) {
286
+ n.push({
355
287
  entityId: e,
356
288
  event: t,
357
- args: n
289
+ args: r
358
290
  });
359
291
  },
360
292
  emitSystemEvent(e, t) {
361
- (a[e] ?? (a[e] = [])).push(t);
293
+ (r[e] ?? (r[e] = [])).push(t);
362
294
  },
363
295
  entityDied(e) {
364
- i.push({
296
+ n.push({
365
297
  entityId: e,
366
298
  event: "death",
367
299
  args: []
368
300
  });
369
301
  },
370
302
  createEntity(e) {
371
- o.push(e);
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
+ });
372
318
  }
373
- }, u = !1;
319
+ }, f = !1;
374
320
  if (this.updateFunction.preRun) try {
375
- this.updateFunction.preRun(e.world, this.entities, c, l);
321
+ this.updateFunction.preRun(e.world, this.entities, u, d);
376
322
  } catch (e) {
377
- u = !0, s.push({
323
+ f = !0, c.push({
378
324
  error: e,
379
325
  phase: "preRun"
380
326
  });
381
327
  }
382
- if (u || this.entities.forEach((t) => {
328
+ if (f || this.entities.forEach((t) => {
383
329
  try {
384
- this.updateFunction(e.world, t.entityId, t.components, c, l);
330
+ this.updateFunction(e.world, t.entityId, t.components, u, d);
385
331
  } catch (e) {
386
- s.push({
332
+ c.push({
387
333
  error: e,
388
334
  phase: "update",
389
335
  entityId: t.entityId
390
336
  });
391
337
  }
392
338
  }), this.updateFunction.entityRemoved) for (let t of e.entities.removed) try {
393
- this.updateFunction.entityRemoved(e.world, t, l);
339
+ this.updateFunction.entityRemoved(e.world, t, d);
394
340
  } catch (e) {
395
- s.push({
341
+ c.push({
396
342
  error: e,
397
343
  phase: "entityRemoved",
398
344
  entityId: t
399
345
  });
400
346
  }
401
- let d = performance.now() - t;
347
+ let p = performance.now() - t;
402
348
  this.onMessageTyped({
403
349
  type: "run-complete",
404
350
  generation: e.generation,
405
- runTime: d,
406
- events: i,
407
- systemEvents: a,
408
- created: o,
409
- errors: s
351
+ runTime: p,
352
+ events: n,
353
+ systemEvents: r,
354
+ created: i,
355
+ componentChanges: s,
356
+ errors: c
410
357
  });
411
358
  }
412
359
  }
413
360
  onMessageTyped(e) {
414
361
  this.onmessage({ data: e });
415
362
  }
416
- }, j = "___main", M = class extends E {
363
+ }, P = "___main", F = class extends k {
417
364
  entities = /* @__PURE__ */ new Map();
418
365
  options;
419
366
  worker;
@@ -440,7 +387,7 @@ var g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescr
440
387
  type: "grow-buffer",
441
388
  buffer: e
442
389
  });
443
- })) : (this.worker = new A(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();
444
391
  }
445
392
  initWorker() {
446
393
  this.worker.onmessage = (e) => {
@@ -455,6 +402,17 @@ var g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescr
455
402
  entityId: t,
456
403
  phase: n
457
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);
458
416
  });
459
417
  for (let e of Object.keys(t.systemEvents)) this.emit(e, t.systemEvents[e]);
460
418
  t.events.forEach((e) => {
@@ -490,7 +448,9 @@ var g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescr
490
448
  data: this.options.getInitData?.(),
491
449
  heap: this.isWorkerThread ? this.world.heap.getSharedMemory() : void 0,
492
450
  sharedMemory: this.isWorkerThread ? this.world.getSharedComponentMemory() : void 0,
493
- 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
494
454
  };
495
455
  return this.worker.postMessage(n), e;
496
456
  }
@@ -529,7 +489,7 @@ var g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescr
529
489
  elapsedTime: e
530
490
  };
531
491
  this.addDataToWorld?.(t), this.isRunning = !0;
532
- let n = this.buildQueryDelta(j, this.options), r = {};
492
+ let n = this.buildQueryDelta(P, this.options), r = {};
533
493
  Object.entries(this.options.queries ?? {}).forEach(([e, t]) => {
534
494
  r[e] = this.buildQueryDelta(e, t);
535
495
  });
@@ -591,13 +551,13 @@ var g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescr
591
551
  }
592
552
  checkAddEntity(e) {
593
553
  let t = this.matchesQuery(e, this.options);
594
- return this.updateEntityList(j, 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]) => {
595
555
  let r = this.queryEntities[t] ?? (this.queryEntities[t] = /* @__PURE__ */ new Map());
596
556
  this.updateEntityList(t, r, e, this.matchesQuery(e, n));
597
557
  }), t;
598
558
  }
599
559
  removeEntity(e) {
600
- this.updateEntityList(j, 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]) => {
601
561
  this.updateEntityList(t, n, e, !1);
602
562
  });
603
563
  }
@@ -612,30 +572,225 @@ var g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescr
612
572
  destroy() {
613
573
  super.destroy(), "terminate" in this.worker && this.worker.terminate();
614
574
  }
615
- }, N = 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 {
616
677
  world;
617
678
  configs;
618
- constructor(e = {}) {
619
- 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));
620
684
  }
621
685
  register(e, t) {
622
- 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]);
623
696
  }
624
697
  getConfig(e) {
625
- let t = e?.type, n = t ? this.configs[t] : void 0;
626
- return n ? {
627
- ...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,
628
705
  ...e
629
706
  } : e;
707
+ return this.hasClasses && n && this.validateResolvedConfig(n, i), i;
630
708
  }
631
709
  loadEntity(e, t = !0) {
632
- let n = this.createEntity(this.getConfig(e));
633
- 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;
634
742
  }
635
743
  createEntity(e) {
636
- return new T(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
+ }
637
792
  }
638
- }, P = h, F = 1e4, I = class extends w.default {
793
+ }, R = y, z = 1e4, B = class extends O.default {
639
794
  heap;
640
795
  constantStrings;
641
796
  eidCounter;
@@ -659,20 +814,20 @@ var g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescr
659
814
  waitingSystems: /* @__PURE__ */ new Set(),
660
815
  waitElapsed: 0
661
816
  };
662
- constructor(e, t = {}) {
663
- super(), this.heap = new m({ bufferSize: t.heapSize ?? P }), this.constantStrings = new l(this.heap), this.eidCounter = this.heap.allocUI32(1), this.heap.addOnGrowBufferHandlers((e) => this.emit("grow-buffer", e));
664
- let n = {
665
- ...e,
666
- entity: a
667
- }, r = {};
668
- for (let e of Object.keys(n)) {
669
- let t = n[e];
670
- r[e] = {
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
822
+ }, a = {};
823
+ for (let e of Object.keys(r)) {
824
+ let t = r[e];
825
+ a[e] = {
671
826
  ...t,
672
- memoryComponent: new o(this.heap, t.type, t.size)
827
+ memoryComponent: new _(this.heap, t.type, t.size)
673
828
  };
674
829
  }
675
- this.registry = r, this.factory = t.factory ?? new N(), this.factory.world = this;
830
+ this.registry = a, this.factory = n.factory ?? new L(), this.factory.setWorld(this);
676
831
  }
677
832
  allocateEid() {
678
833
  return Atomics.add(this.eidCounter.data, 0, 1) + 1;
@@ -689,7 +844,7 @@ var g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescr
689
844
  this.heap.buffers[e.bufferPosition] === void 0 && this.heap.addSharedBuffer(e), this.emit("grow-buffer", e);
690
845
  }
691
846
  get needsSpareBuffer() {
692
- return this.systems.some((e) => e instanceof M && e.isWorkerThread && !!e.options.createsEntities);
847
+ return this.systems.some((e) => e instanceof F && e.isWorkerThread && (!!e.options.createsEntities || !!e.options.addsComponents));
693
848
  }
694
849
  async init() {
695
850
  await Promise.all(this.systems.map((e) => e.init()).filter((e) => e instanceof Promise));
@@ -710,13 +865,24 @@ var g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescr
710
865
  return this.factory.loadEntity(e, t);
711
866
  }
712
867
  adoptEntity(e) {
713
- let t = new T(this, void 0, e.eid);
714
- t.loadComponent("entity", {
715
- type: e.type,
716
- isStatic: e.isStatic
717
- }, !1);
718
- for (let n of Object.keys(e.components)) t.attachComponent(n, e.components[n]);
719
- 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
+ }
720
886
  }
721
887
  load(e) {
722
888
  if (!this.pristine) {
@@ -724,6 +890,7 @@ var g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescr
724
890
  this.systems.forEach((e) => e.clear()), this.consolidateFreeBuffersForReload();
725
891
  }
726
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);
727
894
  let t = e.entities.map((e) => this.loadEntity(e, !1));
728
895
  for (let e of t) e.finishLoading(), this.emit("entity-added", e), e.on("death", () => {
729
896
  this.onEntityDied(e);
@@ -794,9 +961,9 @@ var g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescr
794
961
  }
795
962
  checkFreeBufferTimeout(e) {
796
963
  let t = this.activeFreeBuffer;
797
- if (t.waitingSystems.size !== 0 && (t.waitElapsed += e, t.waitElapsed >= F)) {
964
+ if (t.waitingSystems.size !== 0 && (t.waitElapsed += e, t.waitElapsed >= z)) {
798
965
  let e = Array.from(t.waitingSystems).map((e) => e.name).join(", ");
799
- console.warn(`shared-memory-ecs: deferred component free waited over ${F}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();
800
967
  }
801
968
  }
802
969
  addSystem(e) {
@@ -850,12 +1017,12 @@ var g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescr
850
1017
  }
851
1018
  addEntityToEntityWorkerSystem(e, t) {
852
1019
  this.systems.forEach((n) => {
853
- (n instanceof O && n.options.components?.includes(t) || n instanceof M && this.componentAffectsEntityWorkerSystem(n, t)) && n.checkAddEntity(e);
1020
+ (n instanceof j && n.options.components?.includes(t) || n instanceof F && this.componentAffectsEntityWorkerSystem(n, t)) && n.checkAddEntity(e);
854
1021
  });
855
1022
  }
856
1023
  removeEntityFromEntityWorkerSystem(e, t) {
857
1024
  this.systems.forEach((n) => {
858
- n instanceof O && n.options.components?.includes(t) ? n.removeEntity(e) : n instanceof M && this.componentAffectsEntityWorkerSystem(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);
859
1026
  });
860
1027
  }
861
1028
  componentAffectsEntityWorkerSystem(e, t) {
@@ -869,20 +1036,28 @@ var g = Object.create, _ = Object.defineProperty, v = Object.getOwnPropertyDescr
869
1036
  }
870
1037
  };
871
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
872
1047
  //#region src/actions/kill-entity.ts
873
- function L(e) {
1048
+ function U(e) {
874
1049
  e.components.entity.dead = !0, e.emit("death");
875
1050
  }
876
1051
  //#endregion
877
1052
  //#region src/performance-timing.ts
878
- var R = 1e3, z = {
1053
+ var W = 1e3, G = {
879
1054
  avg: 0,
880
1055
  min: 0,
881
1056
  max: 0,
882
1057
  samples: 0
883
1058
  };
884
- function B(e) {
885
- if (!e.length) return { ...z };
1059
+ function K(e) {
1060
+ if (!e.length) return { ...G };
886
1061
  let t = 0, n = Infinity, r = 0;
887
1062
  for (let i of e) t += i, i < n && (n = i), i > r && (r = i);
888
1063
  return {
@@ -892,13 +1067,13 @@ function B(e) {
892
1067
  samples: e.length
893
1068
  };
894
1069
  }
895
- var V = class extends w.default {
1070
+ var q = class extends O.default {
896
1071
  world;
897
1072
  ticksBetweenUpdates;
898
1073
  stats = {
899
- update: { ...z },
1074
+ update: { ...G },
900
1075
  systems: [],
901
- events: { ...z }
1076
+ events: { ...G }
902
1077
  };
903
1078
  ticks = 0;
904
1079
  updateStart = 0;
@@ -915,9 +1090,9 @@ var V = class extends w.default {
915
1090
  this.ticks = 0, this.updateTimes = [], this.systemTimings.forEach((e) => {
916
1091
  e.run = [], e.events = [], e.eventStart = -1;
917
1092
  }), this.stats = {
918
- update: { ...z },
1093
+ update: { ...G },
919
1094
  systems: [],
920
- events: { ...z }
1095
+ events: { ...G }
921
1096
  };
922
1097
  }
923
1098
  destroy() {
@@ -959,26 +1134,26 @@ var V = class extends w.default {
959
1134
  let t = this.systemTimings.get(e.name);
960
1135
  return {
961
1136
  name: e.name,
962
- run: B(t?.run ?? []),
963
- events: B(t?.events ?? [])
1137
+ run: K(t?.run ?? []),
1138
+ events: K(t?.events ?? [])
964
1139
  };
965
- }), t = { ...z };
1140
+ }), t = { ...G };
966
1141
  e.forEach((e) => {
967
1142
  t.avg += e.events.avg, t.min += e.events.min, t.max += e.events.max, t.samples += e.events.samples;
968
1143
  }), this.stats = {
969
- update: B(this.updateTimes),
1144
+ update: K(this.updateTimes),
970
1145
  systems: e,
971
1146
  events: t
972
1147
  }, this.ticks = 0, this.updateTimes = [], this.systemTimings.forEach((e) => {
973
1148
  e.run = [], e.events = [];
974
1149
  }), this.emit("stats-updated", this.stats);
975
1150
  }
976
- }, H = class extends M {
1151
+ }, J = class extends F {
977
1152
  constructor(e, t) {
978
1153
  super(e, {
979
1154
  ...t,
980
1155
  required: [],
981
- updateFunction: s(t.updateFunction)
1156
+ updateFunction: u(t.updateFunction)
982
1157
  });
983
1158
  }
984
1159
  checkAddEntity(e) {
@@ -992,6 +1167,6 @@ var V = class extends w.default {
992
1167
  }
993
1168
  };
994
1169
  //#endregion
995
- export { T as BaseEntity, I as BaseWorld, p as Component, l as ConstantStringCache, c as DEAD_INDEX, R as DEFAULT_TICKS_BETWEEN_UPDATES, N as EntityFactory, O as EntitySystem, A as EntitySystemWebWorker, M as EntityWorkerSystem, D as IterableSystem, o as MemoryComponent, V as PerformanceTiming, d as STATIC_INDEX, E as System, t as TYPE_INDEX, k as WebWorker, H as WorkerSystem, u as createEntitySystemWorker, i as createEntityWorker, f as createSystemWorker, a as entityDefinition, L as killEntity, e 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 };
996
1171
 
997
1172
  //# sourceMappingURL=index.js.map