@codehz/ecs 0.3.5 → 0.3.7

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/archetype.d.ts CHANGED
@@ -117,6 +117,14 @@ export declare class Archetype {
117
117
  * @returns An array of component data or undefined if not present
118
118
  */
119
119
  getOptionalComponentData<T>(componentType: EntityId<T>): T[] | undefined;
120
+ /**
121
+ * Helper: compute or return cached data sources for provided componentTypes
122
+ */
123
+ private getCachedComponentDataSources;
124
+ /**
125
+ * Helper: build component tuples for a specific entity index using precomputed data sources
126
+ */
127
+ private buildComponentsForIndex;
120
128
  /**
121
129
  * Get entities with their component data for specified component types
122
130
  * Optimized for bulk component access with pre-computed indices
@@ -127,6 +135,12 @@ export declare class Archetype {
127
135
  entity: EntityId;
128
136
  components: ComponentTuple<T>;
129
137
  }>;
138
+ /**
139
+ * Iterate over entities with their component data for specified component types
140
+ * implemented as a generator returning each entity/components pair lazily
141
+ * @param componentTypes Array of component types to retrieve
142
+ */
143
+ iterateWithComponents<const T extends readonly ComponentType<any>[]>(componentTypes: T): IterableIterator<[EntityId, ...ComponentTuple<T>]>;
130
144
  /**
131
145
  * Iterate over entities with their component data for specified component types
132
146
  * Optimized for bulk component access
package/index.js CHANGED
@@ -402,16 +402,9 @@ class Archetype {
402
402
  getOptionalComponentData(componentType) {
403
403
  return this.componentData.get(componentType);
404
404
  }
405
- getEntitiesWithComponents(componentTypes) {
406
- const result = [];
407
- this.forEachWithComponents(componentTypes, (entity, ...components) => {
408
- result.push({ entity, components });
409
- });
410
- return result;
411
- }
412
- forEachWithComponents(componentTypes, callback) {
405
+ getCachedComponentDataSources(componentTypes) {
413
406
  const cacheKey = componentTypes.map((id) => isOptionalEntityId(id) ? `opt(${id.optional})` : `${id}`).join(",");
414
- const componentDataSources = getOrComputeCache(this.componentDataSourcesCache, cacheKey, () => {
407
+ return getOrComputeCache(this.componentDataSourcesCache, cacheKey, () => {
415
408
  return componentTypes.map((compType) => {
416
409
  let optional = false;
417
410
  if (isOptionalEntityId(compType)) {
@@ -433,46 +426,67 @@ class Archetype {
433
426
  }
434
427
  });
435
428
  });
436
- for (let entityIndex = 0;entityIndex < this.entities.length; entityIndex++) {
437
- const entity = this.entities[entityIndex];
438
- const components = componentDataSources.map((dataSource, i) => {
439
- let compType = componentTypes[i];
440
- let optional = false;
441
- if (isOptionalEntityId(compType)) {
442
- compType = compType.optional;
443
- optional = true;
444
- }
445
- if (getIdType(compType) === "wildcard-relation") {
446
- if (dataSource === undefined) {
447
- if (optional) {
448
- return;
449
- } else {
450
- throw new Error(`No matching relations found for mandatory wildcard relation component type`);
451
- }
452
- }
453
- const matchingRelations = dataSource;
454
- const relations = [];
455
- for (const relType of matchingRelations) {
456
- const dataArray = this.getComponentData(relType);
457
- const data = dataArray[entityIndex];
458
- const decodedRel = decodeRelationId(relType);
459
- relations.push([decodedRel.targetId, data === MISSING_COMPONENT ? undefined : data]);
460
- }
461
- return optional ? { value: relations } : relations;
462
- } else {
463
- if (dataSource === undefined) {
464
- if (optional) {
465
- return;
466
- } else {
467
- throw new Error(`No matching relations found for mandatory wildcard relation component type`);
468
- }
429
+ }
430
+ buildComponentsForIndex(componentTypes, componentDataSources, entityIndex) {
431
+ return componentDataSources.map((dataSource, i) => {
432
+ let compType = componentTypes[i];
433
+ let optional = false;
434
+ if (isOptionalEntityId(compType)) {
435
+ compType = compType.optional;
436
+ optional = true;
437
+ }
438
+ if (getIdType(compType) === "wildcard-relation") {
439
+ if (dataSource === undefined) {
440
+ if (optional) {
441
+ return;
442
+ } else {
443
+ throw new Error(`No matching relations found for mandatory wildcard relation component type`);
469
444
  }
470
- const dataArray = dataSource;
445
+ }
446
+ const matchingRelations = dataSource;
447
+ const relations = [];
448
+ for (const relType of matchingRelations) {
449
+ const dataArray = this.getComponentData(relType);
471
450
  const data = dataArray[entityIndex];
472
- const result = data === MISSING_COMPONENT ? undefined : data;
473
- return optional ? { value: result } : result;
451
+ const decodedRel = decodeRelationId(relType);
452
+ relations.push([decodedRel.targetId, data === MISSING_COMPONENT ? undefined : data]);
474
453
  }
475
- });
454
+ return optional ? { value: relations } : relations;
455
+ } else {
456
+ if (dataSource === undefined) {
457
+ if (optional) {
458
+ return;
459
+ } else {
460
+ throw new Error(`No matching relations found for mandatory wildcard relation component type`);
461
+ }
462
+ }
463
+ const dataArray = dataSource;
464
+ const data = dataArray[entityIndex];
465
+ const result = data === MISSING_COMPONENT ? undefined : data;
466
+ return optional ? { value: result } : result;
467
+ }
468
+ });
469
+ }
470
+ getEntitiesWithComponents(componentTypes) {
471
+ const result = [];
472
+ this.forEachWithComponents(componentTypes, (entity, ...components) => {
473
+ result.push({ entity, components });
474
+ });
475
+ return result;
476
+ }
477
+ *iterateWithComponents(componentTypes) {
478
+ const componentDataSources = this.getCachedComponentDataSources(componentTypes);
479
+ for (let entityIndex = 0;entityIndex < this.entities.length; entityIndex++) {
480
+ const entity = this.entities[entityIndex];
481
+ const components = this.buildComponentsForIndex(componentTypes, componentDataSources, entityIndex);
482
+ yield [entity, ...components];
483
+ }
484
+ }
485
+ forEachWithComponents(componentTypes, callback) {
486
+ const componentDataSources = this.getCachedComponentDataSources(componentTypes);
487
+ for (let entityIndex = 0;entityIndex < this.entities.length; entityIndex++) {
488
+ const entity = this.entities[entityIndex];
489
+ const components = this.buildComponentsForIndex(componentTypes, componentDataSources, entityIndex);
476
490
  callback(entity, ...components);
477
491
  }
478
492
  }
@@ -756,6 +770,14 @@ class Query {
756
770
  archetype.forEachWithComponents(componentTypes, callback);
757
771
  }
758
772
  }
773
+ *iterate(componentTypes) {
774
+ if (this.isDisposed) {
775
+ throw new Error("Query has been disposed");
776
+ }
777
+ for (const archetype of this.cachedArchetypes) {
778
+ yield* archetype.iterateWithComponents(componentTypes);
779
+ }
780
+ }
759
781
  getComponentData(componentType) {
760
782
  if (this.isDisposed) {
761
783
  throw new Error("Query has been disposed");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codehz/ecs",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",
package/query.d.ts CHANGED
@@ -32,6 +32,11 @@ export declare class Query {
32
32
  * @param callback Function called for each entity with its components
33
33
  */
34
34
  forEach<const T extends readonly ComponentType<any>[]>(componentTypes: T, callback: (entity: EntityId, ...components: ComponentTuple<T>) => void): void;
35
+ /**
36
+ * Iterate over entities with their component data (generator)
37
+ * @param componentTypes Array of component types to retrieve
38
+ */
39
+ iterate<const T extends readonly ComponentType<any>[]>(componentTypes: T): IterableIterator<[EntityId, ...ComponentTuple<T>]>;
35
40
  /**
36
41
  * Get component data arrays for all matching entities
37
42
  * @param componentType The component type to retrieve