diff --git a/app/ecs/component.js b/app/ecs/component.js index be65c84..b2c182d 100644 --- a/app/ecs/component.js +++ b/app/ecs/component.js @@ -134,11 +134,22 @@ export default class Component { $$entity = 0; destroy() {} initialize(values, defaults) { + const {properties} = concrete; for (const key in values) { - this[`$$${key}`] = values[key]; + if (properties[key]?.$.set) { + properties[key].$.set(Component, this, `$$${key}`, values[key]); + } + else { + this[`$$${key}`] = values[key]; + } } for (const key in defaults) { - this[`$$${key}`] = defaults[key]; + if (properties[key]?.$.set) { + properties[key].$.set(Component, this, `$$${key}`, defaults[key]); + } + else { + this[`$$${key}`] = defaults[key]; + } } Component.ecs.markChange(this.entity, {[Component.constructor.componentName]: values}) } @@ -146,7 +157,12 @@ export default class Component { const {properties} = concrete; const json = {}; for (const key in properties) { - json[key] = this[key]; + if (properties[key]?.$.json) { + json[key] = properties[key].$.json(this[key]); + } + else { + json[key] = this[key]; + } } return json; } @@ -160,9 +176,15 @@ export default class Component { return this.toFullJSON(); } update(values) { + const {properties} = concrete; for (const key in values) { - if (concrete.properties[key]) { - this[`$$${key}`] = values[key]; + if (properties[key]) { + if (properties[key]?.$.set) { + properties[key].$.set(Component, this, `$$${key}`, values[key]); + } + else { + this[`$$${key}`] = values[key]; + } } else { this[key] = values[key]; @@ -186,7 +208,12 @@ export default class Component { }, set: function set(value) { if (this[`$$${key}`] !== value) { - this[`$$${key}`] = value; + if (concrete.properties[key]?.$.set) { + concrete.properties[key].$.set(Component, this, `$$${key}`, value); + } + else { + this[`$$${key}`] = value; + } Component.markChange(this.entity, key, value); } }, diff --git a/app/ecs/components/alive.js b/app/ecs/components/alive.js index 94e6ff0..fe47d03 100644 --- a/app/ecs/components/alive.js +++ b/app/ecs/components/alive.js @@ -19,8 +19,8 @@ export default class Alive extends Component { this.$$dead = true; const {Ticking} = ecs.get(this.entity); if (Ticking) { - this.$$death.locals.entity = ecs.get(this.entity); - const ticker = this.$$death.ticker(); + this.deathScript.locals.entity = ecs.get(this.entity); + const ticker = this.deathScript.ticker(); ecs.addDestructionDependency(this.entity.id, Ticking.add(ticker)); } } @@ -30,21 +30,11 @@ export default class Alive extends Component { if (0 === instance.maxHealth) { instance.maxHealth = instance.health; } - // heavy handed... - if ('undefined' !== typeof window) { - return; - } - instance.$$death = this.ecs.readScript( - instance.deathScript, - { - ecs: this.ecs, - }, - ); } static properties = { deathScript: { defaultValue: '/resources/misc/death-default.js', - type: 'string', + type: 'script', }, health: {type: 'uint32'}, maxHealth: {type: 'uint32'}, diff --git a/app/ecs/components/behaving.js b/app/ecs/components/behaving.js index ac3c64a..540b117 100644 --- a/app/ecs/components/behaving.js +++ b/app/ecs/components/behaving.js @@ -16,10 +16,6 @@ export default class Behaving extends Component { }; } load(instance) { - // heavy handed... - if ('undefined' !== typeof window) { - return; - } for (const key in instance.routines) { instance.$$routineInstances[key] = this.ecs.readScript(instance.routines[key]); } diff --git a/app/ecs/components/collider.js b/app/ecs/components/collider.js index 0c6c2aa..de2ad20 100644 --- a/app/ecs/components/collider.js +++ b/app/ecs/components/collider.js @@ -9,8 +9,6 @@ export default class Collider extends Component { return class ColliderInstance extends super.instanceFromSchema() { $$aabb = {x0: Infinity, x1: -Infinity, y0: Infinity, y1: -Infinity}; $$aabbs = []; - $$collisionStart; - $$collisionEnd; $$intersections = new Map(); get aabb() { const {Position: {x: px, y: py}} = ecs.get(this.entity); @@ -77,8 +75,8 @@ export default class Collider extends Component { } } if (!hasMatchingIntersection) { - if (this.$$collisionStart) { - const script = this.$$collisionStart.clone(); + if (this.collisionStartScript) { + const script = this.collisionStartScript.clone(); script.locals.entity = thisEntity; script.locals.other = otherEntity; script.locals.pair = [body, otherBody]; @@ -87,8 +85,8 @@ export default class Collider extends Component { ecs.addDestructionDependency(otherEntity.id, promise); ecs.addDestructionDependency(thisEntity.id, promise); } - if (other.$$collisionStart) { - const script = other.$$collisionStart.clone(); + if (other.collisionStartScript) { + const script = other.collisionStartScript.clone(); script.locals.entity = otherEntity; script.locals.other = thisEntity; script.locals.pair = [otherBody, body]; @@ -162,8 +160,8 @@ export default class Collider extends Component { intersection.entity.bodies[intersection.i], intersection.other.bodies[intersection.j], ]; - if (this.$$collisionEnd) { - const script = this.$$collisionEnd.clone(); + if (this.collisionEndScript) { + const script = this.collisionEndScript.clone(); script.locals.other = otherEntity; script.locals.pair = [body, otherBody]; const ticker = script.ticker(); @@ -171,8 +169,8 @@ export default class Collider extends Component { ecs.addDestructionDependency(thisEntity.id, promise); ecs.addDestructionDependency(otherEntity.id, promise); } - if (other.$$collisionEnd) { - const script = other.$$collisionEnd.clone(); + if (other.collisionEndScript) { + const script = other.collisionEndScript.clone(); script.locals.other = thisEntity; script.locals.pair = [otherBody, body]; const ticker = script.ticker(); @@ -268,26 +266,6 @@ export default class Collider extends Component { }; } instance.updateAabbs(); - // heavy handed... - if ('undefined' !== typeof window) { - return; - } - if (instance.collisionEndScript) { - instance.$$collisionEnd = this.ecs.readScript( - instance.collisionEndScript, - { - ecs: this.ecs, - }, - ); - } - if (instance.collisionStartScript) { - instance.$$collisionStart = this.ecs.readScript( - instance.collisionStartScript, - { - ecs: this.ecs, - }, - ); - } } static properties = { bodies: { @@ -311,8 +289,8 @@ export default class Collider extends Component { }, }, }, - collisionEndScript: {type: 'string'}, - collisionStartScript: {type: 'string'}, + collisionEndScript: {type: 'script'}, + collisionStartScript: {type: 'script'}, isColliding: {defaultValue: 1, type: 'uint8'}, }; } diff --git a/app/ecs/components/harmful.js b/app/ecs/components/harmful.js index 9dec10c..3db78ba 100644 --- a/app/ecs/components/harmful.js +++ b/app/ecs/components/harmful.js @@ -6,26 +6,14 @@ export default class Harmful extends Component { return class HarmfulInstance extends super.instanceFromSchema() { harm(other) { const entity = ecs.get(this.entity); - const script = this.$$harm.clone(); + const script = this.harmScript.clone(); script.locals.other = other; script.locals.entity = entity; entity.Ticking.add(script.ticker()); } } } - load(instance) { - // heavy handed... - if ('undefined' !== typeof window) { - return; - } - instance.$$harm = this.ecs.readScript( - instance.harmScript, - { - ecs: this.ecs, - }, - ); - } static properties = { - harmScript: {type: 'string'}, + harmScript: {type: 'script'}, }; } diff --git a/app/ecs/components/interactive.js b/app/ecs/components/interactive.js index ecc5528..487f607 100644 --- a/app/ecs/components/interactive.js +++ b/app/ecs/components/interactive.js @@ -4,9 +4,8 @@ export default class Interactive extends Component { instanceFromSchema() { const {ecs} = this; return class ControlledInstance extends super.instanceFromSchema() { - $$interact; interact(initiator) { - const script = this.$$interact.clone(); + const script = this.interactScript.clone(); script.locals.initiator = initiator; script.locals.subject = ecs.get(this.entity); const {Ticking} = script.locals.subject; @@ -20,20 +19,8 @@ export default class Interactive extends Component { } } } - load(instance) { - // heavy handed... - if ('undefined' !== typeof window) { - return; - } - instance.$$interact = this.ecs.readScript( - instance.interactScript, - { - ecs: this.ecs, - }, - ); - } static properties = { interacting: {type: 'uint8'}, - interactScript: {type: 'string'}, + interactScript: {type: 'script'}, }; } diff --git a/app/ecs/components/plant.js b/app/ecs/components/plant.js index f19aa98..ba188b8 100644 --- a/app/ecs/components/plant.js +++ b/app/ecs/components/plant.js @@ -5,44 +5,26 @@ export default class Plant extends Component { const {ecs} = this; const Instance = super.instanceFromSchema(); return class PlantInstance extends Instance { - $$grow; - $$mayGrow; grow() { const {Ticking} = ecs.get(this.entity); - Ticking.add(this.$$grow.ticker()); + Ticking.add(this.growScript.ticker()); } mayGrow() { - return this.$$mayGrow.evaluate(); + return this.mayGrowScript.evaluate(); } }; } load(instance) { - // heavy handed... - if ('undefined' !== typeof window) { - return; - } - instance.$$grow = this.ecs.readScript( - instance.growScript, - { - ecs: this.ecs, - plant: instance, - }, - ); - instance.$$mayGrow = this.ecs.readScript( - instance.mayGrowScript, - { - ecs: this.ecs, - plant: instance, - }, - ); + instance.growScript.locals.plant = instance; + instance.mayGrowScript.locals.plant = instance; } // heavy handed... markChange() {} static properties = { - growScript: {type: 'string'}, + growScript: {type: 'script'}, growth: {type: 'uint16'}, growthFactor: {defaultValue: 127, type: 'uint8'}, - mayGrowScript: {type: 'string'}, + mayGrowScript: {type: 'script'}, stage: {type: 'uint8'}, stages: { type: 'array', diff --git a/app/ecs/schema-types/script.js b/app/ecs/schema-types/script.js new file mode 100644 index 0000000..9429f52 --- /dev/null +++ b/app/ecs/schema-types/script.js @@ -0,0 +1,22 @@ +import string from './string.js'; + +export default function () { + const spec = string(); + return { + ...spec, + json: (value) => { + return value ? value.path : ''; + }, + set: (Component, receiver, key, value) => { + if (!value) { + return; + } + receiver[key] = Component.ecs.readScript( + value, + { + ecs: Component.ecs, + }, + ); + }, + }; +} diff --git a/app/util/script.js b/app/util/script.js index c142840..858505c 100644 --- a/app/util/script.js +++ b/app/util/script.js @@ -4,18 +4,19 @@ export default class Script { static registered = {}; - constructor(fn, locals) { + constructor(path, fn, locals) { if (!fn) { throw new TypeError('Script needs a function'); } this.fn = fn; this.iterator = null; this.locals = locals; + this.path = path; this.$$ticker = null; } clone() { - return new this.constructor(this.fn, this.locals); + return new this.constructor(this.path, this.fn, this.locals); } evaluate() { @@ -27,7 +28,7 @@ export default class Script { if (!fn) { throw new Error(`no such script: ${path}`); } - const script = new this(fn, locals); + const script = new this(path, fn, locals); if (import.meta.hot) { const hotRef = new WeakRef(script); import.meta.hot.accept('./scripts.js', ({default: scripts}) => {