UNPKG

entix-ecs

Version:
81 lines (76 loc) 3.51 kB
export type EntityId = number;// A entityId type type ComponentClass<T> = new (...args: any[]) => T type Query = 'All' | 'Any' | 'None'; export class EntityManager {// A class to manage all the entities private entityCount: number = 0;//A counter for id's private entities: EntityId[] = [];//A array of entities private componentMap: Map<EntityId, Map<ComponentClass<any>, any>> = new Map();/* A nested map, contains EntityId with a another map containing components.*/ createEntity(): EntityId {// create a entity const id: EntityId = this.entityCount; this.entities.push(id); this.componentMap.set(id, new Map()); this.entityCount++; return id; }; addComponent<T>(id: EntityId, componentClass: ComponentClass<T>, componentInstance: T) {/* adds a component to entity, doenst add a already added*/ this.ensureEntityExists(id); const components = this.componentMap.get(id); if (!components?.has(componentClass)) { components?.set(componentClass, componentInstance); } }; removeComponent<T>(id: EntityId, componentClass: ComponentClass<T>) {//removes a component from entity this.ensureEntityExists(id); const components = this.componentMap.get(id); if (components?.has(componentClass)) { components.delete(componentClass); } }; getComponent<T>(id: EntityId, componentClass: ComponentClass<T>): T | undefined {// used to get a component this.ensureEntityExists(id); const components = this.componentMap.get(id); const requestedComponent = components?.get(componentClass) as T | undefined; return requestedComponent; }; getAllComponents(id: EntityId): any[] { this.ensureEntityExists(id); const components = this.componentMap.get(id); if (!components) return []; return Array.from(components.values()); }; removeEntity(id: EntityId) { this.ensureEntityExists(id); this.entities = this.entities.filter(e => e !== id); this.componentMap.delete(id); }; query<T extends Record<string,ComponentClass<any>>>( filterType: Query, componentsToMatch: T, callback: (id: EntityId, matched: {[K in keyof T]:InstanceType<T[K]>}) => void ) { for (const entity of this.entities) { const matched = {} as {[K in keyof T]: InstanceType<T[K]>}; const results: boolean[] = []; 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():EntityId[]{ return this.entities; } private ensureEntityExists(id: EntityId) { if (!this.entities.includes(id)) throw new Error(`Entity ${id} does not exist!`); }; };