// Copyright (C) 2013 Mike Hoffert ("Omega")
// Licensed under GNU GPL v3.0
// ==============================================================
var DEFAULT_REFRESH_TIME = 20000;
// Get query arguments
var get_data = {};
var args = location.search.substr(1).split(/&/);
var version = '';
// Break up URL to find the get queries
for (var i = 0; i < args.length; i++)
{
var tmp = args[i].split(/=/);
if(tmp[0] != "")
{
get_data[decodeURIComponent(tmp[0])] = decodeURIComponent(tmp.slice(1).join("").replace("+", " "));
}
}
// Check if there's a version query
if(get_data['version'])
{
version = get_data['version'];
}
var serverList = {};
var firstLoop = true;
// Modify the document body
var domUl = document.getElementsByTagName("ul");
var domBody = document.getElementsByTagName("body");
var wrapperDiv = document.createElement("div");
wrapperDiv.innerHTML = "The parameters used by the masterserver API will display when you move your mouse pointer over any of the table headings.
"
+ " "
+ " ";
wrapperDiv.style.paddingLeft = "30px";
domBody[0].insertBefore(wrapperDiv, domUl[0]);
domUl[0].parentNode.removeChild(domUl[0]);
// Request permission for issuing desktop notifications when the checkbox is ticked
var notifications = document.getElementById("enableNotifications");
notifications.onclick = function()
{
if(notifications.checked)
{
Notification.requestPermission();
}
}
// Helper function for escpaing special characters
function escapeHtml(text) {
return text.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'");
}
// Check the JSON data for changes at intervals and update table
function timedRequest()
{
// Break out if the checkbox isn't ticked
if(!notifications.checked)
{
return;
}
// Get JSON of server list
var request = new XMLHttpRequest();
request.open('GET', 'showServersJson.php', true);
request.send();
// Function calls as soon as we receive the right data from the site
request.onreadystatechange = function()
{
if (request.readyState == 4 && request.status == 200)
{
// Parse the JSON data for safety
var jsonText = JSON.parse(request.responseText);
var newServerList = {};
// Repopulate table content
var table = "
\n"
+ "
Version
\n"
+ "
Status
\n"
+ "
Country
\n"
+ "
Title
\n"
+ "
Techtree
\n"
+ "
Network players
\n"
+ "
Network slots
\n"
+ "
Total slots
\n"
+ "
Map
\n"
+ "
Tileset
\n"
+ "
IPv4 address
\n"
+ "
Game protocol port
\n"
+ "
Platform
\n"
+ "
Build date
\n"
+ "
\n";
// Loop through all json objects
for(var i = 0; i < jsonText.length; i++)
{
// Check if version filter is active
if(version == '' || jsonText[i].glestVersion == version)
{
////// DYNAMIC TABLE SECTION
table += "
";
/// Status
var statusCode = jsonText[i].status;
// Change text if the server is full
if((statusCode == 0) && (jsonText[i].networkSlots <= jsonText[i].connectedClients))
{
statusCode = 1;
}
var statusTitle, statusClass;
// Note that the json value is stored as a string, not a number
switch(statusCode)
{
case "0":
statusTitle = 'waiting for players';
statusClass = 'waiting_for_players';
break;
case "1":
statusTitle = 'game full, pending start';
statusClass = 'game_full_pending_start';
break;
case "2":
statusTitle = 'in progress';
statusClass = 'in_progress';
break;
case "3":
statusTitle = 'finished';
statusClass = 'finished';
break;
default:
statusTitle = 'unknown';
statusClass = 'unknown';
}
table += "
" + escapeHtml(statusTitle) + "
";
/// Country
if(jsonText[i].country !== "")
{
var flagFile = "flags/" + jsonText[i].country.toLowerCase() + ".png";
table += "
";
////// DESKTOP NOTIFICATIONS SECTION
// Store data in an array keyed by the concatenation of the IP and port
var identifier = jsonText[i].ip + jsonText[i].externalServerPort;
newServerList[identifier] = { 'ip': jsonText[i].ip, 'port': jsonText[i].externalServerPort, 'title': jsonText[i].serverTitle, 'free': (jsonText[i].networkSlots - jsonText[i].connectedClients), 'version': jsonText[i].glestVersion };
// Only check for changes if NOT the first time
if(!firstLoop)
{
// Check if new server doesn't exist in old list
if((newServerList[identifier].free > 0) && !serverList[identifier] && statusCode == 0)
{
// Create notification
var notification = new Notification("Open server", {
iconUrl: 'images/game_icon.png',
body: 'Server "' + newServerList[identifier].title + '" has ' + newServerList[identifier].free + ' free slots available. Click to join now.',
});
notification.onclick = function() { window.location.assign('http://play.mg/?version=' + newServerList[identifier].version + '&mgg_host=' + newServerList[identifier].ip + '&mgg_port=' + newServerList[identifier].port); };
}
}
else
{
firstLoop = false;
}
}
}
// Replace old list with new one
serverList = newServerList;
// Write to actual table when done only, otherwise the browser trips as it tries to fix the partial table formatting
var tableDOM = document.getElementsByTagName("tbody");
tableDOM[0].innerHTML = table;
// Catch empty case
if(jsonText.length == 0)
{
serverList = { };
}
}
// Empty server list
else if(request.readyState == 4 && request.status == 0)
{
serverList = { };
}
}
}
// Default time in miliseconds between updates
var refreshTime = DEFAULT_REFRESH_TIME;
// Check if there's an HTTP refresh query. If so, we need to overwrite it
if(get_data['refresh'])
{
// Get the base URL without any GET parameters (because we have to remove the
// old refresh variable)
var redirectLocation = location.href.split("?")[0] + "?";
// If a version variable was specified, add that back in
if(get_data['version'])
{
redirectLocation += "version=" + get_data['version'] + "&";
}
// Finally the new refresh variable just for JS use
redirectLocation += "jsrefresh=" + get_data['refresh'];
window.location.replace(redirectLocation);
}
// Check if there's a js refresh query
if(get_data['jsrefresh'])
{
// In seconds, so multiply by 1000 for miliseconds
refreshTime = parseInt(get_data['jsrefresh']) * 1000;
}
// Initialize value in text field
var refreshTimeBox = document.getElementById("refreshTimeId");
refreshTimeBox.value = refreshTime / 1000;
// Initiate interval
timedRequest();
var interval = setInterval(timedRequest, refreshTime);
// Catch changes to the refresh time box
refreshTimeBox.onchange = function()
{
// Validate if the input is a number
if(!isNaN(parseFloat(refreshTimeBox.value)) && isFinite(refreshTimeBox.value))
{
if(refreshTimeBox.value < 10)
{
refreshTime = 10000;
refreshTimeBox.value = 10;
}
else if(refreshTimeBox.value > 999)
{
refreshTime = 999000;
refreshTimeBox.value = 999;
}
else
{
refreshTime = refreshTimeBox.value * 1000;
}
}
else
{
refreshTime = DEFAULT_REFRESH_TIME;
refreshTimeBox.value = 20;
}
// Reset the interval
clearInterval(interval);
interval = setInterval(timedRequest, refreshTime);
}