2019-03-17 23:45:48 -05:00
|
|
|
import * as I from 'immutable';
|
|
|
|
import mapValues from 'lodash.mapvalues';
|
|
|
|
|
2019-03-18 19:58:22 -05:00
|
|
|
import {compose} from '@avocado/core';
|
2019-03-20 18:35:19 -05:00
|
|
|
import {QuadTree} from '@avocado/math';
|
2019-03-18 19:58:22 -05:00
|
|
|
import {EventEmitter} from '@avocado/mixins';
|
|
|
|
|
2019-03-17 23:45:48 -05:00
|
|
|
import {create} from './index';
|
|
|
|
|
2019-03-18 19:58:22 -05:00
|
|
|
const decorate = compose(
|
|
|
|
EventEmitter,
|
|
|
|
);
|
|
|
|
|
|
|
|
class EntityListBase {
|
2019-03-17 23:45:48 -05:00
|
|
|
|
|
|
|
constructor() {
|
|
|
|
this.entities_PRIVATE = {};
|
2019-03-20 18:35:19 -05:00
|
|
|
this.quadTree_PRIVATE = new QuadTree();
|
|
|
|
this.quadTreeData_PRIVATE = {};
|
2019-03-17 23:45:48 -05:00
|
|
|
this.state_PRIVATE = I.Map();
|
|
|
|
this.uuidMap_PRIVATE = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
*[Symbol.iterator]() {
|
|
|
|
for (const uuid in this.entities_PRIVATE) {
|
|
|
|
const entity = this.entities_PRIVATE[uuid];
|
|
|
|
yield entity;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
acceptStateChange(change) {
|
|
|
|
for (const uuid in change) {
|
|
|
|
const localUuid = this.uuidMap_PRIVATE[uuid];
|
|
|
|
const entity = this.entities_PRIVATE[localUuid];
|
|
|
|
if (entity) {
|
|
|
|
if (false === change[uuid]) {
|
|
|
|
// Entity removed.
|
|
|
|
this.removeEntity(entity);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
entity.acceptStateChange(change[uuid]);
|
|
|
|
this.state_PRIVATE = this.state_PRIVATE.set(localUuid, entity.state());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2019-03-18 21:22:54 -05:00
|
|
|
// New entity. Create with change as traits.
|
|
|
|
const newEntity = create().fromJSON({
|
|
|
|
traits: change[uuid],
|
|
|
|
});
|
2019-03-17 23:45:48 -05:00
|
|
|
this.addEntity(newEntity);
|
|
|
|
this.uuidMap_PRIVATE[uuid] = newEntity.instanceUuid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
addEntity(entity) {
|
|
|
|
const uuid = entity.instanceUuid;
|
|
|
|
this.entities_PRIVATE[uuid] = entity;
|
|
|
|
this.state_PRIVATE = this.state_PRIVATE.set(uuid, entity.state());
|
|
|
|
entity.on('destroyed', () => {
|
|
|
|
this.removeEntity(entity);
|
|
|
|
});
|
2019-03-20 18:35:19 -05:00
|
|
|
entity.on('positionChanged', () => {
|
|
|
|
this.quadTree_PRIVATE.remove(this.quadTreePoint(entity));
|
|
|
|
this.quadTree_PRIVATE.add(this.recomputeQuadTreePoint(entity));
|
|
|
|
});
|
2019-03-18 19:58:22 -05:00
|
|
|
this.emit('entityAdded', entity);
|
2019-03-20 18:35:19 -05:00
|
|
|
this.quadTree_PRIVATE.add(this.recomputeQuadTreePoint(entity));
|
2019-03-17 23:45:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
entity(uuid) {
|
|
|
|
return this.entities_PRIVATE[uuid];
|
|
|
|
}
|
|
|
|
|
2019-03-20 18:35:19 -05:00
|
|
|
quadTreePoint(entity) {
|
|
|
|
return this.quadTreeData_PRIVATE[entity.instanceUuid];
|
|
|
|
}
|
|
|
|
|
|
|
|
recomputeQuadTreePoint(entity) {
|
|
|
|
const point = this.quadTreeData_PRIVATE[entity.instanceUuid] = [
|
|
|
|
entity.x,
|
|
|
|
entity.y,
|
|
|
|
entity,
|
|
|
|
];
|
|
|
|
return point;
|
|
|
|
}
|
|
|
|
|
2019-03-17 23:45:48 -05:00
|
|
|
recomputeState() {
|
|
|
|
for (const uuid in this.entities_PRIVATE) {
|
|
|
|
const entity = this.entities_PRIVATE[uuid];
|
|
|
|
this.state_PRIVATE = this.state_PRIVATE.set(uuid, entity.state());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
removeEntity(entity) {
|
|
|
|
const uuid = entity.instanceUuid;
|
|
|
|
delete this.entities_PRIVATE[uuid];
|
|
|
|
this.state_PRIVATE = this.state_PRIVATE.delete(uuid);
|
2019-03-18 19:58:22 -05:00
|
|
|
this.emit('entityRemoved', entity);
|
2019-03-17 23:45:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
state() {
|
|
|
|
return this.state_PRIVATE;
|
|
|
|
}
|
|
|
|
|
|
|
|
tick(elapsed) {
|
|
|
|
for (const uuid in this.entities_PRIVATE) {
|
|
|
|
const entity = this.entities_PRIVATE[uuid];
|
|
|
|
if ('tick' in entity) {
|
|
|
|
entity.tick(elapsed);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.recomputeState();
|
|
|
|
}
|
|
|
|
|
2019-03-20 18:35:19 -05:00
|
|
|
within(rectangle) {
|
|
|
|
return this.quadTree_PRIVATE.search(rectangle).map((node) => {
|
|
|
|
return node.data[2];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-03-17 23:45:48 -05:00
|
|
|
}
|
2019-03-18 19:58:22 -05:00
|
|
|
|
|
|
|
export class EntityList extends decorate(EntityListBase) {}
|