humus-old/traits/informed.js
2019-03-27 19:25:10 -05:00

129 lines
2.9 KiB
JavaScript

import * as I from 'immutable';
import {compose} from '@avocado/core';
import {StateProperty, Trait} from '@avocado/entity';
const decorate = compose(
StateProperty('informSize'),
);
class InformedBase extends Trait {
static defaultState() {
return {
informSize: [640, 360],
};
}
initialize() {
this._sentSelf = false;
this._socket = undefined;
this.lastNearby = I.Set();
}
destroy() {
if (this._socket) {
delete this._socket.entity;
delete this._socket;
}
}
createIndexedReducer() {
let previous = {};
return (diff, indexed) => {
const reducedDiff = {};
const current = {};
for (const index in indexed) {
const item = indexed[index];
current[index] = item;
// Diff.
if (previous[index]) {
if (diff[index]) {
reducedDiff[index] = diff[index];
}
}
// Added.
else {
reducedDiff[index] = item.state.toJS();
}
}
// Removed.
for (const index in previous) {
if (!current[index]) {
reducedDiff[index] = false;
}
}
previous = current;
return reducedDiff;
};
}
get socket() {
return this._socket;
}
set socket(socket) {
socket.entity = this.entity;
this._socket = socket;
}
methods() {
const entityReducer = this.createIndexedReducer();
const layerReducer = this.createIndexedReducer();
return {
inform: (diff) => {
// Remove dead updates.
if (0 === Object.keys(diff).length) {
return;
}
if (!this._sentSelf) {
diff.selfEntity = this.entity.instanceUuid;
this._sentSelf = true;
}
this._socket.send({
type: 'state-update',
payload: diff,
});
},
reduceStateDiff: (diff) => {
diff.room = diff.room || {};
diff.room.layers = diff.room.layers || {};
// Index layers.
const room = this.entity.room;
const indexedLayers = {};
for (const {index, layer} of room.layers) {
indexedLayers[index] = layer;
}
// Reduce layers.
diff.room.layers = layerReducer(
diff.room.layers,
indexedLayers,
);
for (const index in diff.room.layers) {
// Index entities.
const layer = room.layer(index);
const visibleEntities = layer.visibleEntities(
[0, 0, 640, 360]
);
const indexedEntities = {};
for (const entity of visibleEntities) {
indexedEntities[entity.instanceUuid] = entity;
}
// Reduce entities.
diff.room.layers[index].entityList = entityReducer(
diff.room.layers[index].entityList || {},
indexedEntities,
);
}
return diff;
},
};
}
}
export class Informed extends decorate(InformedBase) {}