//-----------------------------------------------------------------------------
// PluginManager
//
// The static class that manages the plugins.
/**
* The static class that manages plugins in the game
*
* @namespace
*/
function PluginManager() {
throw new Error("This is a static class");
}
PluginManager._scripts = [];
PluginManager._errorUrls = [];
PluginManager._parameters = {};
PluginManager._commands = {};
/**
* Sets up all plugins
*
* @static
* @param {Array} plugins - array of plugin objects including name, status, and parameters
*/
PluginManager.setup = function(plugins) {
for (const plugin of plugins) {
const pluginName = Utils.extractFileName(plugin.name);
if (plugin.status && !this._scripts.includes(pluginName)) {
this.setParameters(pluginName, plugin.parameters);
this.loadScript(plugin.name);
this._scripts.push(pluginName);
}
}
};
/**
* Gets the parameters of a given plugin
*
* @static
* @param {string} name - The name of the plugin
*/
PluginManager.parameters = function(name) {
return this._parameters[name.toLowerCase()] || {};
};
/**
* Sets the parameters of a given plugin
*
* @static
* @param {string} name - The name of the plugin
* @param {Object} parameters - The parameters of the plugin
*/
PluginManager.setParameters = function(name, parameters) {
this._parameters[name.toLowerCase()] = parameters;
};
/**
* Appends the plugin script file to the html game page
*
* @static
* @param {string} filename - The plugin filename
*/
PluginManager.loadScript = function(filename) {
const url = this.makeUrl(filename);
const script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
script.async = false;
script.defer = true;
script.onerror = this.onError.bind(this);
script._url = url;
document.body.appendChild(script);
};
/**
* Adds an error to the error stack if there was a problem loading a plugin
*
* @static
* @param {Error} e - The returned error
*/
PluginManager.onError = function(e) {
this._errorUrls.push(e.target._url);
};
/**
* Returns the full url of the plugin file including folder + filename + extension
*
* @static
* @param {Error} filename - The filename of the plugin with no extension
* @return {string} The full url of the plugin file including folder + filename + extension
*/
PluginManager.makeUrl = function(filename) {
return "js/plugins/" + Utils.encodeURI(filename) + ".js";
};
/**
* Checks if any errors were encountered while loading plugins
*
* @static
*/
PluginManager.checkErrors = function() {
const url = this._errorUrls.shift();
if (url) {
this.throwLoadError(url);
}
};
/**
* Throws an error if a plugin failed to load
*
* @static
* @throws Failed to load error
*/
PluginManager.throwLoadError = function(url) {
throw new Error("Failed to load: " + url);
};
/**
* Register a plugin command by plugin name, command name, and callback function
*
* @static
* @param {string} pluginName - The name of the plugin
* @param {string} commandName - The name of the plugin command
* @param {function} func - The callback function to call when plugin command is called
*/
PluginManager.registerCommand = function(pluginName, commandName, func) {
const key = pluginName + ":" + commandName;
this._commands[key] = func;
};
/**
* Calls a plugin command
*
* @static
* @param {context} self - The context passed to the function
* @param {string} pluginName - The name of the plugin
* @param {string} commandName - The name of the plugin command
* @param {Object} args - The various arguments passed to the callback function
*/
PluginManager.callCommand = function(self, pluginName, commandName, args) {
const key = pluginName + ":" + commandName;
const func = this._commands[key];
if (typeof func === "function") {
func.bind(self)(args);
}
};