UNPKG

entix-ecs

Version:
105 lines (104 loc) 3.54 kB
export class EntityManager { entityCount = 0; //A counter for id's entities = []; //A array of entities componentMap = new Map(); /* A nested map, contains EntityId with a another map containing components.*/ createEntity() { const id = this.entityCount; this.entities.push(id); this.componentMap.set(id, new Map()); this.entityCount++; return id; } ; addComponent(id, componentClass, componentInstance) { if (!this.hasEntity(id)) throw new Error(`Entity ${id} does not exist!`); const components = this.componentMap.get(id); if (!components?.has(componentClass)) { components?.set(componentClass, componentInstance); } } ; removeComponent(id, componentClass) { if (!this.hasEntity(id)) throw new Error(`Entity ${id} does not exist!`); const components = this.componentMap.get(id); if (components?.has(componentClass)) { components.delete(componentClass); } } ; getComponent(id, componentClass, strict) { if (!this.hasEntity(id)) throw new Error(`Entity ${id} does not exist!`); const components = this.componentMap.get(id); const requestedComponent = components?.get(componentClass); if (strict && !requestedComponent) { throw new Error(`'${componentClass.name}'` + ' COMPONENT NOT FOUND ON ENTITY: ' + id); } return requestedComponent; } ; getAllComponents(id) { if (!this.hasEntity(id)) throw new Error(`Entity ${id} does not exist!`); const components = this.componentMap.get(id); if (!components) return []; return Array.from(components.values()); } ; hasComponent(id, componentClass) { if (!this.hasEntity(id)) throw new Error(`Entity ${id} does not exist!`); return this.componentMap.get(id)?.has(componentClass) ?? false; } ; removeEntity(id) { if (!this.hasEntity(id)) throw new Error(`Entity ${id} does not exist!`); this.entities = this.entities.filter(e => e !== id); this.componentMap.delete(id); } ; query(filterType, componentsToMatch, callback) { const entitiesSnapshot = [...this.entities]; for (const entity of entitiesSnapshot) { if (!this.hasEntity(entity)) continue; const matched = {}; const results = []; for (const key in componentsToMatch) { const compClass = componentsToMatch[key]; const instance = this.getComponent(entity, compClass); if (instance) matched[key] = instance; results.push(!!instance); } let shouldCall = false; if (filterType === 'All') shouldCall = results.every(Boolean); else if (filterType === 'Any') shouldCall = results.some(Boolean); else if (filterType === 'None') shouldCall = results.every(r => !r); else throw new Error(`Unknown filter type: ${filterType}`); if (shouldCall) callback(entity, matched); } } ; getAllEntities() { return this.entities; } ; hasEntity(id) { if (this.entities.includes(id)) return true; return false; } ; } ;