import * as I from 'immutable'; import {arrayUnique, compose, EventEmitter, flatten} from '@avocado/core'; import {EntityCreatePacket} from '@avocado/entity'; import {Synchronized} from '@avocado/state'; import {Layer} from './layer'; import {LayerCreatePacket} from './packets/layer-create.packet'; import {TileUpdatePacket} from './packets/tile-update.packet'; const decorate = compose( EventEmitter, Synchronized, ); export class Layers extends decorate(class {}) { constructor(json) { super(); this.layers = []; if ('undefined' !== typeof json) { this.fromJSON(json); } } *[Symbol.iterator]() { for (let i = 0; i < this.layers.length; i++) { yield this.layers[i]; } } acceptPacket(packet) { if (packet instanceof LayerCreatePacket) { this.addLayer(new Layer(packet.data)); } if (packet instanceof TileUpdatePacket) { this.layers[packet.data.layer].acceptPacket(packet); } if (packet instanceof EntityCreatePacket) { this.layers[packet.data.layer].acceptPacket(packet); } } addEntityToLayer(entity, layerIndex) { const layer = this.layers[layerIndex]; if (!layer) { return; } layer.addEntity(entity); } addLayer(layer) { layer.on('entityAdded', this.onEntityAddedToLayers, this); layer.on('entityRemoved', this.onEntityRemovedFromLayers, this); this.layers.push(layer); layer.index = this.layers.length - 1; this.emit('layerAdded', layer); } allEntities() { let allEntities = []; for (let i = 0; i < this.layers.length; i++) { const layerEntities = this.layers[i].allEntities(); for (let j = 0; j < layerEntities.length; j++) { allEntities.push(layerEntities[j]); } } return allEntities; } destroy() { for (let i = 0; i < this.layers.length; i++) { const layer = this.layers[i]; this.removeLayer(layer); layer.destroy(); } } findEntity(uuid) { for (let i = 0; i < this.layers.length; i++) { const foundEntity = this.layers[i].findEntity(uuid); if (foundEntity) { return foundEntity; } } } fromJSON(json) { for (let i = 0; i < json.length; i++) { this.addLayer(new Layer(json[i])); } return this; } layer(index) { return this.layers[index]; } onEntityAddedToLayers(entity) { this.emit('entityAdded', entity); } onEntityRemovedFromLayers(entity) { this.emit('entityRemoved', entity); } packetsForUpdate(force = false) { const packets = []; for (let i = 0; i < this.layers.length; i++) { const layerPacketsForUpdate = this.layers[i].packetsForUpdate(force); for (let j = 0; j < layerPacketsForUpdate.length; j++) { packets.push(layerPacketsForUpdate[j]); } } return packets; } removeEntityFromLayer(entity, layerIndex) { const layer = this.layers[layerIndex]; if (!layer) { return; } layer.removeEntity(entity); } // TODO: fix index for remaining layers removeLayer(layer) { const index = this.layers.indexOf(layer); if (-1 === index) { return; } layer.off('entityAdded', this.onEntityAddedToLayers); layer.off('entityRemoved', this.onEntityRemovedFromLayers); this.layers.splice(index, 1); this.emit('layerRemoved', layer); } tick(elapsed) { for (let i = 0; i < this.layers.length; i++) { this.layers[i].tick(elapsed); } } visibleEntities(query) { const entities = []; for (let i = 0; i < this.layers.length; i++) { const layerVisibleEntities = this.layers[i].visibleEntities(query); for (let j = 0; j < layerVisibleEntities.length; j++) { const layerVisibleEntity = layerVisibleEntities[j]; entities.push(layerVisibleEntity); } } return entities; } }