avocado-old/packages/entity/trait/index.js
2020-06-19 15:31:35 -05:00

172 lines
3.2 KiB
JavaScript

import {compose, merge, mergeDiff, Property} from '@avocado/core';
import {Vector} from '@avocado/math';
import {SynchronizedMixin} from '@avocado/net';
const decorate = compose(
SynchronizedMixin,
);
export class Trait extends decorate(class {}) {
constructor(entity, params, state) {
super();
this.entity = entity;
const ctor = this.constructor;
this._fastDirtyCheck = true;
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);
}
}
acceptPacket(packet) {
}
cleanPackets() {
if (!this._fastDirtyCheck) {
return;
}
for (const key in this.state) {
this.previousState[key] = this.state[key];
}
this._fastDirtyCheck = false;
}
static contextDescription() {
return {};
}
static defaultJSON() {
return {
params: this.defaultParams(),
state: this.defaultState(),
};
}
static defaultParams() {
return {};
}
static defaultState() {
return {};
}
static dependencies() {
return [];
}
static describeParams() {
return {};
}
static describeState() {
return {};
}
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 {};
}
memoizedListeners() {
if (!this._memoizedListeners) {
this._memoizedListeners = this.listeners();
}
return this._memoizedListeners;
}
methods() {
return {};
}
packets(informed) {
const packets = [];
return packets;
}
packetsAreIdempotent() {
return false;
}
setDirty() {
this._fastDirtyCheck = true;
this.entity._fastDirtyCheck = true;
}
stateDifferences() {
const differences = {};
for (const key in this.state) {
if (this.state[key] !== this.previousState[key]) {
differences[key] = {
old: this.previousState[key],
value: this.state[key],
};
}
}
return differences;
}
toJSON() {
return {
params: this.params,
state: this.state,
};
}
transformPatchValue(key, value) {
return value;
}
}
export function StateProperty(key, meta = {}) {
const transformedKey = `$$avocado_state_property_${key}`;
return (Superclass) => {
meta.emit = meta.emit || function(...args) {
this.entity.emit(...args);
};
meta.initialize = meta.initialize || function() {
this[transformedKey] = this.state[key];
}
meta.get = meta.get || new Function(`
return this.${transformedKey};
`);
meta.set = meta.set || new Function('value', `
if (value !== this.${transformedKey}) {
this.setDirty();
}
this.${transformedKey} = value;
this.state['${key}'] = value;
`);
return Property(key, meta)(Superclass);
}
}