// Atom.js
(function () {
/*global adventurejs A*/
"use strict";
/**
* @class adventurejs.Atom
* @ajsinternal
* @ajsnavheading FrameworkReference
* @param {String} game_name A reference back to the top level
* game object, by way of window[game_name]. Done this way
* rather than using an object reference in order to avoid circular
* references, because they're difficult to parse into JSON, the
* method that's used for saving/restoring game data.
* @param {String} name The name of the object in the game world,
* ie "brass lantern". The name is also used to create the object's
* <a href="#id">id</a> by means of removing periods and spaces and
* converting to lowercase.
* @summary Experimental class made with Javascript ES6 class keyword.
* @classdesc
* <strong>Atom</strong> is a bedrock class that is used as the
* prime ancestor for all in-game classes. It defines several
* important base properties including <a href="#name">name</a>,
* <a href="#class">class</a>, <a href="#id">id</a>,
* and the <a href="#set">set</a> method.
* Authors should not need to instantiate or subclass Atom.
* Start with the {@link adventurejs.Tangible|Tangible} class
* to create new physical Assets, or the
* {@link adventurejs.Intangible|Intangible} class to create
* new abstract Assets.
*/
class Atom {
constructor(name, game_name) {
/**
* game_name stores the name of
* the current game instance as scoped to window.
* (By default, we use "MyGame", but you can use
* any name.) In order
* to refer to the game object, we use window[this.game_name].
* We store a string instead of the object itself in order to
* avoid problems caused by circular references during
* JSON encoding, which is used extensively for managing game
* state and saved games.
* @alias game_name
* @type {string}
* @memberof adventurejs.Atom
*/
this.game_name = game_name;
/**
* Class identifier to be provided in the asset definition.
* All game objects start as generic objects that get passed to
* {@link adventurejs.Game#createAsset|createAsset},
* which uses an object's class field to specify
* a class constructor.
* @alias class
* @type {string}
* @memberof adventurejs.Atom
*/
this.class = "Atom";
// Name should only be undefined when restoring from JSON.
if ("undefined" !== typeof name) {
/**
* Class identifier to be provided in the asset definition.
* All game objects start as generic objects that get passed to
* {@link adventurejs.Game#createAsset|createAsset},
* which uses an object's class field to specify
* a class constructor.
* @alias name
* @type {string}
* @memberof adventurejs.Atom
*/
this.name = name;
if (this.name) {
/**
* A unique ID for the game asset, based on the object name
* provided in the asset definition.
* @alias id
* @type {string}
* @memberof adventurejs.Atom
*/
this.id = A.serialize(name);
}
/**
* A unique numerical ID for the game asset. Currently unused but
* included as a potential alternative to id.
* @alias UID
* @type {string}
* @memberof adventurejs.Atom
*/
this.UID = adventurejs.UID.get();
}
}
/**
* Name returns the name of the class instance
* with the first character uppercased.
* @var {String} adventurejs.Atom#Name
*/
get Name() {
return A.propercase(this.name);
}
get self() {
return this;
}
/**
* Returns the top level game object. Use <code class="property">this.game</code>.
* @var {Getter} adventurejs.Atom#game
* @returns {adventurejs.Game}
*/
get game() {
return window[this.game_name] || false;
}
/**
* Provides a chainable shortcut method for setting a number of properties on the instance.
* @method adventurejs.Atom#set
* @memberOf adventurejs.Atom
* @param {Object} props A generic object containing properties to copy to the Object instance.
* @returns {Object} Returns the instance the method is called on (useful for chaining calls.)
* @chainable
*/
set(props) {
return A.deepSet.call(this.game, props, this);
}
/**
* A method to test whether the Atom is an instance of a given class.
* @method adventurejs.Atom#hasClass
* @memberOf adventurejs.Atom
* @param {String} prop Name of the class to test for.
* @returns {Boolean}
*/
hasClass(classname) {
if (!classname || "string" !== typeof classname) return false;
if (!adventurejs[classname]) {
// classes have leading capitalization so we'll make an effort
// to see if that's the problem
classname = A.propercase(classname);
}
if (!adventurejs[classname]) {
return false;
}
return this instanceof adventurejs[classname];
}
/**
* <strong>getInheritance</strong> is a utility method to get
* an asset's inheritance chain. Returns a list of class names
* from high to low.
* @method adventurejs.Atom#getInheritance
* @memberOf adventurejs.Atom
* @returns {Array}
*/
getInheritance() {
var proto = ".__proto__";
var chain = "this" + proto;
var classlist = [];
var classname;
while (classname !== "Atom") {
classname = eval(chain).constructor.name;
classlist.push(classname);
chain += proto;
}
return classlist;
}
}
adventurejs.Atom = Atom;
})();