koota 0.2.2 → 0.3.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.cjs CHANGED
@@ -3,10 +3,6 @@ var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __typeError = (msg) => {
7
- throw TypeError(msg);
8
- };
9
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10
6
  var __export = (target, all) => {
11
7
  for (var name in all)
12
8
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -20,19 +16,6 @@ var __copyProps = (to, from, except, desc) => {
20
16
  return to;
21
17
  };
22
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
23
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
24
- var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
25
- var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
26
- var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
27
- var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
28
- var __privateWrapper = (obj, member, setter, getter) => ({
29
- set _(value) {
30
- __privateSet(obj, member, value, setter);
31
- },
32
- get _() {
33
- return __privateGet(obj, member, getter);
34
- }
35
- });
36
19
 
37
20
  // src/index.ts
38
21
  var index_exports = {};
@@ -75,6 +58,110 @@ var getEntityGeneration = (entity) => entity >>> GENERATION_SHIFT & GENERATION_M
75
58
  var incrementGeneration = (entity) => entity & ~(GENERATION_MASK << GENERATION_SHIFT) | // Clear current generation bits
76
59
  ((entity >>> GENERATION_SHIFT & GENERATION_MASK) + 1 & GENERATION_MASK) << GENERATION_SHIFT;
77
60
 
61
+ // ../core/src/world/utils/world-index.ts
62
+ function createWorldIndex() {
63
+ return {
64
+ worldCursor: 0,
65
+ releasedWorldIds: [],
66
+ maxWorlds: 2 ** WORLD_ID_BITS
67
+ };
68
+ }
69
+ function allocateWorldId(index) {
70
+ if (index.releasedWorldIds.length > 0) {
71
+ return index.releasedWorldIds.pop();
72
+ }
73
+ if (index.worldCursor >= index.maxWorlds) {
74
+ throw new Error(`Koota: Too many worlds created. The maximum is ${index.maxWorlds}.`);
75
+ }
76
+ return index.worldCursor++;
77
+ }
78
+ function releaseWorldId(index, worldId) {
79
+ if (worldId < 0 || worldId >= index.maxWorlds) {
80
+ throw new Error(`Invalid world ID: ${worldId}`);
81
+ }
82
+ if (worldId === index.worldCursor - 1) {
83
+ index.worldCursor--;
84
+ } else if (worldId < index.worldCursor && !index.releasedWorldIds.includes(worldId)) {
85
+ index.releasedWorldIds.push(worldId);
86
+ }
87
+ }
88
+
89
+ // ../core/src/universe/universe.ts
90
+ var universe = {
91
+ worlds: new Array(WORLD_ID_BITS ** 2),
92
+ cachedQueries: /* @__PURE__ */ new Map(),
93
+ worldIndex: createWorldIndex(),
94
+ reset: () => {
95
+ universe.worlds = new Array(WORLD_ID_BITS ** 2).fill(null);
96
+ universe.cachedQueries = /* @__PURE__ */ new Map();
97
+ universe.worldIndex = createWorldIndex();
98
+ }
99
+ };
100
+
101
+ // ../core/src/query/modifier.ts
102
+ var ModifierData = class {
103
+ constructor(type, id, traits) {
104
+ this.type = type;
105
+ this.id = id;
106
+ this.traits = traits;
107
+ this.traitIds = traits.map((trait2) => trait2[$internal].id);
108
+ }
109
+ traitIds;
110
+ };
111
+
112
+ // ../core/src/query/utils/tracking-cursor.ts
113
+ var cursor = 3;
114
+ function createTrackingId() {
115
+ return cursor++;
116
+ }
117
+ function getTrackingCursor() {
118
+ return cursor;
119
+ }
120
+ function setTrackingMasks(world, id) {
121
+ const ctx = world[$internal];
122
+ const snapshot = structuredClone(ctx.entityMasks);
123
+ ctx.trackingSnapshots.set(id, snapshot);
124
+ ctx.dirtyMasks.set(
125
+ id,
126
+ snapshot.map((mask) => mask.map(() => 0))
127
+ );
128
+ ctx.changedMasks.set(
129
+ id,
130
+ snapshot.map((mask) => mask.map(() => 0))
131
+ );
132
+ }
133
+
134
+ // ../core/src/query/modifiers/changed.ts
135
+ function createChanged() {
136
+ const id = createTrackingId();
137
+ for (const world of universe.worlds) {
138
+ if (!world) continue;
139
+ setTrackingMasks(world.deref(), id);
140
+ }
141
+ return (...traits) => new ModifierData(`changed-${id}`, id, traits);
142
+ }
143
+ function setChanged(world, entity, trait2) {
144
+ const ctx = world[$internal];
145
+ if (!hasTrait(world, entity, trait2)) return;
146
+ if (!ctx.traitData.has(trait2)) registerTrait(world, trait2);
147
+ const data = ctx.traitData.get(trait2);
148
+ for (const changedMask of ctx.changedMasks.values()) {
149
+ const eid = getEntityId(entity);
150
+ if (!changedMask[eid]) changedMask[eid] = new Array();
151
+ const traitId2 = trait2[$internal].id;
152
+ changedMask[eid][traitId2] = 1;
153
+ }
154
+ for (const query of data.queries) {
155
+ if (!query.hasChangedModifiers) continue;
156
+ let match = query.check(world, entity, { type: "change", traitData: data });
157
+ if (match) query.add(entity);
158
+ else query.remove(world, entity);
159
+ }
160
+ for (const sub of data.changedSubscriptions) {
161
+ sub(entity);
162
+ }
163
+ }
164
+
78
165
  // ../core/src/relation/relation.ts
79
166
  function defineRelation(definition) {
80
167
  const pairsMap = /* @__PURE__ */ new Map();
@@ -112,8 +199,9 @@ function getRelationTrait(relation2, traitFactory, pairsMap, target) {
112
199
  }
113
200
  var getRelationTargets = (world, relation2, entity) => {
114
201
  const ctx = world[$internal];
115
- const traits = ctx.entityTraits.get(entity) || [];
202
+ const traits = ctx.entityTraits.get(entity);
116
203
  const targets = [];
204
+ if (!traits) return targets;
117
205
  for (const trait2 of traits) {
118
206
  const traitCtx = trait2[$internal];
119
207
  if (traitCtx.relation === relation2 && traitCtx.pairTarget !== Wildcard) {
@@ -145,15 +233,15 @@ var incrementWorldBitflag = (world) => {
145
233
 
146
234
  // ../core/src/trait/trait-data.ts
147
235
  var TraitData = class {
236
+ generationId;
237
+ bitflag;
238
+ trait;
239
+ store;
240
+ queries;
241
+ notQueries;
242
+ schema;
243
+ changedSubscriptions;
148
244
  constructor(world, trait2) {
149
- __publicField(this, "generationId");
150
- __publicField(this, "bitflag");
151
- __publicField(this, "trait");
152
- __publicField(this, "store");
153
- __publicField(this, "queries");
154
- __publicField(this, "notQueries");
155
- __publicField(this, "schema");
156
- __publicField(this, "changedSubscriptions");
157
245
  const ctx = world[$internal];
158
246
  const traitCtx = trait2[$internal];
159
247
  this.generationId = ctx.entityMasks.length - 1;
@@ -322,7 +410,7 @@ function addTrait(world, entity, ...traits) {
322
410
  } else {
323
411
  trait2 = traits[i];
324
412
  }
325
- if (entity.has(trait2)) return;
413
+ if (hasTrait(world, entity, trait2)) return;
326
414
  const traitCtx = trait2[$internal];
327
415
  if (!ctx.traitData.has(trait2)) registerTrait(world, trait2);
328
416
  const data = ctx.traitData.get(trait2);
@@ -344,8 +432,8 @@ function addTrait(world, entity, ...traits) {
344
432
  const target = traitCtx.pairTarget;
345
433
  if (traitCtx.isPairTrait && relation2 !== null && target !== null) {
346
434
  ctx.relationTargetEntities.add(target);
347
- entity.add(Pair(Wildcard, target));
348
- entity.add(Pair(relation2, Wildcard));
435
+ addTrait(world, entity, Pair(Wildcard, target));
436
+ addTrait(world, entity, Pair(relation2, Wildcard));
349
437
  if (relation2[$internal].exclusive === true && target !== Wildcard) {
350
438
  const oldTarget = getRelationTargets(world, relation2, entity)[0];
351
439
  if (oldTarget !== null && oldTarget !== void 0 && oldTarget !== target) {
@@ -362,10 +450,10 @@ function addTrait(world, entity, ...traits) {
362
450
  defaults[key] = data.schema[key];
363
451
  }
364
452
  }
365
- entity.set(trait2, { ...defaults, ...params }, false);
453
+ setTrait(world, entity, trait2, { ...defaults, ...params }, false);
366
454
  } else {
367
455
  const state = params ?? data.schema();
368
- entity.set(trait2, state, false);
456
+ setTrait(world, entity, trait2, state, false);
369
457
  }
370
458
  }
371
459
  }
@@ -374,7 +462,7 @@ function removeTrait(world, entity, ...traits) {
374
462
  for (let i = 0; i < traits.length; i++) {
375
463
  const trait2 = traits[i];
376
464
  const traitCtx = trait2[$internal];
377
- if (!entity.has(trait2)) return;
465
+ if (!hasTrait(world, entity, trait2)) return;
378
466
  const data = ctx.traitData.get(trait2);
379
467
  const { generationId, bitflag, queries } = data;
380
468
  const eid = getEntityId(entity);
@@ -417,6 +505,25 @@ function getStore(world, trait2) {
417
505
  const store = data.store;
418
506
  return store;
419
507
  }
508
+ function setTrait(world, entity, trait2, value, triggerChanged = true) {
509
+ const ctx = trait2[$internal];
510
+ const index = entity & ENTITY_ID_MASK;
511
+ const store = getStore(world, trait2);
512
+ value instanceof Function && (value = value(ctx.get(index, store)));
513
+ ctx.set(index, store, value);
514
+ triggerChanged && setChanged(world, entity, trait2);
515
+ }
516
+ function getTrait(world, entity, trait2) {
517
+ const worldCtx = world[$internal];
518
+ const data = worldCtx.traitData.get(trait2);
519
+ if (!data) return void 0;
520
+ const index = getEntityId(entity);
521
+ const mask = worldCtx.entityMasks[data.generationId][index];
522
+ if ((mask & data.bitflag) !== data.bitflag) return void 0;
523
+ const traitCtx = trait2[$internal];
524
+ const store = getStore(world, trait2);
525
+ return traitCtx.get(index, store);
526
+ }
420
527
 
421
528
  // ../core/src/entity/utils/entity-index.ts
422
529
  var createEntityIndex = (worldId) => ({
@@ -464,172 +571,61 @@ var getAliveEntities = (index) => {
464
571
  return index.dense.slice(0, index.aliveCount);
465
572
  };
466
573
 
467
- // ../core/src/world/utils/world-index.ts
468
- function createWorldIndex() {
469
- return {
470
- worldCursor: 0,
471
- releasedWorldIds: [],
472
- maxWorlds: 2 ** WORLD_ID_BITS
473
- };
474
- }
475
- function allocateWorldId(index) {
476
- if (index.releasedWorldIds.length > 0) {
477
- return index.releasedWorldIds.pop();
478
- }
479
- if (index.worldCursor >= index.maxWorlds) {
480
- throw new Error(`Koota: Too many worlds created. The maximum is ${index.maxWorlds}.`);
481
- }
482
- return index.worldCursor++;
483
- }
484
- function releaseWorldId(index, worldId) {
485
- if (worldId < 0 || worldId >= index.maxWorlds) {
486
- throw new Error(`Invalid world ID: ${worldId}`);
487
- }
488
- if (worldId === index.worldCursor - 1) {
489
- index.worldCursor--;
490
- } else if (worldId < index.worldCursor && !index.releasedWorldIds.includes(worldId)) {
491
- index.releasedWorldIds.push(worldId);
492
- }
493
- }
494
-
495
- // ../core/src/universe/universe.ts
496
- var universe = {
497
- worlds: new Array(WORLD_ID_BITS ** 2),
498
- cachedQueries: /* @__PURE__ */ new Map(),
499
- worldIndex: createWorldIndex(),
500
- reset: () => {
501
- universe.worlds = new Array(WORLD_ID_BITS ** 2);
502
- universe.cachedQueries = /* @__PURE__ */ new Map();
503
- universe.worldIndex = createWorldIndex();
504
- }
505
- };
506
-
507
- // ../core/src/query/modifier.ts
508
- var ModifierData = class {
509
- constructor(type, id, traits) {
510
- this.type = type;
511
- this.id = id;
512
- this.traits = traits;
513
- __publicField(this, "traitIds");
514
- this.traitIds = traits.map((trait2) => trait2[$internal].id);
515
- }
516
- };
517
-
518
- // ../core/src/query/utils/tracking-cursor.ts
519
- var cursor = 3;
520
- function createTrackingId() {
521
- return cursor++;
522
- }
523
- function getTrackingCursor() {
524
- return cursor;
525
- }
526
- function setTrackingMasks(world, id) {
527
- const ctx = world[$internal];
528
- const snapshot = structuredClone(ctx.entityMasks);
529
- ctx.trackingSnapshots.set(id, snapshot);
530
- ctx.dirtyMasks.set(
531
- id,
532
- snapshot.map((mask) => mask.map(() => 0))
533
- );
534
- ctx.changedMasks.set(
535
- id,
536
- snapshot.map((mask) => mask.map(() => 0))
537
- );
538
- }
539
-
540
- // ../core/src/query/modifiers/changed.ts
541
- function createChanged() {
542
- const id = createTrackingId();
543
- for (const world of universe.worlds) {
544
- if (!world) continue;
545
- setTrackingMasks(world, id);
546
- }
547
- return (...traits) => new ModifierData(`changed-${id}`, id, traits);
548
- }
549
- function setChanged(world, entity, trait2) {
550
- const ctx = world[$internal];
551
- if (!entity.has(trait2)) return;
552
- if (!ctx.traitData.has(trait2)) registerTrait(world, trait2);
553
- const data = ctx.traitData.get(trait2);
554
- for (const changedMask of ctx.changedMasks.values()) {
555
- const eid = getEntityId(entity);
556
- if (!changedMask[eid]) changedMask[eid] = new Array();
557
- const traitId2 = trait2[$internal].id;
558
- changedMask[eid][traitId2] = 1;
559
- }
560
- for (const query of data.queries) {
561
- if (!query.hasChangedModifiers) continue;
562
- let match = query.check(world, entity, { type: "change", traitData: data });
563
- if (match) query.add(entity);
564
- else query.remove(world, entity);
565
- }
566
- for (const sub of data.changedSubscriptions) {
567
- sub(entity);
568
- }
569
- }
570
-
571
574
  // ../core/src/entity/entity-methods-patch.ts
572
575
  Number.prototype.add = function(...traits) {
573
576
  const worldId = this >>> WORLD_ID_SHIFT;
574
- const world = universe.worlds[worldId];
577
+ const world = universe.worlds[worldId].deref();
575
578
  return addTrait(world, this, ...traits);
576
579
  };
577
580
  Number.prototype.remove = function(...traits) {
578
581
  const worldId = this >>> WORLD_ID_SHIFT;
579
- const world = universe.worlds[worldId];
582
+ const world = universe.worlds[worldId].deref();
580
583
  return removeTrait(world, this, ...traits);
581
584
  };
582
585
  Number.prototype.has = function(trait2) {
583
586
  const worldId = this >>> WORLD_ID_SHIFT;
584
- const world = universe.worlds[worldId];
587
+ const world = universe.worlds[worldId].deref();
585
588
  return hasTrait(world, this, trait2);
586
589
  };
587
590
  Number.prototype.destroy = function() {
588
591
  const worldId = this >>> WORLD_ID_SHIFT;
589
- const world = universe.worlds[worldId];
592
+ const world = universe.worlds[worldId].deref();
590
593
  return destroyEntity(world, this);
591
594
  };
592
595
  Number.prototype.changed = function(trait2) {
593
596
  const worldId = this >>> WORLD_ID_SHIFT;
594
- const world = universe.worlds[worldId];
597
+ const world = universe.worlds[worldId].deref();
595
598
  return setChanged(world, this, trait2);
596
599
  };
597
600
  Number.prototype.get = function(trait2) {
598
601
  const worldId = this >>> WORLD_ID_SHIFT;
599
- const world = universe.worlds[worldId];
600
- const worldCtx = world[$internal];
601
- const data = worldCtx.traitData.get(trait2);
602
- if (!data) return void 0;
603
- const index = this & ENTITY_ID_MASK;
604
- const mask = worldCtx.entityMasks[data.generationId][index];
605
- if ((mask & data.bitflag) !== data.bitflag) return void 0;
606
- const traitCtx = trait2[$internal];
607
- const store = traitCtx.stores[worldId];
608
- return traitCtx.get(index, store);
602
+ const world = universe.worlds[worldId].deref();
603
+ return getTrait(world, this, trait2);
609
604
  };
610
605
  Number.prototype.set = function(trait2, value, triggerChanged = true) {
611
- const ctx = trait2[$internal];
612
- const index = this & ENTITY_ID_MASK;
613
606
  const worldId = this >>> WORLD_ID_SHIFT;
614
- const store = ctx.stores[worldId];
615
- value instanceof Function && (value = value(ctx.get(index, store)));
616
- ctx.set(index, store, value);
617
- triggerChanged && setChanged(universe.worlds[worldId], this, trait2);
607
+ const world = universe.worlds[worldId].deref();
608
+ setTrait(world, this, trait2, value, triggerChanged);
618
609
  };
619
610
  Number.prototype.targetsFor = function(relation2) {
620
611
  const worldId = this >>> WORLD_ID_SHIFT;
621
- const world = universe.worlds[worldId];
612
+ const world = universe.worlds[worldId].deref();
622
613
  return getRelationTargets(world, relation2, this);
623
614
  };
624
615
  Number.prototype.targetFor = function(relation2) {
625
616
  const worldId = this >>> WORLD_ID_SHIFT;
626
- const world = universe.worlds[worldId];
617
+ const world = universe.worlds[worldId].deref();
627
618
  return getRelationTargets(world, relation2, this)[0];
628
619
  };
629
620
  Number.prototype.id = function() {
630
621
  const id = this & ENTITY_ID_MASK;
631
622
  return id;
632
623
  };
624
+ Number.prototype.isAlive = function() {
625
+ const worldId = this >>> WORLD_ID_SHIFT;
626
+ const world = universe.worlds[worldId].deref();
627
+ return isEntityAlive(world[$internal].entityIndex, this);
628
+ };
633
629
 
634
630
  // ../core/src/entity/entity.ts
635
631
  function createEntity(world, ...traits) {
@@ -638,10 +634,10 @@ function createEntity(world, ...traits) {
638
634
  for (const query of ctx.notQueries) {
639
635
  const match = query.check(world, entity);
640
636
  if (match) query.add(entity);
641
- query.resetTrackingBitmasks(entity.id());
637
+ query.resetTrackingBitmasks(getEntityId(entity));
642
638
  }
643
639
  ctx.entityTraits.set(entity, /* @__PURE__ */ new Set());
644
- entity.add(...traits);
640
+ addTrait(world, entity, ...traits);
645
641
  return entity;
646
642
  }
647
643
  var cachedSet = /* @__PURE__ */ new Set();
@@ -682,6 +678,8 @@ function destroyEntity(world, entity) {
682
678
  }
683
679
  }
684
680
  releaseEntity(ctx.entityIndex, currentEntity);
681
+ const allQuery = ctx.queriesHashMap.get("");
682
+ if (allQuery) allQuery.remove(world, currentEntity);
685
683
  ctx.entityTraits.delete(entity);
686
684
  const eid = getEntityId(currentEntity);
687
685
  for (let i = 0; i < ctx.entityMasks.length; i++) {
@@ -691,57 +689,51 @@ function destroyEntity(world, entity) {
691
689
  }
692
690
 
693
691
  // ../core/src/utils/sparse-set.ts
694
- var _dense, _sparse, _cursor;
695
692
  var SparseSet = class {
696
- constructor() {
697
- __privateAdd(this, _dense, []);
698
- __privateAdd(this, _sparse, []);
699
- __privateAdd(this, _cursor, 0);
700
- }
693
+ #dense = [];
694
+ #sparse = [];
695
+ #cursor = 0;
701
696
  has(val) {
702
- const index = __privateGet(this, _sparse)[val];
703
- return index < __privateGet(this, _cursor) && __privateGet(this, _dense)[index] === val;
697
+ const index = this.#sparse[val];
698
+ return index < this.#cursor && this.#dense[index] === val;
704
699
  }
705
700
  add(val) {
706
701
  if (this.has(val)) return;
707
- __privateGet(this, _sparse)[val] = __privateGet(this, _cursor);
708
- __privateGet(this, _dense)[__privateWrapper(this, _cursor)._++] = val;
702
+ this.#sparse[val] = this.#cursor;
703
+ this.#dense[this.#cursor++] = val;
709
704
  }
710
705
  remove(val) {
711
706
  if (!this.has(val)) return;
712
- const index = __privateGet(this, _sparse)[val];
713
- __privateWrapper(this, _cursor)._--;
714
- const swapped = __privateGet(this, _dense)[__privateGet(this, _cursor)];
707
+ const index = this.#sparse[val];
708
+ this.#cursor--;
709
+ const swapped = this.#dense[this.#cursor];
715
710
  if (swapped !== val) {
716
- __privateGet(this, _dense)[index] = swapped;
717
- __privateGet(this, _sparse)[swapped] = index;
711
+ this.#dense[index] = swapped;
712
+ this.#sparse[swapped] = index;
718
713
  }
719
714
  }
720
715
  clear() {
721
- for (let i = 0; i < __privateGet(this, _cursor); i++) {
722
- __privateGet(this, _sparse)[__privateGet(this, _dense)[i]] = 0;
716
+ for (let i = 0; i < this.#cursor; i++) {
717
+ this.#sparse[this.#dense[i]] = 0;
723
718
  }
724
- __privateSet(this, _cursor, 0);
719
+ this.#cursor = 0;
725
720
  }
726
721
  sort() {
727
- __privateGet(this, _dense).sort((a, b) => a - b);
728
- for (let i = 0; i < __privateGet(this, _dense).length; i++) {
729
- __privateGet(this, _sparse)[__privateGet(this, _dense)[i]] = i;
722
+ this.#dense.sort((a, b) => a - b);
723
+ for (let i = 0; i < this.#dense.length; i++) {
724
+ this.#sparse[this.#dense[i]] = i;
730
725
  }
731
726
  }
732
727
  getIndex(val) {
733
- return __privateGet(this, _sparse)[val];
728
+ return this.#sparse[val];
734
729
  }
735
730
  get dense() {
736
- return __privateGet(this, _dense).slice(0, __privateGet(this, _cursor));
731
+ return this.#dense.slice(0, this.#cursor);
737
732
  }
738
733
  get sparse() {
739
- return __privateGet(this, _sparse);
734
+ return this.#sparse;
740
735
  }
741
736
  };
742
- _dense = new WeakMap();
743
- _sparse = new WeakMap();
744
- _cursor = new WeakMap();
745
737
 
746
738
  // ../core/src/query/utils/create-query-hash.ts
747
739
  var sortedIDs = new Float32Array(1024);
@@ -771,22 +763,22 @@ var createQueryHash = (parameters) => {
771
763
  // ../core/src/query/query.ts
772
764
  var IsExcluded = trait();
773
765
  var Query = class {
766
+ version = 0;
767
+ world;
768
+ parameters;
769
+ hash;
770
+ traits = [];
771
+ traitData = { required: [], forbidden: [], or: [], added: [], removed: [], changed: [], all: [] };
772
+ bitmasks = [];
773
+ generations;
774
+ entities = new SparseSet();
775
+ isTracking = false;
776
+ hasChangedModifiers = false;
777
+ changedTraits = /* @__PURE__ */ new Set();
778
+ toRemove = new SparseSet();
779
+ addSubscriptions = /* @__PURE__ */ new Set();
780
+ removeSubscriptions = /* @__PURE__ */ new Set();
774
781
  constructor(world, parameters = []) {
775
- __publicField(this, "version", 0);
776
- __publicField(this, "world");
777
- __publicField(this, "parameters");
778
- __publicField(this, "hash");
779
- __publicField(this, "traits", []);
780
- __publicField(this, "traitData", { required: [], forbidden: [], or: [], added: [], removed: [], changed: [], all: [] });
781
- __publicField(this, "bitmasks", []);
782
- __publicField(this, "generations");
783
- __publicField(this, "entities", new SparseSet());
784
- __publicField(this, "isTracking", false);
785
- __publicField(this, "hasChangedModifiers", false);
786
- __publicField(this, "changedTraits", /* @__PURE__ */ new Set());
787
- __publicField(this, "toRemove", new SparseSet());
788
- __publicField(this, "addSubscriptions", /* @__PURE__ */ new Set());
789
- __publicField(this, "removeSubscriptions", /* @__PURE__ */ new Set());
790
782
  this.world = world;
791
783
  this.parameters = parameters;
792
784
  const ctx = world[$internal];
@@ -968,6 +960,7 @@ var Query = class {
968
960
  for (const sub of this.removeSubscriptions) {
969
961
  sub(entity);
970
962
  }
963
+ this.version++;
971
964
  }
972
965
  check(world, entity, event) {
973
966
  const { bitmasks, generations } = this;
@@ -1129,7 +1122,7 @@ function createQueryResult(query, world, params) {
1129
1122
  }
1130
1123
  for (let i = 0; i < changedPairs.length; i++) {
1131
1124
  const [entity, trait2] = changedPairs[i];
1132
- entity.changed(trait2);
1125
+ setChanged(world, entity, trait2);
1133
1126
  }
1134
1127
  } else if (options.changeDetection === "always") {
1135
1128
  const changedPairs = [];
@@ -1164,7 +1157,7 @@ function createQueryResult(query, world, params) {
1164
1157
  }
1165
1158
  for (let i = 0; i < changedPairs.length; i++) {
1166
1159
  const [entity, trait2] = changedPairs[i];
1167
- entity.changed(trait2);
1160
+ setChanged(world, entity, trait2);
1168
1161
  }
1169
1162
  } else if (options.changeDetection === "never") {
1170
1163
  for (let i = 0; i < entities.length; i++) {
@@ -1195,6 +1188,10 @@ function createQueryResult(query, world, params) {
1195
1188
  stores.length = 0;
1196
1189
  getQueryStores(params2, traits, stores, world);
1197
1190
  return results;
1191
+ },
1192
+ sort(callback = (a, b) => getEntityId(a) - getEntityId(b)) {
1193
+ Array.prototype.sort.call(entities, callback);
1194
+ return results;
1198
1195
  }
1199
1196
  });
1200
1197
  return results;
@@ -1219,46 +1216,44 @@ function getQueryStores(params, traits, stores, world) {
1219
1216
  }
1220
1217
 
1221
1218
  // ../core/src/world/world.ts
1222
- var _a, _id, _isInitialized;
1223
- _a = $internal;
1224
1219
  var World = class {
1225
- constructor(...traits) {
1226
- __privateAdd(this, _id, allocateWorldId(universe.worldIndex));
1227
- __publicField(this, _a, {
1228
- entityIndex: createEntityIndex(__privateGet(this, _id)),
1229
- entityMasks: [[]],
1230
- entityTraits: /* @__PURE__ */ new Map(),
1231
- bitflag: 1,
1232
- traitData: /* @__PURE__ */ new Map(),
1233
- queries: /* @__PURE__ */ new Set(),
1234
- queriesHashMap: /* @__PURE__ */ new Map(),
1235
- notQueries: /* @__PURE__ */ new Set(),
1236
- dirtyQueries: /* @__PURE__ */ new Set(),
1237
- relationTargetEntities: /* @__PURE__ */ new Set(),
1238
- dirtyMasks: /* @__PURE__ */ new Map(),
1239
- trackingSnapshots: /* @__PURE__ */ new Map(),
1240
- changedMasks: /* @__PURE__ */ new Map(),
1241
- worldEntity: null,
1242
- trackedTraits: /* @__PURE__ */ new Set()
1243
- });
1244
- __privateAdd(this, _isInitialized, false);
1245
- __publicField(this, "traits", /* @__PURE__ */ new Set());
1246
- this.init(...traits);
1247
- }
1220
+ #id = allocateWorldId(universe.worldIndex);
1221
+ [$internal] = {
1222
+ entityIndex: createEntityIndex(this.#id),
1223
+ entityMasks: [[]],
1224
+ entityTraits: /* @__PURE__ */ new Map(),
1225
+ bitflag: 1,
1226
+ traitData: /* @__PURE__ */ new Map(),
1227
+ queries: /* @__PURE__ */ new Set(),
1228
+ queriesHashMap: /* @__PURE__ */ new Map(),
1229
+ notQueries: /* @__PURE__ */ new Set(),
1230
+ dirtyQueries: /* @__PURE__ */ new Set(),
1231
+ relationTargetEntities: /* @__PURE__ */ new Set(),
1232
+ dirtyMasks: /* @__PURE__ */ new Map(),
1233
+ trackingSnapshots: /* @__PURE__ */ new Map(),
1234
+ changedMasks: /* @__PURE__ */ new Map(),
1235
+ worldEntity: null,
1236
+ trackedTraits: /* @__PURE__ */ new Set()
1237
+ };
1248
1238
  get id() {
1249
- return __privateGet(this, _id);
1239
+ return this.#id;
1250
1240
  }
1241
+ #isInitialized = false;
1251
1242
  get isInitialized() {
1252
- return __privateGet(this, _isInitialized);
1243
+ return this.#isInitialized;
1253
1244
  }
1254
1245
  get entities() {
1255
1246
  return getAliveEntities(this[$internal].entityIndex);
1256
1247
  }
1248
+ traits = /* @__PURE__ */ new Set();
1249
+ constructor(...traits) {
1250
+ this.init(...traits);
1251
+ }
1257
1252
  init(...traits) {
1258
1253
  const ctx = this[$internal];
1259
- if (__privateGet(this, _isInitialized)) return;
1260
- __privateSet(this, _isInitialized, true);
1261
- universe.worlds[__privateGet(this, _id)] = this;
1254
+ if (this.#isInitialized) return;
1255
+ this.#isInitialized = true;
1256
+ universe.worlds[this.#id] = new WeakRef(this);
1262
1257
  const cursor2 = getTrackingCursor();
1263
1258
  for (let i = 0; i < cursor2; i++) {
1264
1259
  setTrackingMasks(this, i);
@@ -1273,41 +1268,47 @@ var World = class {
1273
1268
  return createEntity(this, ...traits);
1274
1269
  }
1275
1270
  has(target) {
1276
- return typeof target === "number" ? isEntityAlive(this[$internal].entityIndex, target) : this[$internal].worldEntity.has(target);
1271
+ return typeof target === "number" ? isEntityAlive(this[$internal].entityIndex, target) : hasTrait(this, this[$internal].worldEntity, target);
1277
1272
  }
1278
1273
  add(...traits) {
1279
- this[$internal].worldEntity.add(...traits);
1274
+ addTrait(this, this[$internal].worldEntity, ...traits);
1280
1275
  }
1281
1276
  remove(...traits) {
1282
- this[$internal].worldEntity.remove(...traits);
1277
+ removeTrait(this, this[$internal].worldEntity, ...traits);
1283
1278
  }
1284
1279
  get(trait2) {
1285
- return this[$internal].worldEntity.get(trait2);
1280
+ return getTrait(this, this[$internal].worldEntity, trait2);
1286
1281
  }
1287
1282
  set(trait2, value) {
1288
- this[$internal].worldEntity.set(trait2, value);
1283
+ setTrait(this, this[$internal].worldEntity, trait2, value);
1289
1284
  }
1290
1285
  destroy() {
1291
1286
  destroyEntity(this, this[$internal].worldEntity);
1292
1287
  this[$internal].worldEntity = null;
1293
1288
  this.entities.forEach((entity) => destroyEntity(this, entity));
1294
1289
  this.reset();
1295
- __privateSet(this, _isInitialized, false);
1296
- releaseWorldId(universe.worldIndex, __privateGet(this, _id));
1297
- universe.worlds.splice(universe.worlds.indexOf(this), 1);
1290
+ this.#isInitialized = false;
1291
+ releaseWorldId(universe.worldIndex, this.#id);
1292
+ universe.worlds[this.#id] = null;
1298
1293
  }
1299
- reset() {
1294
+ reset(options = {}) {
1300
1295
  const ctx = this[$internal];
1301
- ctx.entityIndex = createEntityIndex(__privateGet(this, _id));
1296
+ const shouldPreserveTraits = options.preserveTraits || options.preserveSubscriptions;
1297
+ const shouldPreserveQueries = options.preserveQueries || options.preserveSubscriptions;
1298
+ ctx.entityIndex = createEntityIndex(this.#id);
1302
1299
  ctx.entityTraits.clear();
1303
- ctx.notQueries.clear();
1304
1300
  ctx.entityMasks = [[]];
1305
1301
  ctx.bitflag = 1;
1306
- ctx.traitData.clear();
1307
- this.traits.clear();
1308
- ctx.queries.clear();
1309
- ctx.queriesHashMap.clear();
1310
- ctx.dirtyQueries.clear();
1302
+ if (!shouldPreserveTraits) {
1303
+ ctx.traitData.clear();
1304
+ this.traits.clear();
1305
+ }
1306
+ if (!shouldPreserveQueries) {
1307
+ ctx.queries.clear();
1308
+ ctx.queriesHashMap.clear();
1309
+ ctx.dirtyQueries.clear();
1310
+ ctx.notQueries.clear();
1311
+ }
1311
1312
  ctx.relationTargetEntities.clear();
1312
1313
  ctx.trackingSnapshots.clear();
1313
1314
  ctx.dirtyMasks.clear();
@@ -1369,10 +1370,14 @@ var World = class {
1369
1370
  };
1370
1371
  }
1371
1372
  };
1372
- _id = new WeakMap();
1373
- _isInitialized = new WeakMap();
1373
+ var worldFinalizer = new FinalizationRegistry((worldId) => {
1374
+ universe.worlds[worldId] = null;
1375
+ releaseWorldId(universe.worldIndex, worldId);
1376
+ });
1374
1377
  function createWorld(...traits) {
1375
- return new World(...traits);
1378
+ const world = new World(...traits);
1379
+ worldFinalizer.register(world, world.id);
1380
+ return world;
1376
1381
  }
1377
1382
 
1378
1383
  // ../core/src/query/modifiers/added.ts
@@ -1380,7 +1385,7 @@ function createAdded() {
1380
1385
  const id = createTrackingId();
1381
1386
  for (const world of universe.worlds) {
1382
1387
  if (!world) continue;
1383
- setTrackingMasks(world, id);
1388
+ setTrackingMasks(world.deref(), id);
1384
1389
  }
1385
1390
  return (...traits) => new ModifierData(`added-${id}`, id, traits);
1386
1391
  }
@@ -1390,7 +1395,7 @@ function createRemoved() {
1390
1395
  const id = createTrackingId();
1391
1396
  for (const world of universe.worlds) {
1392
1397
  if (!world) continue;
1393
- setTrackingMasks(world, id);
1398
+ setTrackingMasks(world.deref(), id);
1394
1399
  }
1395
1400
  return (...traits) => new ModifierData(`removed-${id}`, id, traits);
1396
1401
  }
@@ -1404,8 +1409,9 @@ var Or = (...traits) => new ModifierData("or", 2, traits);
1404
1409
  // ../core/src/query/utils/cache-query.ts
1405
1410
  function cacheQuery(...parameters) {
1406
1411
  const hash = createQueryHash(parameters);
1407
- for (const world of universe.worlds) {
1408
- if (!world) continue;
1412
+ for (const worldRef of universe.worlds) {
1413
+ if (!worldRef) continue;
1414
+ const world = worldRef.deref();
1409
1415
  const ctx = world[$internal];
1410
1416
  if (!ctx.queriesHashMap.has(hash)) {
1411
1417
  const query = new Query(world, parameters);
@@ -1433,6 +1439,9 @@ function createActions(actionSet) {
1433
1439
  return actions;
1434
1440
  };
1435
1441
  }
1442
+
1443
+ // ../core/src/query/types.ts
1444
+ var $parameters = Symbol();
1436
1445
  // Annotate the CommonJS export names for ESM import in node:
1437
1446
  0 && (module.exports = {
1438
1447
  $internal,