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

110 lines
2.8 KiB
JavaScript

import Base from './base.js';
export default class Arbitrary extends Base {
data = [];
serializer;
Instance;
allocateMany(count) {
if (!this.Instance) {
this.Instance = this.instanceFromSchema();
}
const results = super.allocateMany(count);
count -= results.length; while (count--) {
results.push(this.data.push(new this.Instance()) - 1);
}
return results;
}
createMany(entries) {
if (entries.length > 0) {
const allocated = this.allocateMany(entries.length);
const keys = Object.keys(this.constructor.properties);
for (let i = 0; i < entries.length; ++i) {
const [entityId, values = {}] = entries[i];
this.map[entityId] = allocated[i];
this.data[allocated[i]].entity = entityId;
if (false === values) {
continue;
}
for (let k = 0; k < keys.length; ++k) {
const j = keys[k];
const {defaultValue} = this.constructor.properties[j];
if (j in values) {
this.data[allocated[i]][j] = values[j];
}
else if ('undefined' !== typeof defaultValue) {
this.data[allocated[i]][j] = defaultValue;
}
}
}
}
}
deserialize(entityId, view, offset) {
const {properties} = this.constructor;
const instance = this.get(entityId);
const deserialized = this.constructor.schema.deserialize(view, offset);
for (const key in properties) {
instance[key] = deserialized[key];
}
}
serialize(entityId, view, offset) {
this.constructor.schema.serialize(this.get(entityId), view, offset);
}
get(entityId) {
return this.data[this.map[entityId]];
}
instanceFromSchema() {
const Component = this;
const Instance = class {
$$entity = 0;
constructor() {
this.$$reset();
}
$$reset() {
const {properties} = Component.constructor;
for (const key in properties) {
const {defaultValue} = properties[key];
this[`$$${key}`] = defaultValue;
}
}
toJSON() {
return Component.constructor.filterDefaults(this);
}
};
const properties = {};
properties.entity = {
get: function get() {
return this.$$entity;
},
set: function set(v) {
this.$$entity = v;
this.$$reset();
},
};
for (const key in Component.constructor.properties) {
properties[key] = {
get: function get() {
return this[`$$${key}`];
},
set: function set(value) {
if (this[`$$${key}`] !== value) {
this[`$$${key}`] = value;
Component.markChange(this.entity, key, value);
}
},
};
}
Object.defineProperties(Instance.prototype, properties);
return Instance;
}
}