UNPKG

sam-ecs

Version:

A specialized entity component system

467 lines (390 loc) 14.2 kB
'use strict'; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } //Manager.js// /** * @description - Defines the manager class that manages the ECS * @author - Samuel Faulkner */ //node imports // const { SortedArraySet, FastSet } = require('collections'); var FastSet = require('collections/fast-set.js'), SortedSet = require('collections/sorted-array-set.js'); var EventEmitter = require('events'); //user imports var StateManager = require('./StateManager.js'); var ProcessorManager = require('./ProcessorManager.js'); var ActionManager = require('./ActionManager.js'); var EventManager = require('./EventManager.js'); var ComponentManager = require('./ComponentManager.js'); //constants var HASH_LENGTH = 8; var Manager = function () { function Manager() { _classCallCheck(this, Manager); this._stateManager = new StateManager(); this._actionManager = new ActionManager(); this._componentManager = new ComponentManager(this._stateManager); this._eventManager = new EventManager(this._actionManager); this._processorManager = new ProcessorManager(this._stateManager); this._currentTick = 0; } _createClass(Manager, [{ key: 'setMaxBufferSize', value: function setMaxBufferSize(value) { this._stateManager.setMaxBufferSize(value); this._actionManager.setMaxBufferSize(value); } }, { key: 'getStateManager', value: function getStateManager() { return this._stateManager; } }, { key: 'getEventManager', value: function getEventManager() { return this._eventManager; } }, { key: 'getComponentManager', value: function getComponentManager() { return this._componentManager; } }, { key: 'getActionManager', value: function getActionManager() { return this._actionManager; } }, { key: 'getProcessorManager', value: function getProcessorManager() { return this._processorManager; } /** * @description - Returns the entites object; essentially the state tree * @return {Object} - the entities object within this class */ }, { key: 'getEntities', value: function getEntities() { return this._stateManager.getEntities(); } /** * @description - Returns the state of an entity's specific component * @param {String} entity - the hash of the entity * @param {String} component - the specific component to retrieve * @returns {Object} the state object of the component */ }, { key: 'getEntityComponent', value: function getEntityComponent(entity, component) { return this._stateManager.getEntityComponent(entity, component); } /** * @description - Helper method to get retrieve data for a single entity * @param {String} hash - the hash value for the entity that is being * retrieved * @return {Object} - Entity's component state tree being retrieved */ }, { key: 'getEntityState', value: function getEntityState(hash) { return this._stateManager.getEntityState(hash); } /** * @description - Returns the the entity object itself from a given hash */ }, { key: 'getEntity', value: function getEntity(hash) { return this._stateManager.getEntity(hash); } /** * @description - Returns a single list depending on the parameter * @param {String} field - Denotes the specific component type to grab the * list of entities from, or if undefined returns the entire object * @return {Set} - the set of entities containing the given component */ }, { key: 'getEntitiesByComponent', value: function getEntitiesByComponent(field) { return this._stateManager.getEntitiesByComponent(field); } /** * @description - Returns a boolean to determine if there are any entities * that currently have the given component in the manager * @param {String} componentType - The type of component in question * @return {boolean} - Does the manager have an entity that has this * component? */ }, { key: 'hasComponent', value: function hasComponent(componentType) { return this._stateManager.hasComponent(componentType); } /** * @description - Adds an entity to the manager * @param {Entity} entity - Entity object to be added */ }, { key: 'addEntity', value: function addEntity(entity) { return this._stateManager.addEntity(entity); } /** * @description - Removes an entity from the manager * @param {Entity} entity - the entity to be removed */ }, { key: 'removeEntity', value: function removeEntity(entity) { return this._stateManager.removeEntity(entity); } /** * @description - Returns a list of reducer functions by action type * @param {String} actionType - type of action the reducer is triggered by * @return {Array} - list of reducers that are 'performed' by that action */ }, { key: 'getReducers', value: function getReducers(actionType) { return this._actionManager.getReducers(actionType); } /** * @description - Adds a reducer function to fire after an action is * dispatched of the given types * @param {Function} reducer - function to be fired * @param {Array} types - types of actions that this reducer is fired * once dispatched */ }, { key: 'addReducer', value: function addReducer(reducer, types) { return this._actionManager.addReducer(reducer, types); } /** * @description - Removes a reducer from the given types of actions * @param {Function} reducer - The function to be removed from the * given lists * @param {Array} types - denotes the lists to remove the reducer * from */ }, { key: 'removeReducer', value: function removeReducer(reducer, types) { return this._actionManager.removeReducer(reducer, types); } /** * @description - Dispatches an action to appropriate reducers * @param {Object} action - the action to dispatch */ }, { key: 'dispatch', value: function dispatch(action, unrolling) { this._actionManager.dispatch(action); if (this._dispatchFun) this._dispatchFun(action, unrolling); } /** * @description - Adds a processor. This processor is called every time * the manager calls update. Each processor is given the intersection of * entities that contain all the components the processor identifies * @param {Processor} processor - The processor to be added */ }, { key: 'addProcessor', value: function addProcessor(processor, addToOrder) { return this._processorManager.addProcessor(processor, addToOrder); } /** * @description - Removes the given processor from the '_processors' field * @param {Processor} processor - processor to be removed */ }, { key: 'removeProcessor', value: function removeProcessor(processor) { return this._processorManager.removeProcessor(processor); } /** * @description - Iterates through everything * defined by the processor */ }, { key: 'update', value: function update() { this._processorManager.update(); this._actionManager.update(this._stateManager, this._currentTick); this._stateManager.update(this._currentTick); this._eventManager.update(this._currentTick); } /** * @description - Updates a single processor * @param {String} processorName - the name of the processor to update */ }, { key: 'updateProcessor', value: function updateProcessor(processorName) { this._processorManager.updateProcessor(processorName); } /** * @description - Allows entities to be sorted in the * cached list that is given to a processor * @param {Function} sorter - comparator function for the sorting. * should take in firstObject, secondObject, and the state manager * @param {String} processorName - the name of the processor * to be sorted */ }, { key: 'addSorterForProcessorList', value: function addSorterForProcessorList(sorter, processorName) { return this._processorManager.addSorterForProcessor(sorter, processorName); } /** * @description - Adds a listener to be called when an event * is thrown * @param {String} eventType - denotes the type of event * @param {Function} fun - the function that will be called * after the event will be removed */ }, { key: 'addListener', value: function addListener(eventType, fun) { this._eventManager.addListener(eventType, fun); } /** * @description - Removes a listener that was previously added * @param {String} eventType - denotes the type of the event * @param {Function} fun - the listener to be removed */ }, { key: 'removeListener', value: function removeListener(eventType, fun) { this._eventManager.removeListener(eventType, fun); } /** * @description - Emits an event with the given argument * @param {String} eventType - denotes the type of event to be * emitted * @param {Object} arg - the argument that will be passed to the * event handler * @return {Bool} - Returns whether there were any listeners * for the supplied event type or not */ }, { key: 'emit', value: function emit(eventType, arg) { if (this._emitFun) { this._emitFun(Object.assign({}, arg, { 'type': eventType })); } this._eventManager.emit(eventType, arg); } /** * @description - Adds a component to the manager, allowing entities * to contain this component * @param {String} name - the name of the component * @param {Function} generatorFunction - the return value of this function * will be given to an entity whenever they request this component */ }, { key: 'addComponentToLibrary', value: function addComponentToLibrary(name, generatorFunction) { return this._componentManager.addComponentToLibrary(name, generatorFunction); } /** * @description - Removes a component that was previously added to the * manager. Does NOT remove all instances of the component from current * entities * @param {String} name - the name of the component to be removed from * the library */ }, { key: 'removeComponentFromLibrary', value: function removeComponentFromLibrary(name) { return this._componentManager.removeComponentFromLibrary(name); } /** * @description - Adds an entity and gives it the components listed * @param {Array} componentList - a list of component objects to give to * the entity. Each component object should have two fields: 'name': the * name of the component, 'args': which will be passed to the * generatorFunction that was given whenever the component was added to * the manager, along with the manager itself * @param {String} hashValue - optional paramter for a hashvalue to be * assigned to the entity rather than one being generated */ }, { key: 'addEntityFromComponents', value: function addEntityFromComponents(componentList, hashValue, subState) { var entity = this._componentManager.createEntityFromComponents(componentList, hashValue); return this._stateManager.addEntity(entity, subState); } /** * @description - This allows for the user to add a function * that will be called every time the dispatch function on * the manager function is invoked * @param {Function} fun - the function that will be called on * every dispatch */ }, { key: 'addDispatchSideEffect', value: function addDispatchSideEffect(fun) { this._dispatchFun = fun; } /** * @description - removes the side effect functions from * {@link dispatch} */ }, { key: 'removeDispatchSideEffect', value: function removeDispatchSideEffect() { if (this._dispatchFun) delete this._dispatchFun; } /** * @description - Like {@link addDispatchSideEffect} this adds * a side effect for {@link emit} * @param {Function} function - function that will be called for * every emit */ }, { key: 'addEmitSideEffect', value: function addEmitSideEffect(fun) { this._emitFun = fun; } /** * @description - Removes the side effect from {@link addEmitSideEffect} */ }, { key: 'removeEmitSideEffect', value: function removeEmitSideEffect() { if (this._emitFun) delete this._emitFun; } /** * @description - Clears out any state from the manager */ }, { key: 'clear', value: function clear() { return this._stateManager.clear(); } /** * @description - Serializes the current state from the state * @param {String} subState - the substate to serialize * manager and returns it * @returns {Object} the state object */ }, { key: 'serializeState', value: function serializeState(subState) { return this._stateManager.serializeState(subState); } /** * @description - Returns the serialized state */ }, { key: 'toJSON', value: function toJSON() { return this._stateManager.getState(); } }]); return Manager; }(); module.exports = Manager;