import * as I from 'immutable'; import {compose} from '@avocado/core'; import {EventEmitter, Property} from '@avocado/mixins'; import {Layers} from './layers'; const decorate = compose( EventEmitter, Property('world', { track: true, }), ); export class Room extends decorate(class {}) { constructor() { super(); this.layers = new Layers(); this._state = I.Map(); // Listeners. this.onEntityAddedToRoom = this.onEntityAddedToRoom.bind(this); this.onEntityRemovedFromRoom = this.onEntityRemovedFromRoom.bind(this); this.onWorldChanged = this.onWorldChanged.bind(this); this.layers.on('entityAdded', this.onEntityAddedToRoom); this.layers.on('entityRemoved', this.onEntityRemovedFromRoom); this.on('worldChanged', this.onWorldChanged); } acceptStateChange(change) { if (change.layers) { this.layers.acceptStateChange(change.layers); } } addEntityToLayer(entity, layerIndex = 0) { this.layers.addEntityToLayer(entity, layerIndex); } destroy() { this.layers.destroy(); this.layers.off('entityAdded', this.onEntityAddedToRoom); this.layers.off('entityRemoved', this.onEntityRemovedFromRoom); this.off('worldChanged', this.onWorldChanged); } findEntity(uuid) { return this.layers.findEntity(uuid); } fromJSON(json) { if (json.layers) { this.layers.fromJSON(json.layers); } return this; } layer(index) { return this.layers.layer(index); } onEntityAddedToRoom(entity) { entity.addTrait('roomed'); entity.room = this; this.emit('entityAdded', entity) } onEntityRemovedFromRoom(entity) { if (entity.is('roomed')) { entity.removeTrait('roomed'); } this.emit('entityRemoved', entity); } onWorldChanged() { for (const {layer} of this.layers) { for (const entity of layer.entityList) { if (entity.is('physical')) { entity.world = this.world; } } } } removeEntityFromLayer(entity, layerIndex = 0) { this.layers.removeEntityFromLayer(entity, layerIndex); } get state() { return this._state; } tick(elapsed) { this.layers.tick(elapsed); this._state = this._state.set('layers', this.layers.state); if (this.world) { this.world.tick(elapsed); } } }