import {compose, merge, mergeDiff, Property} from '@avocado/core'; import {Vector} from '@avocado/math'; import {Synchronized} from '@avocado/state'; const decorate = compose( Synchronized, ); export class Trait extends decorate(class {}) { constructor(entity, params, state) { super(); this.entity = entity; const ctor = this.constructor; this._memoizedListeners = undefined; this.params = Object.assign({}, ctor.defaultParams(), params); this.state = Object.assign({}, ctor.defaultState(), state); this.previousState = JSON.parse(JSON.stringify(this.state)); if (this.tick) { this.tick = this.tick.bind(this); } if (this.renderTick) { this.renderTick = this.renderTick.bind(this); } } createTraitPacketUpdates(Packet) { const packets = []; if (this.isDirty) { packets.push(new Packet(this.state, this.entity)); this.makeClean(); } return packets; } destroy() {} hooks() { return {}; } hydrate() { return Promise.resolve(); } get isDirty() { for (const key in this.state) { if (this.state[key] !== this.previousState[key]) { return true; } } return false; } label() { return this.constructor.name; } listeners() { return {}; } makeClean() { for (const key in this.state) { this.previousState[key] = this.state[key]; } } memoizedListeners() { if (!this._memoizedListeners) { this._memoizedListeners = this.listeners(); } return this._memoizedListeners; } methods() { return {}; } toJSON() { return { params: this.params, state: this.state, }; } transformPatchValue(key, value) { return value; } static contextType() { return {}; } static defaultJSON() { return { params: this.defaultParams(), state: this.defaultState(), }; } static defaultParams() { return {}; } static defaultState() { return {}; } static dependencies() { return []; } } export function StateProperty(key, meta = {}) { let transformedProperty; if (meta.transformProperty) { transformedProperty = meta.transformProperty(key); } else { transformedProperty = `$$avocado_state_property_${key}`; } return (Superclass) => { meta.emit = meta.emit || function(...args) { this.entity.emit(...args); }; meta.initialize = meta.initialize || function() { this[transformedProperty] = this.state[key]; } meta.get = meta.get || new Function(` return this.${transformedProperty}; `); meta.set = meta.set || new Function('value', ` this.${transformedProperty} = value; this.state['${key}'] = value; `); return Property(key, meta)(Superclass); } }