avocado-old/packages/entity/list.js

163 lines
4.2 KiB
JavaScript
Raw Normal View History

2019-03-17 23:45:48 -05:00
import * as I from 'immutable';
import mapValues from 'lodash.mapvalues';
import {arrayUnique, compose} from '@avocado/core';
import {QuadTree, Rectangle, Vector} from '@avocado/math';
import {EventEmitter} from '@avocado/mixins';
2019-04-05 22:14:29 -05:00
import {StateSynchronizer} from '@avocado/state';
2019-03-17 23:45:48 -05:00
import {create} from './index';
const decorate = compose(
EventEmitter,
);
export class EntityList extends decorate(class {}) {
2019-03-17 23:45:48 -05:00
constructor() {
super();
2019-03-17 23:45:48 -05:00
this.entities_PRIVATE = {};
this._quadTree = new QuadTree();
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;
}
}
addEntity(entity) {
const uuid = entity.instanceUuid;
this.entities_PRIVATE[uuid] = entity;
2019-03-27 01:02:16 -05:00
this.state_PRIVATE = this.state_PRIVATE.set(uuid, entity.state);
2019-03-21 00:36:06 -05:00
entity.addTrait('listed');
entity.list = this;
2019-03-21 00:09:17 -05:00
entity.once('destroyed', () => {
this.removeEntity(entity);
2019-03-20 18:35:19 -05:00
});
this.emit('entityAdded', entity);
2019-03-17 23:45:48 -05:00
}
2019-03-21 01:32:49 -05:00
destroy() {
for (const entity of this) {
entity.destroy();
}
}
2019-03-27 17:36:57 -05:00
findEntity(uuid) {
if (this.uuidMap_PRIVATE[uuid]) {
return this.entities_PRIVATE[this.uuidMap_PRIVATE[uuid]];
}
if (this.entities_PRIVATE[uuid]) {
return this.entities_PRIVATE[uuid];
}
2019-03-20 21:07:57 -05:00
}
2019-04-05 15:16:55 -05:00
patchState(patch) {
2019-04-05 22:14:29 -05:00
for (const step of patch) {
const {op, path, value} = step;
if ('/' === path) {
for (const uuid in value) {
const localUuid = this.uuidMap_PRIVATE[uuid];
const entity = this.entities_PRIVATE[localUuid];
if (entity) {
if (false === value[uuid]) {
// Entity removed.
this.removeEntity(entity);
}
else {
entity.patchState([
{
op: 'replace',
path: '/',
value: value[uuid],
}
]);
this.state_PRIVATE = this.state_PRIVATE.set(localUuid, entity.state);
}
}
else {
// New entity. Create with patch as traits.
const newEntity = create().fromJSON({
traits: value[uuid],
});
this.uuidMap_PRIVATE[uuid] = newEntity.instanceUuid;
this.addEntity(newEntity);
}
2019-04-05 15:16:55 -05:00
}
}
else {
2019-04-05 22:14:29 -05:00
const [uuid, substep] = StateSynchronizer.forwardStep(step);
const localUuid = this.uuidMap_PRIVATE[uuid];
const entity = this.entities_PRIVATE[localUuid];
if (entity) {
if (false === substep.value[uuid]) {
// Entity removed.
this.removeEntity(entity);
}
else {
entity.patchState([substep]);
this.state_PRIVATE = this.state_PRIVATE.set(localUuid, entity.state);
}
}
else {
// New entity. Create with patch as traits.
const newEntity = create().fromJSON({
traits: substep.value[uuid],
});
this.uuidMap_PRIVATE[uuid] = newEntity.instanceUuid;
this.addEntity(newEntity);
}
2019-04-05 15:16:55 -05:00
}
}
}
get quadTree() {
return this._quadTree;
2019-03-20 18:35:19 -05:00
}
2019-03-17 23:45:48 -05:00
recomputeState() {
for (const uuid in this.entities_PRIVATE) {
const entity = this.entities_PRIVATE[uuid];
2019-03-27 01:02:16 -05:00
this.state_PRIVATE = this.state_PRIVATE.set(uuid, entity.state);
2019-03-17 23:45:48 -05:00
}
}
removeEntity(entity) {
const uuid = entity.instanceUuid;
delete this.entities_PRIVATE[uuid];
this.state_PRIVATE = this.state_PRIVATE.delete(uuid);
this.emit('entityRemoved', entity);
2019-03-23 18:49:19 -05:00
if (entity.is('listed')) {
2019-03-20 23:23:34 -05:00
entity.removeTrait('listed');
}
2019-03-17 23:45:48 -05:00
}
2019-03-26 15:41:49 -05:00
get state() {
2019-03-17 23:45:48 -05:00
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();
}
visibleEntities(query) {
const quadTree = this._quadTree;
const entities = quadTree.search(query).map((node) => {
return node.data[2];
});
// Hitting multiple points for each entity can return duplicates.
return arrayUnique(entities);
}
2019-03-17 23:45:48 -05:00
}