// setVerbSubscription.js
(function () {
/*global adventurejs A*/
"use strict";
var p = adventurejs.Asset.prototype;
/**
* <strong>setVerbSubscription</strong> constructs verb subscriptions
* at asset.dov / asset.iov. It's intended mostly
* as a private function, though it is available to authors.
* An early version takes a string with separate params object.
* A later version takes an object that includes the verb name
* as an object key and params as value.
* // valid (for now) early version
* this.setIOV('hold',{with_params:{max_connections:2}});
* // valid later version with one verb
* this.setIOV( { hold: { with_params: { max_connections:2 } } } );
* // valid later version with multiple verbs
* this.setIOVs([
* { hold: { with_params: { max_connections:3 } } },
* { smell: true },
* ]);
* @memberOf adventurejs.Asset
* @method adventurejs.Asset#setVerbSubscription
* @param {String} object_of
* @param {String|Object} verb An early version takes a string,
* with separate params object. A later version takes an object
* that includes the verb name as an object key and params as value.
* @param {Object} params An optional param that works with the
* earlier version.
* @todo phase out earlier version
*/
p.setVerbSubscription = function Asset_setObjectOfVerb(object_of, verb) {
if (!object_of) return; // no object type
let params;
// does verb look like this: { verb: {} }
if ("object" === typeof verb) {
params = verb[Object.keys(verb)[0]];
verb = Object.keys(verb)[0];
}
if (!verb || !this.game.dictionary.verbs[verb]) return; // no verb
// we allow this shortcut {dov:{verb:true}}
// did author use shortcut to enable verb subscription?
if (params === true) {
params = { enabled: true, with_nothing: true }; // we accept a bool
}
if (params === false) {
params = { enabled: false };
}
// no other accepted form of params received?
if ("object" !== typeof params) {
params = { enabled: true, with_nothing: true };
}
if ("undefined" === typeof params.enabled) {
params.enabled = true;
}
// if verb setting exists and params include nothing new, we're done
if (this[object_of][verb] && !Object.keys(params).length) {
return this[object_of][verb];
}
// is asset not already subscribed to verb?
if (!this[object_of][verb]) {
this[object_of][verb] = new adventurejs.VerbSubscription(
verb,
this.game_name,
this.id
);
// set constructor name which gives us a way to find inheritance
// @TODO this doesn't work the way I expected it to
// need to loop through __proto__ to find which ancestor
// this prop initiated from, but as verb subscriptions are set in
// asset constructors, they're not available from here - rethink this
this[object_of][verb].inherited_from = this.constructor.name;
// save the verb name back to the verb subscription
this[object_of][verb].name = verb;
// copy verb.with_params
// IMPORTANT: use JSON.parse(JSON.stringify(with_params))
this[object_of][verb].with_params = JSON.parse(
JSON.stringify(this.game.dictionary.verbs[verb].with_params)
);
}
// if params include nothing new, we're done
if (!Object.keys(params).length) {
return this[object_of][verb];
}
// apply params from asset class or game file
// which may include with_params and is therefore deep
this[object_of][verb] = A.deepSet.call(
this.game,
params,
this[object_of][verb]
);
// did author set a string for with_assets? we'll allow it
if ("string" === typeof this[object_of][verb].with_assets) {
this[object_of][verb].with_assets = [this[object_of][verb].with_assets];
}
if (this[object_of][verb].with_assets.length) {
for (var i = 0; i < this[object_of][verb].with_assets.length; i++) {
// author probably used names - set to ids
this[object_of][verb].with_assets[i] = A.serialize(
this[object_of][verb].with_assets[i]
);
// we want to validate these asset name/ids,
// but at this point paired assets may not yet have been created
}
// was automatically setting with_nothing/anything
// but maybe should leave that for author to explicitly set
object_of === "dov"
? (this[object_of][verb].with_nothing = false)
: (this[object_of][verb].with_anything = false);
}
// did author set a string for with_classes? we'll allow it
if ("string" === typeof this[object_of][verb].with_classes) {
this[object_of][verb].with_classes = [this[object_of][verb].with_classes];
}
if (this[object_of][verb].with_classes.length) {
for (var i = this[object_of][verb].with_classes.length - 1; i >= 0; i--) {
// validate classes
var klass = this[object_of][verb].with_classes[i];
if (!adventurejs[klass]) {
var msg = `${this.id}.${object_of}.${verb}.with_classes.${klass}: ${klass} isn't recognized as an adventurejs class and was removed. `;
this.game.log("warn", 0, msg, "Asset");
this[object_of][verb].with_classes.splice(i);
}
}
object_of === "dov"
? (this[object_of][verb].with_nothing = false)
: (this[object_of][verb].with_anything = false);
}
// if no supporting assets, set anything/nothing to true?
if (
!this[object_of][verb].with_assets.length &&
!this[object_of][verb].with_classes.length
) {
//this[object_of][verb].with_anything = true;
//this[object_of][verb].with_nothing = true;
}
return this[object_of][verb];
};
})();