var _ = require('lodash') var events = require('events') var fs = require('fs') var Gamedig = require('gamedig') var slugify = require('slugify') var ArmaServer = require('arma-server') var config = require('../config.js') var queryInterval = 5000 var queryTypes = { arma1: 'arma', arma2: 'arma2', arma2oa: 'arma2', arma3: 'arma3', arma3_x64: 'arma3', cwa: 'operationflashpoint', ofp: 'operationflashpoint', ofpresistance: 'operationflashpoint' } var createServerTitle = function (title) { if (config.prefix) { title = config.prefix + title } if (config.suffix) { title = title + config.suffix } return title } var Server = function (config, logs, options) { this.config = config this.logs = logs this.update(options) } Server.prototype = new events.EventEmitter() Server.prototype.generateId = function () { return slugify(this.title).replace(/\./g, '-') } Server.prototype.update = function (options) { this.admin_password = options.admin_password this.auto_start = options.auto_start this.battle_eye = options.battle_eye this.max_players = options.max_players this.missions = options.missions this.mods = options.mods || [] this.number_of_headless_clients = options.number_of_headless_clients || 0 this.password = options.password this.parameters = options.parameters this.persistent = options.persistent this.port = options.port || 2302 this.title = options.title this.von = options.von this.verify_signatures = options.verify_signatures this.id = this.generateId() this.port = parseInt(this.port, 10) // If port is a string then gamedig fails } Server.prototype.queryStatus = function () { if (!this.instance) { return } var self = this Gamedig.query( { type: queryTypes[config.game], host: '127.0.0.1', port: self.port }, function (state) { if (!self.instance) { return } if (state.error) { self.state = null } else { self.state = state } self.emit('state') } ) } Server.prototype.getParameters = function () { var parameters = [] if (config.parameters && Array.isArray(config.parameters)) { parameters = parameters.concat(config.parameters) } if (this.parameters && Array.isArray(this.parameters)) { parameters = parameters.concat(this.parameters) } return parameters } Server.prototype.start = function () { var parameters = this.getParameters() var server = new ArmaServer.Server({ admins: config.admins, battleEye: this.battle_eye ? 1 : 0, config: this.id, disableVoN: this.von ? 0 : 1, game: config.game, headlessClients: this.number_of_headless_clients > 0 ? ['127.0.0.1'] : null, hostname: createServerTitle(this.title), localClient: this.number_of_headless_clients > 0 ? ['127.0.0.1'] : null, missions: this.missions, mods: this.mods, parameters: parameters, password: this.password, passwordAdmin: this.admin_password, path: this.config.path, persistent: this.persistent ? 1 : 0, platform: this.config.type, players: this.max_players, port: this.port, serverMods: config.serverMods, verifySignatures: this.verify_signatures ? 2 : 0 }) server.writeServerConfig() var instance = server.start() var self = this var logStream = null if (this.config.type === 'linux') { logStream = fs.createWriteStream(this.logs.generateLogFilePath(), { 'flags': 'a' }) } instance.stdout.on('data', function (data) { if (logStream) { logStream.write(data) } }) instance.stderr.on('data', function (data) { if (logStream) { logStream.write(data) } }) instance.on('close', function (code) { if (logStream) { logStream.end() } clearInterval(self.queryStatusInterval) self.state = null self.pid = null self.instance = null self.stopHeadlessClients() self.emit('state') }) instance.on('error', function (err) { console.log(err) }) this.pid = instance.pid this.instance = instance this.queryStatusInterval = setInterval(function () { self.queryStatus() }, queryInterval) this.startHeadlessClients() this.emit('state') return this } Server.prototype.startHeadlessClients = function () { var parameters = this.getParameters() var self = this var headlessClientInstances = _.times(this.number_of_headless_clients, function (i) { var headless = new ArmaServer.Headless({ game: config.game, host: '127.0.0.1', mods: self.mods, parameters: parameters, password: self.password, path: self.config.path, platform: self.config.type, port: self.port }) var headlessInstance = headless.start() var name = 'HC_' + i var logPrefix = self.id + ' ' + name console.log(logPrefix + ' starting') headlessInstance.stdout.on('data', function (data) { console.log(logPrefix + ' stdout: ' + data) }) headlessInstance.stderr.on('data', function (data) { console.log(logPrefix + ' stderr: ' + data) }) headlessInstance.on('close', function (code) { console.log(logPrefix + ' exited: ' + code) var elementIndex = headlessClientInstances.indexOf(headlessInstance) if (elementIndex !== -1) { headlessClientInstances.splice(elementIndex, 1) } }) headlessInstance.on('error', function (err) { console.log(logPrefix + ' error: ' + err) }) return headlessInstance }) this.headlessClientInstances = headlessClientInstances } Server.prototype.stop = function (cb) { var handled = false this.instance.on('close', function (code) { if (!handled) { handled = true if (cb) { cb() } } }) this.instance.kill() setTimeout(function () { if (!handled) { handled = true if (cb) { cb() } } }, 5000) return this } Server.prototype.stopHeadlessClients = function () { this.headlessClientInstances.map(function (headlessClientInstance) { headlessClientInstance.kill() }) } Server.prototype.toJSON = function () { return { admin_password: this.admin_password, auto_start: this.auto_start, battle_eye: this.battle_eye, id: this.id, max_players: this.max_players, missions: this.missions, mods: this.mods, number_of_headless_clients: this.number_of_headless_clients, parameters: this.parameters, password: this.password, persistent: this.persistent, pid: this.pid, port: this.port, state: this.state, title: this.title, von: this.von, verify_signatures: this.verify_signatures } } module.exports = Server