import {compose, merge} from '@avocado/core'; import {Vector} from '@avocado/math'; import {StateProperty, Trait} from '../trait'; import {Entity} from '..'; const decorate = compose( StateProperty('isSpawning', { track: true, }), StateProperty('maxSpawns'), ); export class Spawner extends decorate(Trait) { static defaultParams() { return { spawns: {}, }; } static defaultState() { return { isSpawning: true, maxSpawns: Infinity, }; } static type() { return 'spawner'; } destroy() { this.children = []; } constructor(entity, params, state) { super(entity, params, state); this.children = []; this.spawnJSONs = this.params.spawns; } destinationEntityList() { if ( this.entity.is('listed') && this.entity.list ) { return this.entity.list; } if ( this.entity.wielder && this.entity.wielder.is('listed') && this.entity.wielder.list ) { return this.entity.wielder.list; } } listeners() { return { dying: () => { this.isSpawning = false; }, }; } methods() { return { killAllChildren: () => { for (let i = 0; i < this.children.length; i++) { this.children[i].destroyGently(); } }, spawn: (key, json = {}) => { if (this.maxSpawns <= this.children.length) { return; } const spawnJSON = this.spawnJSONs[key]; if (!spawnJSON) { return; } const list = this.destinationEntityList(); if (!list) { return; } const mergedJSON = merge({}, spawnJSON, json); // Add null to children to prevent race. const childIndex = this.children.length; this.children.push(null); return Entity.loadOrInstance(mergedJSON).then((spawn) => { this.children[childIndex] = spawn; spawn.once('destroy', () => { const index = this.children.indexOf(spawn); this.children.splice(index, 1); }) list.addEntity(spawn); return spawn; }); }, spawnAt: (key, position, json = {}) => { if (this.maxSpawns <= this.children.length) { return; } if (!json.traits) { json.traits = {}; } if (!json.traits.positioned) { json.traits.positioned = {}; } if (!json.traits.positioned.state) { json.traits.positioned.state = {}; } json.traits.positioned.state.x = position[0] << 2; json.traits.positioned.state.y = position[1] << 2; return this.entity.spawn(key, json); }, }; } }