ecsjs
Version:
An entity component system library for JavaScript
64 lines (55 loc) • 1.98 kB
text/typescript
import type { ComponentMap } from './component-map.js';
import type { EntityMap } from './entity-map.js';
import type { ComponentClass, ComponentInstances, IteratorResult } from './types.js';
/**
* @category Iterators
* @example
* // construct an instance
* const iterator = new ComponentIterator(entityMap, Player, Position)
*
* // iterate each component value that is related to the Player
* for(const [entityId, player, position] of iterator) { }
*
* // you can also reset the iterator back to the start
* // without having to create a new ComponentIterator instance
* iterator.reset()
* for(const [entityId, player, position] of iterator) { }
*/
export class ComponentIterator<
TComponentKey extends ComponentClass<any>,
TComponentClasses extends ComponentClass<any>[]
> {
private keyMap: ComponentMap<any>
private components: ComponentMap<any>[]
// iteration state
private entries: MapIterator<[number, TComponentKey]>
/**
* {@link ComponentNotRegistered} when any of specified component(s) are not registered
*/
constructor(public ecs: EntityMap, public key: TComponentKey, ...components: TComponentClasses) {
this.keyMap = this.ecs.getMap(key)!;
this.entries = this.keyMap.entries();
this.components = components.map(x => this.ecs.getMap(x)!);
}
/**
* gets the next iterator value
*/
next(): IteratorResult<ComponentInstances<[ComponentClass<number>, TComponentKey, ...TComponentClasses]>> {
const entry = this.entries.next();
const { value, done } = entry;
if (done) return { value: value as any, done };
const [entityId, entityValue] = value;
const results = [entityId, entityValue]
for (const x of this.components) {
results.push(x.get(entityId));
}
return { value: results as any, done: false };
}
/**
* resets the iterator back to the first entry
*/
reset() {
this.entries = this.keyMap.entries();
}
[Symbol.iterator]() { return this; }
}