Created
March 28, 2020 16:00
-
-
Save aikar/f860f804ddbe1779dd2f211f7f87566a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env _node | |
var Rcon = require('rcon'); | |
var exec = require('child_process').exec; | |
var rconPass = require('fs').readFileSync(__dirname + '/rconpass').toString(); | |
var servers = {}; | |
[ | |
"smp1", "smp2", "smp3", | |
"smp4", "smp5", "smp6", | |
"smp7", "smp8", "smp9", | |
"utopia", | |
"games", | |
"stage" | |
].forEach(initServer); | |
function generateReport(server, _) { | |
var lag = rconCommand(server, "_empireserver servermonitor", _); | |
var tps = rconCommand(server, "tps", _); | |
var load= ''; | |
//var uptime = exec('ssh ' + server + '.emc uptime', _); | |
//var load = match(uptime, /load average: (.*)/); | |
var m; | |
var lcolor = 'a'; | |
if (m = load.match(/[\d\.]+/)) { | |
if (parseFloat(m[0]) > 8) { | |
lcolor = 'c'; | |
} | |
} | |
tps = match(tps, /15m: (.*)/); | |
var players = match(lag, /Players: (\d+)/); | |
var chunks = match(lag, /Chunks: (\d+)/); | |
var entities = match(lag, /Entities: (\d+)/); | |
var tileentities = match(lag, /TileEnt: (\d+)/); | |
var memocnt = parseInt(match(lag, /GCOldCount: (\d+)/)); | |
var memolast = match(lag, /GCOldLast: (\d+)/); | |
var memydur = match(lag, /GCYoungDur: (\d+)/); | |
var memyint = Math.round(Number(match(lag, /GCYoungInt: (\d+)/)/1000)); | |
var old = memocnt > 0 ? c(4, " (OLD: " + memocnt + ")") : ""; | |
var report = | |
c('e', server + ": ") + c(6, "TPS: ") + c('a', tps) + c(6, " - Load: ") + c(lcolor, load) +"\n" + | |
c('e', server + ": ") + c(6, memyint + "s(" + memydur +"ms)") + old | |
+ c(6, " P: ") + c('a', players) | |
+ c(6, " E: ") + c('a', entities) | |
+ c(6, " TE: ") + c('a', tileentities) | |
+ c(6, " Ch: ") + c('a', chunks); | |
//servers[server].membars = membars; | |
servers[server].players = players; | |
servers[server].report = report; | |
servers[server].report_dupe = report; | |
servers[server].lastupdate = new Date; | |
reprint(); | |
} | |
setInterval(function() { | |
var now = new Date().getTime(); | |
forEachServer(function(s, t) { | |
if (now - s.lastupdate.getTime() > 60*1000) { | |
s.report = c(4, t + ": ERROR: NOT RESPONDING: " + s.lastupdate + "\n" + (s.report_dupe||"")); | |
beep(); | |
reprint(); | |
} | |
}); | |
}, 10000); | |
function initServer(server) { | |
servers[server] = { | |
authed: false, | |
rcon: initRcon(server), | |
cb: null, | |
queue: [], | |
lastupdate: new Date, | |
player: 0, | |
membars: 5 | |
}; | |
setInterval(renderReport, 1000); | |
renderReport(); | |
function renderReport() { | |
generateReport(server, errstub); | |
} | |
} | |
var scheduled = false; | |
var reprintdelay = 500; | |
function reprint() { | |
if (scheduled) { | |
return; | |
} | |
scheduled = true; | |
setTimeout(function() { | |
resetConsole(); | |
var players = 0; | |
forEachServer(function(v) { | |
if (v.report) { | |
console.log(mccolor(v.report)); | |
players += parseInt(v.players || 0); | |
} | |
}); | |
console.log(mccolor( | |
c('e', 'Total Players: ') + | |
c('a', players) | |
)); | |
scheduled = false; | |
}, reprintdelay); | |
} | |
function match(src, ptn, idx) { | |
var m; | |
if ((m = src.match(ptn))) { | |
return m[idx || 1] || m[0]; | |
} | |
return m; | |
} | |
function forEachServer(cb) { | |
Object.keys(servers).forEach(function (v) { | |
cb(servers[v], v); | |
}); | |
} | |
function initRcon(server) { | |
var rcon = new Rcon(server + '.emc', 25576, rconPass); | |
rcon.on('response', function(str) { | |
receiveResponse(server, str); | |
}); | |
rcon.on('auth', function() { | |
servers[server].authed = true; | |
processQueue(server); | |
}); | |
rcon.on('end', function() { | |
reconnect(); | |
}); | |
rcon.on("error", function(e){ | |
rcon.disconnect(); | |
reconnect(); | |
}); | |
try { | |
rcon.connect(); | |
} catch (e) { | |
console.error(e.message); | |
reconnect() | |
} | |
function reconnect() { | |
setTimeout(function() { | |
servers[server].rcon = initRcon(server); | |
}, 1000); | |
} | |
return rcon; | |
} | |
function rconCommand(server, cmd, cb) { | |
var obj = servers[server]; | |
if (obj.cb == null && obj.authed) { | |
obj.cb = cb; | |
obj.cmd = cmd; | |
executeRcon(obj); | |
} else { | |
var nxt = { | |
cb: cb, | |
cmd: cmd | |
}; | |
obj.queue.push(nxt); | |
} | |
} | |
function executeRcon(obj) { | |
obj.rcon.send(obj.cmd); | |
} | |
function receiveResponse(server, str) { | |
var obj = servers[server]; | |
if (obj.cb) { | |
obj.cb(null, str); | |
} | |
processQueue(server); | |
} | |
function processQueue(server) { | |
var obj = servers[server]; | |
if (obj.queue.length) { | |
var next = obj.queue.shift(); | |
obj.cb = next.cb; | |
obj.cmd = next.cmd; | |
executeRcon(obj); | |
} else { | |
obj.cb = null; | |
obj.cmd = null; | |
} | |
} | |
function beep() { | |
// return exec('ssh laptop bin/alert 0.5'); | |
} | |
function resetConsole() { | |
process.stdout.write('\x1Bc'); | |
} | |
function errstub(err) { | |
if (err) { | |
throw err; | |
} | |
} | |
var colors = { | |
0: "\x1B[0;30m", /* 00 BLACK 0x30 */ | |
1: "\x1B[0;34m", /* 01 BLUE 0x31 */ | |
2: "\x1B[0;32m", /* 02 GREEN 0x32 */ | |
3: "\x1B[0;36m", /* 03 CYAN 0x33 */ | |
4: "\x1B[0;31m", /* 04 RED 0x34 */ | |
5: "\x1B[0;35m", /* 05 PURPLE 0x35 */ | |
6: "\x1B[0;33m", /* 06 GOLD 0x36 */ | |
7: "\x1B[0;37m", /* 07 GREY 0x37 */ | |
8: "\x1B[1;30m", /* 08 DGREY 0x38 */ | |
9: "\x1B[1;34m", /* 09 LBLUE 0x39 */ | |
a: "\x1B[1;32m", /* 10 LGREEN 0x61 */ | |
b: "\x1B[1;36m", /* 11 LCYAN 0x62 */ | |
c: "\x1B[1;31m", /* 12 LRED 0x63 */ | |
d: "\x1B[1;35m", /* 13 LPURPLE 0x64 */ | |
e: "\x1B[1;33m", /* 14 YELLOW 0x65 */ | |
f: "\x1B[1;37m", /* 15 WHITE 0x66 */ | |
}; | |
function mccolor(str) { | |
return str.replace(/§([0-9a-fr])/g, function(m, contents) { | |
return colors[contents] || "\x1B[0m"; | |
}); | |
} | |
function c(r, msg) { | |
return '§' + r + msg + '§r'; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment