From 714daace1886584a87aa1e543d0595e98b369a67 Mon Sep 17 00:00:00 2001 From: Daniel Scalzi Date: Sun, 15 Apr 2018 22:35:14 -0400 Subject: [PATCH] Added server status retrieval and implemented it on UI. The player count on the landing page is now functional. If the server cannot be reached, the label and value will change to SERVER and OFFLINE, respectively. This behavior can be modified. --- app/assets/js/actionbinder.js | 30 ++++++++++++++++ app/assets/js/assetguard.js | 4 +-- app/assets/js/preloader.js | 2 +- app/assets/js/serverstatus.js | 65 +++++++++++++++++++++++++++++++++++ app/landing.ejs | 2 +- 5 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 app/assets/js/serverstatus.js diff --git a/app/assets/js/actionbinder.js b/app/assets/js/actionbinder.js index ea67a99..b0c0f38 100644 --- a/app/assets/js/actionbinder.js +++ b/app/assets/js/actionbinder.js @@ -6,8 +6,11 @@ const ConfigManager = require(path.join(__dirname, 'assets', 'js', 'configmanage const DiscordWrapper = require(path.join(__dirname, 'assets', 'js', 'discordwrapper.js')) const Mojang = require(path.join(__dirname, 'assets', 'js', 'mojang.js')) const AuthManager = require(path.join(__dirname, 'assets', 'js', 'authmanager.js')) +const ServerStatus = require(path.join(__dirname, 'assets', 'js', 'serverstatus.js')) +const {URL} = require('url') let mojangStatusListener +let serverStatusListener // Launch Elements let launch_content, launch_details, launch_progress, launch_progress_label, launch_details_text @@ -86,9 +89,36 @@ document.addEventListener('readystatechange', function(){ document.getElementById('mojang_status_icon').style.color = Mojang.statusToHex(status) } + const refreshServerStatus = async function(){ + console.log('Refreshing Server Status') + const serv = AssetGuard.resolveSelectedServer(ConfigManager.getGameDirectory()) + + let pLabel = 'SERVER' + let pVal = 'OFFLINE' + + try { + console.log(serv) + const serverURL = new URL('my://' + serv.server_ip) + const servStat = await ServerStatus.getStatus(serverURL.hostname, serverURL.port) + if(servStat.online){ + pLabel = 'PLAYERS' + pVal = servStat.onlinePlayers + '/' + servStat.maxPlayers + } + + } catch (err) { + console.warn('Unable to refresh server status, assuming offline.') + console.debug(err) + } + document.getElementById('landingPlayerLabel').innerHTML = pLabel + document.getElementById('player_count').innerHTML = pVal + } + refreshMojangStatuses() + refreshServerStatus() + // Set refresh rate to once every 5 minutes. mojangStatusListener = setInterval(refreshMojangStatuses, 300000) + serverStatusListener = setInterval(refreshServerStatus, 300000) } }, false) diff --git a/app/assets/js/assetguard.js b/app/assets/js/assetguard.js index 1c01956..4b3f0a1 100644 --- a/app/assets/js/assetguard.js +++ b/app/assets/js/assetguard.js @@ -421,11 +421,11 @@ class AssetGuard extends EventEmitter { const servers = distro.servers for(let i=0; i 0) ? servers[0].id : null + return (servers.length > 0) ? servers[0] : null } /** diff --git a/app/assets/js/preloader.js b/app/assets/js/preloader.js index 6cd68be..3529475 100644 --- a/app/assets/js/preloader.js +++ b/app/assets/js/preloader.js @@ -15,7 +15,7 @@ AssetGuard.retrieveDistributionDataSync(ConfigManager.getGameDirectory(), false) // Resolve the selected server if its value has yet to be set. if(ConfigManager.getSelectedServer() == null){ console.log('Determining default selected server..') - ConfigManager.setSelectedServer(AssetGuard.resolveSelectedServer(ConfigManager.getGameDirectory())) + ConfigManager.setSelectedServer(AssetGuard.resolveSelectedServer(ConfigManager.getGameDirectory()).id) ConfigManager.save() } diff --git a/app/assets/js/serverstatus.js b/app/assets/js/serverstatus.js new file mode 100644 index 0000000..8e701ac --- /dev/null +++ b/app/assets/js/serverstatus.js @@ -0,0 +1,65 @@ +const net = require('net') + +/** + * Retrieves the status of a minecraft server. + * + * @param {string} address The server address. + * @param {number} port Optional. The port of the server. Defaults to 25565. + * @returns {Promise.} A promise which resolves to an object containing + * status information. + */ +exports.getStatus = function(address, port = 25565){ + + if(port == null || port == ''){ + port = 25565 + } + if(typeof port === 'string'){ + port = parseInt(port) + } + + return new Promise((resolve, reject) => { + const socket = net.connect(port, address, () => { + let buff = new Buffer([0xFE, 0x01]) + socket.write(buff) + }) + + socket.setTimeout(2500, () => { + socket.end() + reject({ + code: 'ETIMEDOUT', + errno: 'ETIMEDOUT', + address, + port + }) + }) + + socket.on('data', (data) => { + if(data != null && data != ''){ + let server_info = data.toString().split('\x00\x00\x00') + const NUM_FIELDS = 6 + if(server_info != null && server_info.length >= NUM_FIELDS){ + resolve({ + online: true, + version: server_info[2].replace(/\u0000/g, ''), + motd: server_info[3].replace(/\u0000/g, ''), + onlinePlayers: server_info[4].replace(/\u0000/g, ''), + maxPlayers: server_info[5].replace(/\u0000/g,'') + }) + } else { + resolve({ + online: false + }) + } + } + socket.end() + }) + + socket.on('error', (err) => { + socket.destroy() + reject(err) + // ENOTFOUND = Unable to resolve. + // ECONNREFUSED = Unable to connect to port. + }) + }) + +} \ No newline at end of file diff --git a/app/landing.ejs b/app/landing.ejs index 1316a13..ffca44d 100644 --- a/app/landing.ejs +++ b/app/landing.ejs @@ -102,7 +102,7 @@
- PLAYERS + PLAYERS 18/100
MOJANG STATUS