maniajs
Version:
ManiaPlanet (Dedicated) Server Controller.
405 lines (320 loc) • 12.7 kB
JavaScript
;
/**
* Client Manager - Will connect to the maniaplanet server
*/
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 _gbxremote = require('gbxremote');
var _gbxremote2 = _interopRequireDefault(_gbxremote);
var _events = require('events');
var _fs = require('fs');
var fs = _interopRequireWildcard(_fs);
var _callbackManager = require('./callback-manager');
var _callbackManager2 = _interopRequireDefault(_callbackManager);
var _commandManager = require('./command-manager');
var _commandManager2 = _interopRequireDefault(_commandManager);
var _send = require('./send');
var _send2 = _interopRequireDefault(_send);
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 _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
/**
* Server Client.
* @class ServerClient
* @type {ServerClient}
*
* @function {Send} send
*
* @property {object} game
* @property {object} game.CurrentGameInfos
* @property {number} game.CurrentGameInfos.GameMode
* @property {object] game.NextGameInfos
* @property {number} game.NextGameInfos.GameMode
*
* @property {{data:string,maps:string,skins:string}} paths Server Paths.
*/
var ServerClient = function (_EventEmitter) {
_inherits(ServerClient, _EventEmitter);
/**
* Prepare the client. parse configuration and pass it to the gbx client.
*
* @param {App} app context
*/
function ServerClient(app) {
_classCallCheck(this, ServerClient);
var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(ServerClient).call(this));
_this.setMaxListeners(0);
_this.app = app;
_this.gbx = null;
/** @type {CallbackManager} */
_this.callback = null;
/** @type {CommandManager} */
_this.command = null;
_this.server = app.config.server;
// Server properties
_this.titleId = null;
_this.version = null;
_this.build = null;
_this.apiVersion = null;
_this.login = null;
_this.name = null;
_this.comment = null;
_this.path = null;
_this.ip = null;
_this.ports = {};
_this.playerId = null;
_this.paths = {};
// Current Game Name, 'trackmania' or 'shootmania'.
_this.gameName = app.config.server.game || 'trackmania';
_this.options = {}; // Will be the result of GetServerOptions() call to the mp server.
_this.game = {}; // Will be the result of GetGameInfo() call.
return _this;
}
/**
* Build a sending query.
*
* @returns {Send}
*/
_createClass(ServerClient, [{
key: 'send',
value: function send() {
return new _send2.default(this.app, this);
}
/**
* Connect to the server.
*
* @returns {Promise}
*/
}, {
key: 'connect',
value: function connect() {
var _this2 = this;
this.app.log.debug("Connecting to ManiaPlanet Server...");
return new Promise(function (resolve, reject) {
_this2.gbx = _gbxremote2.default.createClient(_this2.server.port, _this2.server.address);
// On Connect
_this2.gbx.on('connect', function () {
_this2.app.log.debug('Connection to ManiaPlanet server successful!');
if (_this2.app.config.hasOwnProperty('debug') && _this2.app.config.debug) {
_this2.gbx.on('callback', function (method, params) {
_this2.app.log.debug("GBX: Callback '" + method + "':", params);
});
}
return resolve();
});
// On Error
_this2.gbx.on('error', function (err) {
_this2.app.log.fatal(err.stack);
if (err.message === 'read ECONNRESET') {
_this2.app.log.fatal('Connection with ManiaPlanet server lost!');
process.exit(1);
} else {
return reject(err);
}
});
}).then(function () {
// Authentication
return _this2.gbx.query('Authenticate', [_this2.server.authentication.username, _this2.server.authentication.password]);
}).then(function () {
// Set API Version
_this2.app.log.debug("Connection to ManiaPlanet Server, Successfully authenticated!");
return _this2.gbx.query('SetApiVersion', ['2015-02-10']);
}).then(function () {
// Set Callbacks On
_this2.app.log.debug("Connection to ManiaPlanet Server, Successfully set api version!");
return _this2.gbx.query('EnableCallbacks', [true]);
}).then(function () {
// Get server information
_this2.app.log.debug("Connection to ManiaPlanet Server, Successfully enabled callbacks!");
// Send boot msg
_this2.send().chat("$o$f90Mania$z$o$f90JS$z$fff: Booting Controller...").exec();
// Hide all current ManiaLinks
_this2.gbx.query('SendHideManialinkPage', []);
return _this2.gbx.query('GetVersion', []);
}).then(function (res) {
// Get System Info
_this2.app.log.debug("Connection to ManiaPlanet Server, Getting information...!");
_this2.version = res.Version;
_this2.build = res.Build;
_this2.apiVersion = res.ApiVersion;
return _this2.gbx.query('GetSystemInfo', []);
}).then(function (res) {
// Get Detailed Server Player Information (about the server player).
_this2.ip = res.PublishedIp;
_this2.ports = { port: res.Port, P2PPort: res.P2PPort };
_this2.titleId = res.TitleId;
_this2.login = res.ServerLogin;
_this2.playerId = res.ServerPlayerId;
return _this2.gbx.query('GetDetailedPlayerInfo', [_this2.login]);
}).then(function (res) {
// Get server options
_this2.path = res.Path;
return _this2.getServerOptions();
}).then(function (options) {
_this2.name = options.Name;
_this2.comment = options.Comment;
_this2.options = options;
}).then(function () {
// Get game info
return _this2.getGameInfos();
}).then(function (info) {
_this2.game = info;
// Get Directories.
return _this2.getServerDirectories();
}).then(function (dirs) {
_this2.paths = dirs;
// Test writing and reading in the data directory
if (!fs.existsSync(_this2.paths.data)) {
return Promise.reject(new Error('ManiaJS could not find the ManiaPlanet data dir! Is ManiaJS running on the same machine?'));
}
try {
fs.accessSync(_this2.paths.data);
} catch (err) {
return Promise.reject(err);
}
// If scripted? Then enable scripted callbacks
if (_this2.isScripted()) {
_this2.app.log.debug('Enabling Scripted Callbacks...');
return new Promise(function (resolve, reject) {
_this2.gbx.query('GetModeScriptSettings', []).then(function (settings) {
if (!settings) {
return reject(new Error('No ScriptSettings received!'));
}
// Add callback listener.
if (!settings.hasOwnProperty('S_UseScriptCallbacks')) {
return resolve(); // Ignore and continue.
}
settings['S_UseScriptCallbacks'] = true;
// TODO: Floats.
console.log(settings);
// Set and resolve, BUG: will throw error, type error.
_this2.gbx.query('SetModeScriptSettings', [settings]).then(function () {
return resolve();
}).catch(function (err) {
return reject(err);
});
});
});
}
return Promise.resolve();
});
}
/**
* Register the Callbacks.
*
* @return {Promise}
*/
}, {
key: 'register',
value: function register() {
var _this3 = this;
this.app.log.debug('Registering callbacks...');
return new Promise(function (resolve) {
_this3.callback = new _callbackManager2.default(_this3.app, _this3);
_this3.command = new _commandManager2.default(_this3.app, _this3);
_this3.callback.loadSet('maniaplanet');
if (_this3.app.config.server.game === 'trackmania') {
_this3.callback.loadSet('trackmania');
}
return resolve();
});
}
/**
* Update information about the server.
*
* @return {Promise}
*/
}, {
key: 'updateInfos',
value: function updateInfos() {
var _this4 = this;
// Update
return this.getServerOptions().then(function () {
return _this4.getGameInfos();
});
}
/**
* Is Current mode scripted?
*
* @returns {boolean}
*/
}, {
key: 'isScripted',
value: function isScripted() {
return this.game.CurrentGameInfos.GameMode === 0 || false;
}
/**
* Get Current Mode Integer, try to convert script name to game mode integer.
* @returns {number}
*/
}, {
key: 'currentMode',
value: function currentMode() {
if (this.isScripted()) {
// TODO: Script => legacy integers.
}
return this.game.CurrentGameInfos.GameMode;
}
/**
* Get Options of server.
*
* @returns {Promise}
*/
}, {
key: 'getServerOptions',
value: function getServerOptions() {
var _this5 = this;
return new Promise(function (resolve, reject) {
_this5.gbx.query('GetServerOptions', []).then(function (res) {
// Update properties.
_this5.name = res.Name;
_this5.comment = res.Comment;
_this5.options = res;
return resolve(res);
}).catch(function (err) {
return reject(err);
});
});
}
/**
* Get GetGameInfos call info. Will also update current server.game infos.
*
* @returns {Promise}
*/
}, {
key: 'getGameInfos',
value: function getGameInfos() {
var _this6 = this;
return new Promise(function (resolve, reject) {
_this6.gbx.query('GetGameInfos', []).then(function (res) {
_this6.game = res;
return resolve(res);
}).catch(function (err) {
return reject(err);
});
});
}
/**
* Get Server Directories.
* @returns Promise promise with object: data, maps, skins.
*/
}, {
key: 'getServerDirectories',
value: function getServerDirectories() {
var _this7 = this;
return new Promise(function (resolve, reject) {
_this7.gbx.query('system.multicall', [[{ methodName: 'GameDataDirectory', params: [] }, { methodName: 'GetMapsDirectory', params: [] }, { methodName: 'GetSkinsDirectory', params: [] }]]).then(function (results) {
return resolve({ data: results[0][0], maps: results[1][0], skins: results[2][0] });
}).catch(function (err) {
return reject(err);
});
});
}
}]);
return ServerClient;
}(_events.EventEmitter);
exports.default = ServerClient;