@codehz/ecs 0.3.3 → 0.3.4

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/index.js CHANGED
@@ -594,6 +594,86 @@ class CommandBuffer {
594
594
  }
595
595
  }
596
596
 
597
+ // src/multi-map.ts
598
+ class MultiMap {
599
+ map = new Map;
600
+ _valueCount = 0;
601
+ get valueCount() {
602
+ return this._valueCount;
603
+ }
604
+ get keyCount() {
605
+ return this.map.size;
606
+ }
607
+ hasKey(key) {
608
+ return this.map.has(key);
609
+ }
610
+ has(key, value) {
611
+ const set = this.map.get(key);
612
+ if (!set)
613
+ return false;
614
+ if (arguments.length === 1)
615
+ return true;
616
+ return set.has(value);
617
+ }
618
+ add(key, value) {
619
+ let set = this.map.get(key);
620
+ if (!set) {
621
+ set = new Set;
622
+ this.map.set(key, set);
623
+ }
624
+ if (!set.has(value)) {
625
+ set.add(value);
626
+ this._valueCount++;
627
+ }
628
+ }
629
+ remove(key, value) {
630
+ const set = this.map.get(key);
631
+ if (!set)
632
+ return false;
633
+ if (!set.has(value))
634
+ return false;
635
+ set.delete(value);
636
+ this._valueCount--;
637
+ if (set.size === 0)
638
+ this.map.delete(key);
639
+ return true;
640
+ }
641
+ deleteKey(key) {
642
+ const set = this.map.get(key);
643
+ if (!set)
644
+ return false;
645
+ this._valueCount -= set.size;
646
+ this.map.delete(key);
647
+ return true;
648
+ }
649
+ get(key) {
650
+ const set = this.map.get(key);
651
+ return set ? new Set(set) : new Set;
652
+ }
653
+ *keys() {
654
+ yield* this.map.keys();
655
+ }
656
+ *values() {
657
+ for (const set of this.map.values()) {
658
+ for (const v of set)
659
+ yield v;
660
+ }
661
+ }
662
+ [Symbol.iterator]() {
663
+ return this.entries();
664
+ }
665
+ *entries() {
666
+ for (const [k, set] of this.map.entries()) {
667
+ for (const v of set)
668
+ yield [k, v];
669
+ }
670
+ }
671
+ clear() {
672
+ this.map.clear();
673
+ this._valueCount = 0;
674
+ }
675
+ }
676
+
597
677
  // src/query-filter.ts
598
678
  function serializeQueryFilter(filter = {}) {
599
679
  const negative = (filter.negativeComponentTypes || []).slice().sort((a, b) => a - b);
@@ -878,7 +958,7 @@ class World {
878
958
  return;
879
959
  }
880
960
  const componentReferences = this.getEntityReferences(entityId);
881
- for (const { sourceEntityId, componentType } of componentReferences) {
961
+ for (const [sourceEntityId, componentType] of componentReferences) {
882
962
  const sourceArchetype = this.entityToArchetype.get(sourceEntityId);
883
963
  if (sourceArchetype) {
884
964
  const currentComponents = new Map;
@@ -1206,26 +1286,21 @@ class World {
1206
1286
  }
1207
1287
  trackEntityReference(sourceEntityId, componentType, targetEntityId) {
1208
1288
  if (!this.entityReferences.has(targetEntityId)) {
1209
- this.entityReferences.set(targetEntityId, new Set);
1289
+ this.entityReferences.set(targetEntityId, new MultiMap);
1210
1290
  }
1211
- this.entityReferences.get(targetEntityId).add({ sourceEntityId, componentType });
1291
+ this.entityReferences.get(targetEntityId).add(sourceEntityId, componentType);
1212
1292
  }
1213
1293
  untrackEntityReference(sourceEntityId, componentType, targetEntityId) {
1214
1294
  const references = this.entityReferences.get(targetEntityId);
1215
1295
  if (references) {
1216
- references.forEach((reference) => {
1217
- if (reference.sourceEntityId === sourceEntityId && reference.componentType === componentType) {
1218
- references.delete(reference);
1219
- }
1220
- });
1221
- if (references.size === 0) {
1296
+ references.get(sourceEntityId).delete(componentType);
1297
+ if (references.keyCount === 0) {
1222
1298
  this.entityReferences.delete(targetEntityId);
1223
1299
  }
1224
1300
  }
1225
1301
  }
1226
1302
  getEntityReferences(targetEntityId) {
1227
- const references = this.entityReferences.get(targetEntityId);
1228
- return references ? Array.from(references) : [];
1303
+ return this.entityReferences.get(targetEntityId) ?? [];
1229
1304
  }
1230
1305
  cleanupEmptyArchetype(archetype) {
1231
1306
  if (archetype.getEntities().length > 0) {
package/multi-map.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ declare class MultiMap<K, V> {
2
+ private map;
3
+ private _valueCount;
4
+ get valueCount(): number;
5
+ get keyCount(): number;
6
+ hasKey(key: K): boolean;
7
+ has(key: K, value?: V): boolean;
8
+ add(key: K, value: V): void;
9
+ remove(key: K, value: V): boolean;
10
+ deleteKey(key: K): boolean;
11
+ get(key: K): Set<V>;
12
+ keys(): IterableIterator<K>;
13
+ values(): IterableIterator<V>;
14
+ [Symbol.iterator](): IterableIterator<[K, V]>;
15
+ entries(): IterableIterator<[K, V]>;
16
+ clear(): void;
17
+ }
18
+ export { MultiMap };
19
+ export type { MultiMap as MultiMapType };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codehz/ecs",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",
package/world.d.ts CHANGED
@@ -176,7 +176,7 @@ export declare class World<UpdateParams extends any[] = []> {
176
176
  /**
177
177
  * Get all component references where a target entity is used as a component type
178
178
  * @param targetEntityId The target entity
179
- * @returns Array of {sourceEntityId, componentType} pairs
179
+ * @returns A MultiMap of sourceEntityId to componentTypes that reference the target entity
180
180
  */
181
181
  private getEntityReferences;
182
182
  /**