silphius/app/ecs/base.js
2024-06-12 01:38:05 -05:00

99 lines
2.1 KiB
JavaScript

export default class Base {
map = [];
pool = [];
static schema;
allocateMany(count) {
const results = [];
while (count-- > 0 && this.pool.length > 0) {
results.push(this.pool.pop());
}
return results;
}
create(entityId, values) {
this.createMany([[entityId, values]]);
}
destroy(entityId) {
this.destroyMany([entityId]);
}
destroyMany(entities) {
this.freeMany(
entities
.map((entityId) => {
if ('undefined' !== typeof this.map[entityId]) {
return this.map[entityId];
}
throw new Error(`can't free for non-existent id ${entityId}`);
}),
);
for (let i = 0; i < entities.length; i++) {
this.map[entities[i]] = undefined;
}
}
static filterDefaults(instance) {
const json = {};
for (const key in this.properties) {
const {defaultValue} = this.properties[key];
if (key in instance && instance[key] !== defaultValue) {
json[key] = instance[key];
}
}
return json;
}
freeMany(indices) {
for (let i = 0; i < indices.length; ++i) {
this.pool.push(indices[i]);
}
}
insertMany(entities) {
const creating = [];
for (let i = 0; i < entities.length; i++) {
const [entityId, values] = entities[i];
if (!this.get(entityId)) {
creating.push([entityId, values]);
}
else {
const instance = this.get(entityId);
for (const i in values) {
instance[i] = values[i];
}
}
}
this.createMany(creating);
}
// eslint-disable-next-line no-unused-vars
markChange(entityId, components) {}
mergeDiff(original, update) {
return {...original, ...update};
}
static get properties() {
return this.schema.specification.properties;
}
sizeOf(entityId) {
return this.constructor.schema.sizeOf(this.get(entityId));
}
static wrap(name, ecs) {
class WrappedComponent extends this {
markChange(entityId, key, value) {
ecs.markChange(entityId, {[name]: {[key]: value}})
}
}
return new WrappedComponent();
}
}