import * as I from 'immutable'; import {arrayUnique, compose, EventEmitter, flatten} from '@avocado/core'; import {Layer} from './layer'; import {LayersUpdateLayerPacket} from './packets/layers-update-layer.packet'; const decorate = compose( EventEmitter, ); 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 { index: i, layer: this.layers[i], }; } } acceptPacket(packet) { if (packet instanceof LayersUpdateLayerPacket) { for (let i = 0; i < packet.data.length; i++) { const {layerIndex, layerPackets} = packet.data[i]; for (let j = 0; j < layerPackets.length; j++) { this.layers[layerIndex].acceptPacket(layerPackets[j]); } } } } 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; } cleanPackets() { for (let i = 0; i < this.layers.length; i++) { this.layers[i].cleanPackets(); } } 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); } packets(informed) { const packets = []; const updates = []; for (let i = 0; i < this.layers.length; i++) { const layerPackets = this.layers[i].packets(informed); if (0 === layerPackets.length) { continue; } updates.push({ layerIndex: i, layerPackets, }); } if (updates.length > 0) { packets.push(new LayersUpdateLayerPacket(updates)); } 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); } } toJSON() { return this.layers.map((layer) => layer.toJSON()); } toNetwork(informed) { return this.layers.map((layer) => layer.toNetwork(informed)); } 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; } }