Abstracted clock and tile-updating a bit.

This commit is contained in:
FrozenCow 2011-01-12 01:28:45 +01:00
parent 8263918b8d
commit 27fb8a20f1
5 changed files with 176 additions and 155 deletions

View File

@ -20,7 +20,8 @@
<script type="text/javascript" src="config.js"></script> <script type="text/javascript" src="config.js"></script>
</head> </head>
<body> <body>
<div id="mcmap"></div> <div id="mcmap"></div>
<div id="alert">Updating...</div>
<div id="plist"> <div id="plist">
<img id="plistbtn" alt="on" src="list_on.png" onclick="plistopen()" title="Toggle Player List" /> <img id="plistbtn" alt="on" src="list_on.png" onclick="plistopen()" title="Toggle Player List" />
<div id="maplist"></div> <div id="maplist"></div>

View File

@ -26,8 +26,10 @@ KzedProjection.prototype = {
} }
}; };
KzedMapType.prototype = new DynMapType();
function KzedMapType() {} function KzedMapType() {}
KzedMapType.prototype = { KzedMapType.prototype = {
constructor: KzedMapType,
projection: new KzedProjection(), projection: new KzedProjection(),
tileSize: new google.maps.Size(128, 128), tileSize: new google.maps.Size(128, 128),
minZoom: 0, minZoom: 0,
@ -96,7 +98,7 @@ KzedMapType.prototype = {
} }
if (tileName) { if (tileName) {
img = $('<img/>') img = $('<img/>')
.attr('src', tileUrl(tileName)) .attr('src', getTileUrl(tileName))
.error(function() { img.hide(); }) .error(function() { img.hide(); })
.css({ .css({
width: imgSize + 'px', width: imgSize + 'px',
@ -106,9 +108,9 @@ KzedMapType.prototype = {
marginTop: offset.y + 'px' marginTop: offset.y + 'px'
}) })
.appendTo(tile); .appendTo(tile);
tileDict[tileName] = img; registerTile(this, tileName, img);
} else { } else {
delete tileDict[tileName]; unregisterTile(this, tileName);
} }
return tile.get(0); return tile.get(0);
}, },

View File

