Source: PluginManager.js

PluginManager.js

//-----------------------------------------------------------------------------
// 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);
    }
};