var EventEmitter = require('./EventEmitter');
var BitSet = require('./BitSet');
/**
* Represents a Entity.
* Entity is a simple object that holds {@link Component}.
* @constructor
* @extends EventEmitter
* @param engine {Engine} - The Engine associated with this object.
*/
function Entity(engine) {
EventEmitter.call(this);
/**
* The ID of this object.
* This will be given by Engine, and it shouldn't be edited after
* being added to the Engine.
* Otherwise, You can edit the value to what you want.
* @var {Number}
*/
this.id = null;
/**
* The Engine associated with this object.
* @private
* @var {Engine}
*/
this._engine = engine;
/**
* The BitSet holding information about what kind of Component this has.
* @var {BitSet}
*/
this.componentBits = new BitSet();
/**
* The BitSet holding information about what ComponentGroup this matches.
* @var {BitSet}
*/
this.componentGroupBits = new BitSet();
/**
* The key-value storage of Components.
* @var {Object}
*/
this.components = {};
}
Entity.prototype = Object.create(EventEmitter.prototype);
Entity.prototype.constructor = Entity;
/**
* Adds the Component to the Entity.
* @param key {String} - The key of the Component.
* @param component {Component} - The Component to add.
* @fires Entity#componentAdded
*/
Entity.prototype.add = function(key, component) {
var bitPos = this._engine.getComponentBit(key);
this.componentBits.set(bitPos, true);
this.components[bitPos] = component;
/**
* This event is fired when a Component is added to the Entity.
* @event Entity#componentAdded
* @property {Entity} 0 - the Entity.
* @property {String} 1 - the Component key added to Entity.
* @property {Component} 2 - the Component added to Entity.
*/
this.emit('componentAdded', this, key, component);
}
/**
* Creates new Component with the args and adds to the Entity.
* @param key {String} - The key of the Component.
* @param args {Object} - A key-value storage to create the Component.
* @return {Entity} the Entity to allow chains.
*/
Entity.prototype.create = function(key, args) {
var constructor = this._engine.getComponentConstructor(key);
var component = new constructor(args);
this.add(key, component);
return this;
}
/**
* Executes Component related functions by its arguments.
*
* If only a key is provided, it returns the Component with that ID.
* Otherwise, it creates the Component with the options.
* @param {String} key - The Component's key
* @param {Object} args - The options
*/
Entity.prototype.c = function(key, args) {
if(args == null) return this.get(key);
return this.create(key, args);
}
/**
* Removes the Component from the Entity.
* @param key {String} - The key of the Component.
* @fires Entity#componentRemoved
*/
Entity.prototype.remove = function(key) {
var bitPos = this._engine.getComponentBit(key);
this.componentBits.set(bitPos, false);
var orig = this.components[bitPos];
delete this.components[bitPos];
/**
* This event is fired when a Component is removed from the Entity.
* @event Entity#componentRemoved
* @property {Entity} 0 - the Entity.
* @property {String} 1 - the Component key removed from the Entity.
*/
this.emit('componentRemoved', this, key);
}
/**
* Returns the Component which this Entity has.
* @param key {String} - The key of the Component.
* @returns {Component} The component.
*/
Entity.prototype.get = function(key) {
var bitPos = this._engine.getComponentBit(key);
return this.components[bitPos];
}
/**
* Checks whether if this Entity has the Component.
* @param key {String} - The key of the Component to check.
* @returns {Boolean} Whether if this Entity has the Component.
*/
Entity.prototype.has = function(key) {
var bitPos = this._engine.getComponentBit(key);
return this.componentBits.get(bitPos);
}
/**
* Serializes the Entity object.
* Components should be serializable in order to do this.
* @return {Object} serialized Entity object
*/
Entity.prototype.toJSON = function() {
var obj = {};
obj.id = this.id;
obj.components = {};
for(var key in this.components) {
var name = this._engine.getComponentName(key);
obj.components[name] = this.components[key];
if(this.components[key].toJSON) {
obj.components[name] = this.components[key].toJSON();
}
}
return obj;
}
Entity.prototype.serialize = Entity.prototype.toJSON;
/**
* Returns new deserialized Entity object.
* @param engine {Engine} the Engine object
* @param data {Object} serialized Entity object
* @return {Entity} the Entity object
*/
Entity.fromJSON = function(engine, data) {
var entity = new Entity(engine);
entity.id = data.id;
for(var name in data.components) {
entity.c(name, data.components[name]);
}
return entity;
}
Entity.deserialize = Entity.fromJSON;
if(typeof module !== 'undefined') {
module.exports = Entity;
}