maniajs
Version:
ManiaPlanet (Dedicated) Server Controller.
289 lines (227 loc) • 8.63 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _fs = require('fs');
var fs = _interopRequireWildcard(_fs);
var _path = require('path');
var path = _interopRequireWildcard(_path);
var _glob = require('glob');
var glob = _interopRequireWildcard(_glob);
var _async = require('async');
var async = _interopRequireWildcard(_async);
var _dependencyGraph = require('dependency-graph');
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Plugin class.
* @class PluginManager
* @type {PluginManager}
*/
var PluginManager = function () {
/**
* Construct plugin manager.
*
* @param {App} app
*/
function PluginManager(app) {
_classCallCheck(this, PluginManager);
this.app = app;
this.graph = new _dependencyGraph.DepGraph();
// ObjectArray
this.plugins = {};
// Array of plugin ids in order for starting.
this.order = [];
}
/**
* Load all plugins in order of requirements/dependencies.
*
* @returns {Promise}
*/
_createClass(PluginManager, [{
key: 'loadPlugins',
value: function loadPlugins() {
var _this = this;
this.app.log.debug("Loading plugins from configuration...");
return new Promise(function (resolve, reject) {
// Get all plugin info's first
var plugins = _this.app.config.plugins && _this.app.config.plugins !== null ? _this.app.config.plugins : [];
var pluginIds = Object.keys(plugins);
// Init plugins.
pluginIds.forEach(function (pluginId) {
_this.app.log.debug("Loading plugin '" + pluginId + "'...");
// Import plugin.
try {
// Plugin config.
var config = _this.app.config.plugins[pluginId];
// Load plugin (require).
var PluginClass = require(pluginId).default;
// Save plugin details to plugin array.
_this.plugins[pluginId] = new PluginClass();
// Is Plugin suited for the Game (trackmania/shootmania)
if (_this.plugins[pluginId].hasOwnProperty('game') && _this.plugins[pluginId].game.hasOwnProperty('games')) {
if (_this.plugins[pluginId].game.games.indexOf(_this.app.serverFacade.client.gameName) > -1 || _this.plugins[pluginId].game.games.length === 0) {
// All Right! Let's continue.
} else {
// Don't load! Unload from local properties, throw warning.
delete _this.plugins[pluginId];
_this.app.log.warn('Plugin \'' + pluginId + '\' is not suited for the current game! Plugin unloaded!');
return; // Stop current loop.
}
}
// Inject App, options and child logger.
_this.plugins[pluginId].inject(_this.app, config, _this.app.log.child({ plugin: pluginId }));
// Register node
_this.graph.addNode(pluginId);
} catch (err) {
return reject(err);
}
});
// Set plugins to app plugins.
_this.app.plugins = _this.plugins;
return resolve();
});
}
/**
* Call on MapBegin, will check against current game mode.
* Will also disable plugins when not compatible with game mode.
*/
}, {
key: 'begin',
value: function begin() {
var _this2 = this;
return new Promise(function (resolve, reject) {
Object.keys(_this2.plugins).forEach(function (pluginId) {
var plugin = _this2.plugins[pluginId];
if (plugin.hasOwnProperty('game') && plugin.game.hasOwnProperty('modes') && plugin.game.modes.length > 0) {
if (plugin.game.modes.indexOf(_this2.app.serverFacade.client.currentMode()) > -1) {
// All OK!
} else {
// Stop!
// TODO: Stop plugin.
}
}
});
return resolve();
});
}
/**
* Start all plugins, this will first determinate the start order, then ask the plugins to init, async and in order.
*
* @return {Promise}
*/
}, {
key: 'startPlugins',
value: function startPlugins() {
var self = this;
this.app.log.debug("Starting all plugins... Determinate order...");
// Determinate order.
try {
this.determinateOrder();
} catch (err) {
return Promise.reject(err);
}
this.app.log.debug("Starting all plugins... Calling init...");
return new Promise(function (resolve, reject) {
async.eachSeries(self.order, function (id, callback) {
self.plugins[id].init().then(function () {
callback();
}).catch(function (err) {
callback(err);
});
}, function (err) {
if (err) {
return reject(err);
}
return resolve();
});
});
}
/**
* Determinate start order.
*/
}, {
key: 'determinateOrder',
value: function determinateOrder() {
var ids = Object.keys(this.plugins);
// Loop and register dependencies to nodes.
for (var i = 0; i < ids.length; i++) {
var id = ids[i];
var plugin = this.plugins[id];
if (plugin.hasOwnProperty('dependencies')) {
var dependencies = plugin.dependencies;
if (dependencies.length > 0) {
// Parse, add node and go on.
this.graph.addDependency(plugin);
}
}
}
this.order = this.graph.overallOrder();
}
/**
* Load all models from plugins.
*
* @param sequelize
*
* @returns {Promise}
*/
}, {
key: 'loadModels',
value: function loadModels(sequelize) {
var _this3 = this;
if (this.order.length === 0) {
this.determinateOrder();
}
this.order.forEach(function (id) {
if (_this3.plugins[id].directory) {
var modelDirectory = path.normalize(_this3.plugins[id].directory + '/models/');
try {
if (modelDirectory && fs.existsSync(modelDirectory)) {
var list = glob.sync(modelDirectory + '*.js');
if (list.length > 0) {
list.forEach(function (file) {
// Import sequelize model.
var model = sequelize.import(file);
// Set in the plugin.
if (!_this3.plugins[id].models) {
_this3.plugins[id].models = {};
}
_this3.plugins[id].models[model.name] = model;
// Set in the global models.
if (!_this3.app.models.hasOwnProperty(id)) {
_this3.app.models[id] = {};
}
_this3.app.models[id][model.name] = model;
});
}
}
} catch (err) {
_this3.app.log.warn('Warning, can\'t load models for plugin ' + id, err.stack);
}
}
});
}
/**
* Emit event on all plugins!
* Will be in the order calculated on dependencies.
*
* @param {string} event
* @param {object} params
* @param {object} options
*/
}, {
key: 'emitAll',
value: function emitAll(event, params, options) {
var _this4 = this;
params = params || {};
options = options || {};
// Always do it on the specific order we always use!
this.order.forEach(function (id) {
_this4.plugins[id].emit(event, params);
});
}
}]);
return PluginManager;
}();
exports.default = PluginManager;