@ -1,88 +1,90 @@
if (!console) console = { log: function() {} }; if (!console) console = { log: function() {} };
/* generic function for making an XMLHttpRequest function DynMapType() { }
* url: request URL DynMapType.prototype = {
* func: callback function for success onTileUpdated: function(tile, tileName) {
* type: 'text' by default (callback is called with response text) var src = getTileUrl(tileName);
* otherwise, callback is called with a parsed XML dom tile.attr('src', src);
* fail: callback function for failure tile.show();
* post: if given, make a POST request instead of GET; post data given
*
* contenttype: if given for a POST, set request content-type header
*/
function makeRequest(url, func, type, fail, post, contenttype)
{
var http_request = false;
type = typeof(type) != 'undefined' ? type : 'text';
fail = typeof(fail) != 'undefined' ? fail : function() { };
if(window.XMLHttpRequest) {
http_request = new XMLHttpRequest();
} else if(window.ActiveXObject) {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} }
};
if(type == 'text') { function MinecraftClock(element) { this.element = element; }
http_request.onreadystatechange = function() { MinecraftClock.prototype = {
if(http_request.readyState == 4) { element: null,
if(http_request.status == 200) { timeout: null,
func(http_request.responseText); time: null,
} else { create: function(element) {
fail(http_request); if (!element) element = $('<div/>');
} this.element = element;
} return element;
},
setTime: function(time) {
if (this.timeout != null) {
window.clearTimeout(this.timeout);
this.timeout = null;
} }
} else { this.time = time;
http_request.onreadystatechange = function() { this.element
if(http_request.readyState == 4) { .addClass(time.day ? 'day' : 'night')
if(http_request.status == 200) { func(http_request.responseXML); } else { .removeClass(time.night ? 'day' : 'night')
fail(http_request); .text(this.formatTime(time));
}
} if (this.timeout == null) {
var me = this;
this.timeout = window.setTimeout(function() {
me.timeout = null;
me.setTime(getMinecraftTime(me.time.servertime+(1000/60)));
}, 700 /* should be 600, but since server-resyncing it looks better with 700 */);
} }
},
formatTime: function(time) {
var formatDigits = function(n, digits) {
var s = n.toString();
while (s.length < digits) {
s = '0' + s;
}
return s;
}
return formatDigits(time.hours, 2) + ':' + formatDigits(time.minutes, 2);
} }
};
if(typeof(post) != 'undefined') { var tileDict = new Array();
http_request.open('POST', url, true); var lastSeen = new Array();
if(typeof(contenttype) != 'undefined')
http_request.setRequestHeader("Content-Type", contenttype); function getTileUrl(tile, always) {
http_request.send(post); if(always) {
var now = new Date();
return config.tileUrl + tile + '.png?' + now.getTime();
} else if(tile in lastSeen) {
return config.tileUrl + tile + '.png?' + lastSeen[tile];
} else { } else {
http_request.open('GET', url, true); return config.tileUrl + tile + '.png?0';
http_request.send(null);
} }
} }
var tileDict = new Array(); function registerTile(mapType, tileName, tile) {
var lastSeen = new Array(); tileDict[tileName] = {
tileElement: tile,
mapType: mapType
};
}
function tileUrl(tile, always) { function unregisterTile(mapType, tileName) {
if(always) { delete tileDict[tileName];
var now = new Date(); }
return config.tileUrl + tile + '.png?' + now.getTime();
} else if(tile in lastSeen) {
return config.tileUrl + tile + '.png?' + lastSeen[tile];
} else {
return config.tileUrl + tile + '.png?0';
}
}
function onTileUpdated(tileName, f) { function onTileUpdated(tileName) {
lastSeen[tileName] = lasttimestamp;
}
function imgSubst(tileName) { var tile = tileDict[tileName];
if(!(tileName in tileDict)) if (tile) {
return; tile.mapType.onTileUpdated(tile.tileElement, tileName);
var src = tileUrl(tileName);
var t = tileDict[tileName];
t.attr('src', src);
t.show();
} }
}
var clock = null;
var markers = new Array(); var markers = new Array();
var lasttimestamp = '0'; var lasttimestamp = '0';
var followPlayer = ''; var followPlayer = '';
@ -90,8 +92,6 @@ function makeRequest(url, func, type, fail, post, contenttype)
var lst; var lst;
var plistbtn; var plistbtn;
var lstopen = true; var lstopen = true;
var oldplayerlst = '[Connecting]';
var servertime = 0;
function updateMarker(mi) { function updateMarker(mi) {
if(mi.id in markers) { if(mi.id in markers) {
@ -173,90 +173,75 @@ function makeRequest(url, func, type, fail, post, contenttype)
function mapUpdate() function mapUpdate()
{ {
makeRequest(config.updateUrl + lasttimestamp, function(res) { $.ajax({
var typeVisibleMap = { url: config.updateUrl + lasttimestamp,
'warp': document.getElementById('showWarps').checked, success: function(res) {
'sign': document.getElementById('showSigns').checked, $('#alert')
'home': document.getElementById('showHomes').checked, .hide();
'spawn': document.getElementById('showSpawn').checked var typeVisibleMap = {
}; 'warp': document.getElementById('showWarps').checked,
'sign': document.getElementById('showSigns').checked,
var typeCount = {}; 'home': document.getElementById('showHomes').checked,
'spawn': document.getElementById('showSpawn').checked
var rows = res.split('\n'); };
var loggedin = new Array();
var firstRow = rows[0].split(' ');
lasttimestamp = firstRow[0];
servertime = firstRow[1];
delete rows[0];
for(var line in rows) {
var p = rows[line].split(' ');
if (p[0] == '') continue;
({ tile: function() { var typeCount = {};
var tileName = p[1];
lastSeen[tileName] = lasttimestamp; var rows = res.split('\n');
imgSubst(tileName); var loggedin = new Array();
} var firstRow = rows[0].split(' ');
}[p[0]] || function() { lasttimestamp = firstRow[0];
var mi = { delete rows[0];
id: p[0] + '_' + p[1],
text: p[1], var servertime = firstRow[1];
type: p[0], clock.setTime(getMinecraftTime(servertime));
position: map.getProjection().fromWorldToLatLng(p[2], p[3], p[4]),
visible: ((p[0] in typeVisibleMap) ? typeVisibleMap[p[0]] : true) for(var line in rows) {
}; var p = rows[line].split(' ');
updateMarker(mi); if (p[0] == '') continue;
loggedin[mi.id] = 1;
if (!mi.type in typeCount) typeCount[mi.type] = 0; ({ tile: function() {
typeCount[mi.type]++; onTileUpdated(p[1]);
})(); }
} }[p[0]] || function() {
var mi = {
var time = { id: p[0] + '_' + p[1],
// Assuming it is day at 8:00 text: p[1],
hours: (parseInt(servertime / 1000)+8) % 24, type: p[0],
minutes: parseInt(((servertime / 1000) % 1) * 60), position: map.getProjection().fromWorldToLatLng(p[2], p[3], p[4]),
seconds: parseInt(((((servertime / 1000) % 1) * 60) % 1) * 60) visible: ((p[0] in typeVisibleMap) ? typeVisibleMap[p[0]] : true)
}; };
updateMarker(mi);
$('#clock') loggedin[mi.id] = 1;
.addClass(servertime > 12000 ? 'night' : 'day') if (!mi.type in typeCount) typeCount[mi.type] = 0;
.removeClass(servertime > 12000 ? 'day' : 'night') typeCount[mi.type]++;
.text(formatTime(time)); })();
for(var m in markers) {
if(!(m in loggedin)) {
markers[m].remove(null);
if (markers[m].playerRow) {
markers[m].playerRow.remove();
}
delete markers[m];
} }
for(var m in markers) {
if(!(m in loggedin)) {
markers[m].remove(null);
if (markers[m].playerRow) {
markers[m].playerRow.remove();
}
delete markers[m];
}
}
setTimeout(mapUpdate, config.updateRate);
document.getElementById('warpsDiv').style.display = (typeCount['warps'] == 0)?'none':'';
document.getElementById('signsDiv').style.display = (typeCount['signs'] == 0)?'none':'';
document.getElementById('homesDiv').style.display = (typeCount['homes'] == 0)?'none':'';
document.getElementById('spawnsDiv').style.display = (typeCount['spawns'] == 0)?'none':'';
},
error: function(request, statusText, ex) {
$('#alert')
.text('Could not update map')
.show();
setTimeout(mapUpdate, config.updateRate);
} }
setTimeout(mapUpdate, config.updateRate); });
document.getElementById('warpsDiv').style.display = (typeCount['warps'] == 0)?'none':'';
document.getElementById('signsDiv').style.display = (typeCount['signs'] == 0)?'none':'';
document.getElementById('homesDiv').style.display = (typeCount['homes'] == 0)?'none':'';
document.getElementById('spawnsDiv').style.display = (typeCount['spawns'] == 0)?'none':'';
}, 'text', function() { alert('failed to get update data'); } );
}
function formatTime(time) {
//return formatDigits(time.hours, 2) + ':' + formatDigits(time.minutes, 2) + ':' + formatDigits(time.seconds, 2);
return formatDigits(time.hours, 2) + ':' + formatDigits(time.minutes, 2);
}
function formatDigits(n, digits) {
var s = n.toString();
while (s.length < digits) {
s = '0' + s;
}
return s;
} }
window.onload = function initialize() { window.onload = function initialize() {
@ -317,6 +302,8 @@ function makeRequest(url, func, type, fail, post, contenttype)
map.setMapTypeId(config.defaultMap); map.setMapTypeId(config.defaultMap);
clock = new MinecraftClock($('#clock'));
setTimeout(mapUpdate, config.updateRate); setTimeout(mapUpdate, config.updateRate);
} }

View File

@ -68,3 +68,19 @@ function getMinecraftHead(player,size,completed) {
completed(resizeImage(head,size)); completed(resizeImage(head,size));
} }
} }
function getMinecraftTime(servertime) {
servertime = parseInt(servertime);
return {
servertime: servertime,
days: parseInt((servertime+8000) / 24000),
// Assuming it is day at 8:00
hours: (parseInt(servertime / 1000)+8) % 24,
minutes: parseInt(((servertime / 1000) % 1) * 60),
seconds: parseInt(((((servertime / 1000) % 1) * 60) % 1) * 60),
day: servertime > 12000,
night: servertime <= 12000
};
}

View File

@ -87,6 +87,21 @@ a, a:visited, label {
#clock.night { background-image: url(clock_night.png); } #clock.night { background-image: url(clock_night.png); }
#clock.day { background-image: url(clock_day.png); } #clock.day { background-image: url(clock_day.png); }
#alert {
padding: 5px;
position: fixed;
margin: auto;
top: 0;
left: 0;
right: 0;
width: 25em;
text-align: center;
font: 14px/16px sans-serif;
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.3);
background-color: InfoBackground;
border-radius: 0 0 3px 3px;
}
.playerIcon { .playerIcon {
} }