2019-03-20 18:35:59 -05:00
|
|
|
import * as I from 'immutable';
|
2019-03-28 03:39:57 -05:00
|
|
|
import isPlainObject from 'is-plain-object';
|
2019-03-20 18:35:59 -05:00
|
|
|
|
2019-03-20 18:58:19 -05:00
|
|
|
import {compose} from '@avocado/core';
|
2019-04-05 11:59:14 -05:00
|
|
|
import {Trait} from '@avocado/entity';
|
2019-03-20 18:35:59 -05:00
|
|
|
|
2019-03-20 18:58:19 -05:00
|
|
|
const decorate = compose(
|
|
|
|
);
|
|
|
|
|
2019-04-05 11:59:14 -05:00
|
|
|
export class Informed extends decorate(Trait) {
|
2019-03-20 18:35:59 -05:00
|
|
|
|
|
|
|
initialize() {
|
2019-03-28 02:10:46 -05:00
|
|
|
this.entityReducer = this.createIndexedReducer();
|
2019-04-05 15:06:07 -05:00
|
|
|
this._informState = I.fromJS({
|
|
|
|
// Let the client know who they are.
|
|
|
|
selfEntity: this.entity.instanceUuid,
|
|
|
|
});
|
2019-03-20 23:01:48 -05:00
|
|
|
this._socket = undefined;
|
2019-03-20 18:35:59 -05:00
|
|
|
}
|
|
|
|
|
2019-03-20 23:22:54 -05:00
|
|
|
destroy() {
|
2019-03-21 01:32:59 -05:00
|
|
|
if (this._socket) {
|
|
|
|
delete this._socket.entity;
|
|
|
|
delete this._socket;
|
|
|
|
}
|
2019-03-20 23:22:54 -05:00
|
|
|
}
|
|
|
|
|
2019-03-28 03:39:57 -05:00
|
|
|
collapseStateDiff(diff) {
|
|
|
|
for (const index in diff) {
|
|
|
|
const value = diff[index];
|
|
|
|
if (isPlainObject(value)) {
|
|
|
|
if (!this.collapseStateDiff(value)) {
|
|
|
|
delete diff[index];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (0 === Object.keys(diff).length) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return diff;
|
|
|
|
}
|
|
|
|
|
2019-03-27 02:05:08 -05:00
|
|
|
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];
|
|
|
|
}
|
2019-03-20 18:58:19 -05:00
|
|
|
}
|
|
|
|
// Added.
|
2019-03-27 02:05:08 -05:00
|
|
|
else {
|
|
|
|
reducedDiff[index] = item.state.toJS();
|
|
|
|
}
|
2019-03-20 18:58:19 -05:00
|
|
|
}
|
2019-03-27 02:05:08 -05:00
|
|
|
// Removed.
|
|
|
|
for (const index in previous) {
|
|
|
|
if (!current[index]) {
|
|
|
|
reducedDiff[index] = false;
|
|
|
|
}
|
2019-03-20 18:58:19 -05:00
|
|
|
}
|
2019-03-27 02:05:08 -05:00
|
|
|
previous = current;
|
|
|
|
return reducedDiff;
|
2019-03-20 18:58:19 -05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-03-28 02:10:46 -05:00
|
|
|
reduceStateDiff(diff) {
|
2019-04-05 12:47:49 -05:00
|
|
|
if (diff && diff.room && diff.room.layers) {
|
|
|
|
const room = this.entity.room;
|
|
|
|
const camera = this.entity.camera;
|
|
|
|
for (const index in diff.room.layers) {
|
|
|
|
// Index entities.
|
|
|
|
const layer = room.layer(index);
|
|
|
|
const visibleEntities = layer.visibleEntities(
|
|
|
|
camera.rectangle
|
|
|
|
);
|
|
|
|
const indexedEntities = {};
|
|
|
|
for (const entity of visibleEntities) {
|
|
|
|
indexedEntities[entity.instanceUuid] = entity;
|
|
|
|
}
|
|
|
|
// Reduce entities.
|
|
|
|
diff.room.layers[index].entityList = this.entityReducer(
|
|
|
|
diff.room.layers[index].entityList || {},
|
|
|
|
indexedEntities,
|
|
|
|
);
|
2019-03-28 02:10:46 -05:00
|
|
|
}
|
|
|
|
}
|
2019-03-28 03:39:57 -05:00
|
|
|
return this.collapseStateDiff(diff);
|
2019-03-28 02:10:46 -05:00
|
|
|
}
|
|
|
|
|
2019-03-20 23:01:48 -05:00
|
|
|
get socket() {
|
|
|
|
return this._socket;
|
|
|
|
}
|
|
|
|
|
|
|
|
set socket(socket) {
|
2019-03-21 00:29:44 -05:00
|
|
|
socket.entity = this.entity;
|
2019-03-20 23:01:48 -05:00
|
|
|
this._socket = socket;
|
|
|
|
}
|
|
|
|
|
2019-03-20 18:35:59 -05:00
|
|
|
methods() {
|
|
|
|
return {
|
|
|
|
|
2019-03-28 02:10:46 -05:00
|
|
|
inform: (stateSynchronizer) => {
|
|
|
|
// Take diff.
|
|
|
|
let diff = stateSynchronizer.diff(this._informState);
|
|
|
|
this._informState = stateSynchronizer.state;
|
2019-04-05 12:47:49 -05:00
|
|
|
diff = this.reduceStateDiff(diff);
|
2019-03-28 02:10:46 -05:00
|
|
|
// Emit!
|
2019-04-05 12:47:49 -05:00
|
|
|
if (diff) {
|
|
|
|
this._socket.send({type: 'state-update', payload: diff});
|
|
|
|
}
|
2019-03-20 18:35:59 -05:00
|
|
|
},
|
|
|
|
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|