MCSManager/core/Process/BaseMcserver.js
2017-11-18 11:34:41 +08:00

205 lines
6.2 KiB
JavaScript

const childProcess = require('child_process');
const iconv = require('iconv-lite');
const EventEmitter = require('events');
const DataModel = require('../DataModel');
const os = require('os');
var CODE_CONSOLE = 'GBK';
if (os.platform() == 'win32') {
CODE_CONSOLE = 'GBK';
} else {
CODE_CONSOLE = 'UTF-8';
}
//https://github.com/Gagle/Node-Properties
const properties = require("properties");
const fs = require('fs');
class ServerProcess extends EventEmitter {
constructor(args) {
super(args)
this.dataModel = undefined;
this.process = undefined;
this._run = false;
//用于异步进行的锁
this._loading = false;
}
//自定义高级参数启动
twoStart() {
MCSERVER.infoLog('Minecraft Server start', this.dataModel.name);
MCSERVER.log('服务器 [' + this.dataModel.name + '] 启动进程:')
MCSERVER.log('-------------------------------');
MCSERVER.log('自定义参数启动: ' + this.dataModel.highCommande);
MCSERVER.log('根:' + this.dataModel.cwd);
MCSERVER.log('-------------------------------');
if (!this.highCommande) new Error("自定义参数非法,无法启动服务端");
let commandArray = this.dataModel.highCommande.split(" ");
let javaPath = commandArray.shift();
//过滤
let parList = [];
for (let k in commandArray) {
if (commandArray[k] == '') continue;
parList.push(commandArray[k]);
}
this.process =
childProcess.spawn(javaPath, parList, this.ProcessConfig);
}
//普通启动
oneStart() {
let tmpAddList = [];
let tmpShouldList = [];
this.dataModel.Xmx && tmpShouldList.push('-Xmx' + this.dataModel.Xmx);
this.dataModel.Xms && tmpShouldList.push('-Xms' + this.dataModel.Xms);
tmpShouldList.push('-Djline.terminal=jline.UnsupportedTerminal');
tmpShouldList.push('-jar');
tmpShouldList.push(this.dataModel.jarName);
tmpAddList = this.dataModel.addCmd.concat(tmpShouldList);
//过滤
let parList = [];
for (let k in tmpAddList) {
if (tmpAddList[k] == '') continue;
parList.push(tmpAddList[k]);
}
MCSERVER.infoLog('Minecraft Server start', this.dataModel.name);
MCSERVER.log('服务器 [' + this.dataModel.name + '] 启动进程:')
MCSERVER.log('-------------------------------');
MCSERVER.log('启动: ' + this.dataModel.java + ' ' + parList.toString().replace(/,/gim, ' '));
MCSERVER.log('根:' + this.dataModel.cwd);
MCSERVER.log('-------------------------------');
this.process = childProcess.spawn(this.dataModel.java, parList, this.ProcessConfig);
}
start() {
//防止重复启动
if (this._run || this._loading) throw new Error('服务端进程在运行或正在加载..');
this._loading = true;
let jarPath = (this.dataModel.cwd + '/' + this.dataModel.jarName).replace(/\/\//igm, '/');
//尽在非自定义模式下检查参数
if (!this.dataModel.highCommande) {
if (!fs.existsSync(this.dataModel.cwd)) {
this.stop();
throw new Error('服务端根目录 "' + jarPath + '" 不存在!');
}
if (this.dataModel.jarName.trim() == '') {
this.stop();
throw new Error('未设置服务端核心文件,无法启动服务器');
}
if (!fs.existsSync(jarPath)) {
this.stop();
throw new Error('服务端文件 "' + jarPath + '" 不存在或错误!');
}
}
this.ProcessConfig = {
cwd: this.dataModel.cwd,
stdio: 'pipe'
}
try {
//确定启动方式
this.dataModel.highCommande ? this.twoStart() : this.oneStart();
} catch (err) {
this.stop();
}
this._run = true;
this._loading = false;
this.dataModel.lastDate = new Date().toLocaleString();
this.process.on('error', (err) => {
MCSERVER.error('服务器启动时保存,建议检查配置与环境', err);
this.stop();
this.emit('error', err);
});
if (this.process.pid == undefined) {
MCSERVER.error('this.process.pid is null', this.process.pid);
this.stop();
delete this.process;
throw new Error('服务端进程启动失败,请检查启动参数');
return false;
}
// 事件的传递
this.process.stdout.on('data', (data) => this.emit('console', iconv.decode(data, CODE_CONSOLE)));
this.process.stderr.on('data', (data) => this.emit('console', iconv.decode(data, CODE_CONSOLE)));
this.process.on('exit', (code) => {
this.emit('exit', code);
this.stop();
});
//产生事件开启
this.emit('open', this);
return true;
}
send(command) {
if (this._run) {
this.process.stdin.write(iconv.encode(command, CODE_CONSOLE));
this.process.stdin.write('\n');
return true;
}
return true;
}
restart() {
if (this._run == true) {
this.send('stop');
this.send('end');
//开始计时重启
let timeCount = 0;
let timesCan = setInterval(() => {
if (this._run == false) {
setTimeout(() => this.start(), 1000);
clearInterval(timesCan);
}
//60s 内服务器依然没有关闭,代表出现问题
if (timeCount >= 60) {
clearInterval(timesCan)
}
timeCount++;
}, 1000);
return true;
}
}
stop() {
this._run = false;
this._loading = false;
this.send('stop');
this.send('end');
}
kill() {
if (this._run) {
this.process.kill();
this._run = false;
return true;
}
return false;
}
isRun() {
return this._run;
}
}
module.exports = ServerProcess;