/* ecsjs is an entity component system library for JavaScript Copyright (C) 2014 Peter Flannery This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ import type { ComponentMap } from './component-map.js'; import type { ComponentQuery } from './query.js'; /** * An iterator for yielding entity ids and their associated component data * @category Iterators * @example * // construct an instance * const iterator = new ComponentIterator(new ComponentQuery(entityMap, Player, Position)) * * // iterate component data 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 { private keyMap: ComponentMap; private componentMaps: ComponentMap[] = []; // iteration state private entries: Iterator<[number, TKey]>; /** * Creates a new component iterator * @param query - The {@link ComponentQuery} to iterate over */ constructor(query: ComponentQuery) { // @ts-ignore internal private var accessor this.keyMap = query.keyMap // @ts-ignore internal private var accessor this.componentMaps = query.componentMaps this.entries = this.keyMap.entries(); } /** * Gets the next iterator value * @returns An {@link IteratorResult} containing the next [entityId, keyComponentData, ...relatedComponentData] tuple */ next(): IteratorResult<[number, TKey, ...TRelated]> { const entry = this.entries.next(); const { value, done } = entry; if (done) return { value, done }; const entityId = value[0]; // append the related components for (let i = 0; i < this.componentMaps.length; i++) { const map = this.componentMaps[i]; value.push(map.get(entityId)); } return { value: value as any, done: false }; } /** * Resets the iterator back to the first entry */ reset() { this.entries = this.keyMap.entries(); } /** * Returns this iterator instance */ [Symbol.iterator]() { return this; } }