silphius/app/ecs/system.js
2024-06-11 00:22:30 -05:00

113 lines
2.1 KiB
JavaScript

import Query from './query.js';
export default class System {
destroying = [];
ecs;
queries = {};
constructor(ecs) {
this.ecs = ecs;
const queries = this.constructor.queries();
for (const i in queries) {
this.queries[i] = new Query(queries[i], ecs.Types);
}
}
deindex(entities) {
for (const i in this.queries) {
this.queries[i].deindex(entities);
}
}
destroyEntity(entity) {
this.destroyManyEntities([entity]);
}
destroyManyEntities(entities) {
for (let i = 0; i < entities.length; i++) {
this.destroying.push(entities[i]);
}
}
finalize() {}
static normalize(SystemLike) {
if (SystemLike.prototype instanceof System) {
return SystemLike;
}
if ('function' === typeof SystemLike) {
class TickingSystem extends System {}
TickingSystem.prototype.tick = SystemLike;
return TickingSystem;
}
/* v8 ignore next */
throw new TypeError(`Couldn't normalize '${SystemLike}' as a system`);
}
static queries() {
return {};
}
reindex(entities) {
for (const i in this.queries) {
this.queries[i].reindex(entities);
}
}
select(query) {
return this.queries[query].select();
}
tickDestruction() {
this.deindex(this.destroying);
this.destroying = [];
}
tick() {}
static wrap(source, ecs) {
class WrappedSystem extends System.normalize(source) {
constructor() {
super(ecs);
this.reindex(ecs.entities);
}
createEntity(components) {
return this.ecs.create(components);
}
createManyEntities(componentsList) {
return this.ecs.createMany(componentsList);
}
get source() {
return source;
}
insertComponents(entity, components) {
this.ecs.insert(entity, components);
}
insertManyComponents(components) {
this.ecs.insertMany(components);
}
removeComponents(entity, components) {
this.ecs.remove(entity, components);
}
removeManyComponents(entities) {
this.ecs.removeMany(entities);
}
}
return new WrappedSystem();
}
}