avocado-old/packages/entity/list/index.js

133 lines
3.1 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-07 11:43:50 -05:00
import {Synchronized} from '@avocado/state';
2019-04-16 16:40:20 -05:00
import {Entity} from '../index';
2019-03-17 23:45:48 -05:00
const decorate = compose(
EventEmitter,
2019-04-16 17:52:56 -05:00
Synchronized,
);
2019-04-16 17:52:56 -05:00
export class EntityList extends decorate(class {}) {
2019-03-17 23:45:48 -05:00
constructor() {
super();
2019-04-07 12:00:11 -05:00
this._entities = {};
this._quadTree = new QuadTree();
2019-04-07 12:00:11 -05:00
this._uuidMap = {};
2019-03-17 23:45:48 -05:00
}
*[Symbol.iterator]() {
2019-04-07 12:00:11 -05:00
for (const uuid in this._entities) {
const entity = this._entities[uuid];
2019-03-17 23:45:48 -05:00
yield entity;
}
}
addEntity(entity) {
const uuid = entity.instanceUuid;
2019-04-07 12:00:11 -05:00
this._entities[uuid] = entity;
2019-04-07 11:43:50 -05:00
this.state = this.state.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) {
2019-04-07 12:00:11 -05:00
if (this._uuidMap[uuid]) {
return this._entities[this._uuidMap[uuid]];
2019-03-27 17:36:57 -05:00
}
2019-04-07 12:00:11 -05:00
if (this._entities[uuid]) {
return this._entities[uuid];
2019-03-27 17:36:57 -05:00
}
2019-03-20 21:07:57 -05:00
}
2019-04-07 11:43:50 -05:00
patchStateStep(uuid, step) {
2019-04-07 12:00:11 -05:00
const localUuid = this._uuidMap[uuid];
const entity = this._entities[localUuid];
2019-04-07 11:43:50 -05:00
if (entity) {
2019-04-07 14:34:42 -05:00
if ('remove' === step.op) {
2019-04-07 11:43:50 -05:00
// Entity removed.
this.removeEntity(entity);
2019-04-05 15:16:55 -05:00
}
else {
2019-04-07 11:43:50 -05:00
// Exists; patch.
entity.patchState([step]);
2019-04-06 23:19:32 -05:00
}
}
2019-04-07 11:43:50 -05:00
else {
// New entity. Create with patch as traits.
2019-04-16 16:40:20 -05:00
const newEntity = (new Entity()).fromJSON({
2019-04-07 11:43:50 -05:00
traits: step.value,
});
2019-04-07 12:00:11 -05:00
this._uuidMap[uuid] = newEntity.instanceUuid;
2019-04-07 11:43:50 -05:00
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
removeEntity(entity) {
const uuid = entity.instanceUuid;
2019-04-07 12:00:11 -05:00
delete this._entities[uuid];
2019-04-07 11:43:50 -05:00
this.state = this.state.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
}
tick(elapsed) {
2019-04-07 12:00:11 -05:00
for (const uuid in this._entities) {
const entity = this._entities[uuid];
entity.tick(elapsed);
}
2019-04-12 13:18:34 -05:00
this.state = this.state.withMutations((state) => {
for (const uuid in this._entities) {
const entity = this._entities[uuid];
2019-04-16 23:44:03 -05:00
if (!entity.$$stateDirty) {
continue;
}
entity.$$stateDirty = false;
2019-04-12 13:18:34 -05:00
state.set(uuid, entity.state);
}
});
2019-03-17 23:45:48 -05:00
}
visibleEntities(query) {
2019-04-16 23:59:08 -05:00
const entities = [];
const quadTree = this._quadTree;
2019-04-16 23:59:08 -05:00
const nodes = quadTree.search(query);
for (let i = 0; i < nodes.length; ++i) {
const node = nodes[i];
const entity = node.data[2];
// Make sure they're actually in the query due to expanded AABB.
if (!Rectangle.intersects(query, entity.visibleBoundingBox)) {
continue;
}
entities.push(entity);
}
// Hitting multiple points for each entity can return duplicates.
return arrayUnique(entities);
}
2019-03-17 23:45:48 -05:00
}
2019-04-13 20:53:02 -05:00
export {EntityListView} from './view';