import Digraph from '@/util/digraph.js'; import Query from './query.js'; export default class System { active = false; destroying = []; ecs; elapsed = 0; frequency; queries = {}; constructor(ecs) { this.ecs = ecs; const queries = this.constructor.queries(); for (const i in queries) { this.queries[i] = new Query(queries[i], ecs); } this.reindex(ecs.entities); } createEntity(components) { return this.ecs.create(components); } createManyEntities(componentsList) { return this.ecs.createMany(componentsList); } deindex(entityIds) { for (const i in this.queries) { this.queries[i].deindex(entityIds); } } destroyEntity(entityId) { this.destroyManyEntities([entityId]); } destroyManyEntities(entityIds) { for (let i = 0; i < entityIds.length; i++) { this.destroying.push(entityIds[i]); } } async insertComponents(entityId, components) { return this.ecs.insert(entityId, components); } async insertManyComponents(components) { return this.ecs.insertMany(components); } static get priority() { return { phase: 'normal', } } static queries() { return {}; } reindex(entityIds) { for (const i in this.queries) { this.queries[i].reindex(entityIds); } } removeComponents(entityId, components) { this.ecs.remove(entityId, components); } removeManyComponents(entityIds) { this.ecs.removeMany(entityIds); } select(query) { return this.queries[query].select(); } static sort(Systems) { const phases = { 'pre': new Digraph(), 'normal': new Digraph(), 'post': new Digraph(), }; for (const systemName in Systems) { const {priority} = Systems[systemName]; const phase = phases[priority.phase || 'normal']; phase.ensureTail(systemName); if (priority.before) { for (const before of Array.isArray(priority.before) ? priority.before : [priority.before]) { phase.addDependency(before, systemName); } } if (priority.after) { for (const after of Array.isArray(priority.after) ? priority.after : [priority.after]) { phase.addDependency(systemName, after); } } } const sorted = [ ...phases['pre'].sort(), ...phases['normal'].sort(), ...phases['post'].sort(), ]; return Object.fromEntries( Object.entries(Systems) .toSorted(([l], [r]) => sorted.indexOf(l) - sorted.indexOf(r)), ); } tickDestruction() { if (this.destroying.length > 0) { this.deindex(this.destroying); } this.destroying = []; } tick() {} }