humus-old/traits/informed.js
2019-04-08 08:31:13 -04:00

80 lines
1.8 KiB
JavaScript

import * as I from 'immutable';
import immutablediff from 'immutablediff';
import isPlainObject from 'is-plain-object';
import {compose} from '@avocado/core';
import {Trait} from '@avocado/entity';
import {Packer, Synchronizer} from '@avocado/state';
const decorate = compose(
);
export class Informed extends decorate(Trait) {
initialize() {
this._packer = new Packer();
this._socket = undefined;
this._state = I.Map();
}
destroy() {
if (this._socket) {
delete this._socket.entity;
delete this._socket;
}
}
reduceState(state) {
// Set client's self entity.
state = state.set('selfEntity', this.entity.instanceUuid);
// Reduce entity list to visible.
const room = this.entity.room;
const camera = this.entity.camera;
for (const {index, layer} of room.layers) {
const visibleEntities = layer.visibleEntities(
camera.rectangle
);
let reducedEntityList = I.Map();
for (const entity of visibleEntities) {
reducedEntityList = reducedEntityList.set(
entity.instanceUuid,
entity.state,
);
}
const entityListPath = ['room', 'layers', index, 'entityList'];
state = state.setIn(entityListPath, reducedEntityList);
}
return state;
}
get socket() {
return this._socket;
}
set socket(socket) {
socket.entity = this.entity;
this._socket = socket;
}
methods() {
return {
inform: (state) => {
// Reduce state.
const reducedState = this.reduceState(state);
// Take a pure JS diff.
const steps = immutablediff(this._state, reducedState).toJS();
this._state = reducedState;
if (0 === steps.length) {
return;
}
// Emit!
const packed = this._packer.pack(steps);
this._socket.send({s: packed});
},
};
}
}