2013-10-13 03:44:27 +02:00
// 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 ( /=/ ) ;
2014-01-16 22:13:03 +01:00
if ( tmp [ 0 ] !== "" )
2013-10-13 03:44:27 +02:00
{
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' ] ;
}
2014-01-16 22:13:03 +01:00
// Will store the data about servers last time we checked, so we can compare if there
// are any changes
2013-10-13 03:44:27 +02:00
var serverList = { } ;
var firstLoop = true ;
// Modify the document body
2014-01-16 22:20:49 +01:00
var domUl = document . getElementById ( "noJsUsage" ) ;
2013-10-13 03:44:27 +02:00
var domBody = document . getElementsByTagName ( "body" ) ;
var wrapperDiv = document . createElement ( "div" ) ;
2014-01-16 22:13:03 +01:00
wrapperDiv . innerHTML = "The parameters used by the masterserver API will display when you move your mouse pointer over any of the table headings.<br /><br />" +
"<input id=\"enableNotifications\" type=\"checkbox\" /> <label for=\"enableNotifications\">Check here to enable auto-refreshing of the table and desktop notifications</label><br />" +
"<label for=\"refreshTimeId\">Refresh time (in seconds):</label> <input id=\"refreshTimeId\" type=\"number\" width=\"3\" min=\"10\" max=\"999\" /> <label for=\"refreshTimeId\">(minimum 10)</label>" ;
2013-10-13 03:44:27 +02:00
wrapperDiv . style . paddingLeft = "30px" ;
2014-01-16 22:20:49 +01:00
domBody [ 0 ] . insertBefore ( wrapperDiv , domUl ) ;
domUl . parentNode . removeChild ( domUl ) ;
2013-10-13 03:44:27 +02:00
2014-01-16 22:13:03 +01:00
// Modifying string object to support startsWith(String) function
// Created by CMS <http://stackoverflow.com/a/646643/1968462>
if ( typeof String . prototype . startsWith != 'function' ) {
// see below for better implementation!
String . prototype . startsWith = function ( str ) {
return this . indexOf ( str ) == 0 ;
} ;
}
2013-10-13 03:44:27 +02:00
// Request permission for issuing desktop notifications when the checkbox is ticked
var notifications = document . getElementById ( "enableNotifications" ) ;
notifications . onclick = function ( )
{
if ( notifications . checked )
{
Notification . requestPermission ( ) ;
}
2014-01-16 22:13:03 +01:00
} ;
2013-10-13 03:44:27 +02:00
// Helper function for escpaing special characters
function escapeHtml ( text ) {
return text . replace ( /&/g , "&" ) . 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 ( )
{
2014-01-16 22:13:03 +01:00
if ( request . readyState === 4 && request . status === 200 )
2013-10-13 03:44:27 +02:00
{
// Parse the JSON data for safety
var jsonText = JSON . parse ( request . responseText ) ;
var newServerList = { } ;
2014-01-16 22:13:03 +01:00
games _with _stats = 100 ;
2013-10-13 03:44:27 +02:00
// Repopulate table content
2014-01-16 22:13:03 +01:00
var table = "<tr>\n" +
" <th title=\"glestVersion\">Version</th>\n" +
" <th title=\"status\">Status</th>\n" +
" <th title=\"gameDuration\">Game Duration</th>\n" +
" <th title=\"country\">Country</th>\n" +
" <th title=\"serverTitle\">Title</th>\n" +
" <th title=\"tech\">Techtree</th>\n" +
" <th title=\"connectedClients\">Network players</th>\n" +
" <th title=\"networkSlots\">Network slots</th>\n" +
" <th title=\"activeSlots\">Total slots</th>\n" +
" <th title=\"map\">Map</th>\n" +
" <th title=\"tileset\">Tileset</th>\n" +
" <th title=\"ip\">IPv4 address</th>\n" +
" <th title=\"externalServerPort\">Game protocol port</th>\n" +
" <th title=\"platform\">Platform</th>\n" +
2014-01-16 22:30:33 +01:00
" <th title=\"lasttime\">Play date</th>\n" +
2014-01-16 22:13:03 +01:00
"</tr>\n" ;
2013-10-13 03:44:27 +02:00
// Loop through all json objects
for ( var i = 0 ; i < jsonText . length ; i ++ )
{
// Check if version filter is active
2014-01-19 00:15:05 +01:00
if ( version == '' || jsonText [ i ] . glestVersion == version )
2013-10-13 03:44:27 +02:00
{
////// DYNAMIC TABLE SECTION
table += "<tr>" ;
/// Version
table += "<td><a href=\"?version=" + escapeHtml ( jsonText [ i ] . glestVersion ) + "\" rel=\"nofollow\">" + escapeHtml ( jsonText [ i ] . glestVersion ) + "</a></td>" ;
/// Status
2014-01-19 00:15:05 +01:00
var statusCode = jsonText [ i ] . status ;
2013-10-13 03:44:27 +02:00
// Change text if the server is full
2014-01-19 00:15:05 +01:00
if ( ( statusCode == 0 ) && ( jsonText [ i ] . networkSlots <= jsonText [ i ] . connectedClients ) )
2013-10-13 03:44:27 +02:00
{
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' ;
}
2014-01-16 22:13:03 +01:00
//debugger;
if ( ( statusCode == "2" || statusCode == "3" ) && jsonText [ i ] . gameUUID !== "" )
{
var specialColHTML = "<td title=\"" + jsonText [ i ] . status + "\" class=\"" + statusClass + "\"><a id=\"gameStats_" + games _with _stats + "\" href=\"#\" gameuuid=\"" + jsonText [ i ] . gameUUID + "\">" + escapeHtml ( statusTitle ) + "</a></td>" ;
table += specialColHTML ;
}
else
{
table += "<td title=\"" + jsonText [ i ] . status + "\" class=\"" + statusClass + "\">" + escapeHtml ( statusTitle ) + "</td>" ;
}
2013-10-13 03:44:27 +02:00
2013-11-01 16:42:19 +01:00
/// Game Duration
table += "<td>" + escapeHtml ( jsonText [ i ] . gameDuration ) + "</td>" ;
2013-10-13 03:44:27 +02:00
/// Country
if ( jsonText [ i ] . country !== "" )
{
var flagFile = "flags/" + jsonText [ i ] . country . toLowerCase ( ) + ".png" ;
table += "<td><img src=\"" + flagFile + "\" title=\"" + jsonText [ i ] . country + "\" alt=\"" + jsonText [ i ] . country + "\" /></td>" ;
}
else
{
table += "<td>Unknown</td>" ;
}
/// Server title
table += "<td>" + escapeHtml ( jsonText [ i ] . serverTitle ) + "</td>" ;
/// Tech
table += "<td>" + escapeHtml ( jsonText [ i ] . tech ) + "</td>" ;
/// Connected clients
table += "<td>" + escapeHtml ( jsonText [ i ] . connectedClients ) + "</td>" ;
/// Network slots
table += "<td>" + escapeHtml ( jsonText [ i ] . networkSlots ) + "</td>" ;
/// Active slots
table += "<td>" + escapeHtml ( jsonText [ i ] . activeSlots ) + "</td>" ;
/// Map
table += "<td>" + escapeHtml ( jsonText [ i ] . map ) + "</td>" ;
/// Tileset
table += "<td>" + escapeHtml ( jsonText [ i ] . tileset ) + "</td>" ;
/// IP
table += "<td>" + escapeHtml ( jsonText [ i ] . ip ) + "</td>" ;
/// Port
table += "<td>" + escapeHtml ( jsonText [ i ] . externalServerPort ) + "</td>" ;
/// Platform
table += "<td>" + escapeHtml ( jsonText [ i ] . platform ) + "</td>" ;
2014-01-16 22:30:33 +01:00
/// Play date
table += "<td>" + escapeHtml ( jsonText [ i ] . lasttime ) + "</td>" ;
2013-10-13 03:44:27 +02:00
table += "</tr>" ;
2014-01-19 00:15:05 +01:00
if ( ( statusCode == "2" || statusCode == "3" ) && jsonText [ i ] . gameUUID !== "" )
2014-01-16 22:13:03 +01:00
{
table += "<tr width='100%%' class='fullyhide' id='content_row_" + jsonText [ i ] . gameUUID + "'>" ;
table += "<td width='100%%' colspan='100'></td>" ;
table += "</tr>" ;
2013-10-31 16:43:43 +01:00
2014-01-16 22:13:03 +01:00
games _with _stats ++ ;
}
2013-10-31 16:43:43 +01:00
2013-10-13 03:44:27 +02:00
////// DESKTOP NOTIFICATIONS SECTION
// Store data in an array keyed by the concatenation of the IP and port
2014-01-19 00:15:05 +01:00
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 , 'connectedClients' : jsonText [ i ] . connectedClients } ;
2013-10-13 03:44:27 +02:00
// Only check for changes if NOT the first time
if ( ! firstLoop )
{
2014-01-19 00:15:05 +01:00
if ( ( newServerList [ identifier ] . free > 0 && ! serverList [ identifier ] && statusCode == 0 && ( serverList [ identifier ] === undefined || ! serverList [ identifier ] . title . startsWith ( "Headless" ) ) ) || // doesn't exist in old list
( newServerList [ identifier ] . free > 0 && serverList [ identifier ] . connectedClients == 0 && newServerList [ identifier ] . connectedClients > 0 && statusCode == 0 && ( serverList [ identifier ] !== undefined && serverList [ identifier ] . title . startsWith ( "Headless" ) ) ) ) // Headless server that previously had zero players
2013-10-13 03:44:27 +02:00
{
// 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
2014-01-16 22:20:49 +01:00
var tableDOM = document . getElementById ( "gamesTable" ) ;
tableDOM . innerHTML = table ;
2013-10-13 03:44:27 +02:00
2014-01-16 22:20:49 +01:00
//debugger;
for ( var gameIndex = 100 ; gameIndex < 200 ; ++ gameIndex ) {
setupGameStatsLink ( gameIndex ) ;
}
2013-10-31 16:43:43 +01:00
2013-10-13 03:44:27 +02:00
// Catch empty case
2014-01-16 22:13:03 +01:00
if ( jsonText . length === 0 )
2013-10-13 03:44:27 +02:00
{
serverList = { } ;
}
}
// Empty server list
2014-01-16 22:13:03 +01:00
else if ( request . readyState === 4 && request . status === 0 )
2013-10-13 03:44:27 +02:00
{
serverList = { } ;
}
2014-01-16 22:13:03 +01:00
} ;
2013-10-13 03:44:27 +02:00
}
// 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 ) ;
2014-01-16 22:13:03 +01:00
} ;