dynmap/web/map.js

458 lines
12 KiB
JavaScript

/* generic function for making an XMLHttpRequest
* url: request URL
* func: callback function for success
* type: 'text' by default (callback is called with response text)
* otherwise, callback is called with a parsed XML dom
* fail: callback function for failure
* 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') {
http_request.onreadystatechange = function() {
if(http_request.readyState == 4) {
if(http_request.status == 200) {
func(http_request.responseText);
} else {
fail(http_request);
}
}
}
} else {
http_request.onreadystatechange = function() {
if(http_request.readyState == 4) {
if(http_request.status == 200) { func(http_request.responseXML); } else {
fail(http_request);
}
}
}
}
if(typeof(post) != 'undefined') {
http_request.open('POST', url, true);
if(typeof(contenttype) != 'undefined')
http_request.setRequestHeader("Content-Type", contenttype);
http_request.send(post);
} else {
http_request.open('GET', url, true);
http_request.send(null);
}
}
var config = {
tileUrl: setup.tileUrl,
updateUrl: setup.updateUrl,
tileWidth: 128,
tileHeight: 128,
updateRate: setup.updateRate,
zoomSize: [ 128, 128, 256, 512 ]
};
function MCMapProjection() {
}
MCMapProjection.prototype.fromLatLngToPoint = function(latLng) {
var x = (latLng.lng() * config.tileWidth)|0;
var y = (latLng.lat() * config.tileHeight)|0;
if(map.zoom == 0) {
x += config.tileWidth / 2;
}
return new google.maps.Point(x, y);
};
MCMapProjection.prototype.fromPointToLatLng = function(point) {
var x = point.x;
if(map.zoom == 0)
x -= config.tileWidth / 2;
var lng = x / config.tileWidth;
var lat = point.y / config.tileHeight;
return new google.maps.LatLng(lat, lng);
};
function fromWorldToLatLng(x, y, z)
{
var dx = +x;
var dy = +y - 127;
var dz = +z;
var px = dx + dz;
var py = dx - dz - dy;
var lng = -px / config.tileWidth / 2 + 0.5;
var lat = py / config.tileHeight / 2;
return new google.maps.LatLng(lat, lng);
}
function mcMapType() {
}
var tileDict = new Array();
var lastSeen = new Array();
function tileUrl(tile, always) {
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 {
return config.tileUrl + tile + '.png?0';
}
}
function imgSubst(tile) {
if(!(tile in tileDict))
return;
var src = tileUrl(tile);
var t = tileDict[tile];
t.src = src;
t.style.display = '';
t.onerror = function() {
setTimeout(function() {
t.src = tileUrl(tile, 1);
}, 1000);
t.onerror = '';
}
}
var caveMode = false;
function caveSwitch()
{
caveMode = !caveMode;
if(caveMode) {
cavebtn.src = 'cave_on.png';
map.setMapTypeId('cavemap');
} else {
cavebtn.src = 'cave_off.png';
map.setMapTypeId('mcmap');
}
}
mcMapType.prototype.tileSize = new google.maps.Size(config.tileWidth, config.tileHeight);
mcMapType.prototype.minZoom = 0;
mcMapType.prototype.maxZoom = 3;
mcMapType.prototype.getTile = function(coord, zoom, doc) {
var img = doc.createElement('IMG');
img.onerror = function() { img.style.display = 'none'; }
img.style.width = config.zoomSize[zoom] + 'px';
img.style.height = config.zoomSize[zoom] + 'px';
img.style.borderStyle = 'none';
var pfx = caveMode ? "c" : "";
if(zoom > 0) {
var tilename = pfx + "t_" + (- coord.x * config.tileWidth) + '_' + coord.y * config.tileHeight;
} else {
var tilename = pfx + "zt_" + (- coord.x * config.tileWidth * 2) + '_' + coord.y * config.tileHeight * 2;
}
tileDict[tilename] = img;
var url = tileUrl(tilename);
img.src = url;
//img.style.background = 'url(' + url + ')';
//img.innerHTML = '<small>' + tilename + '</small>';
return img;
}
var markers = new Array();
var lasttimestamp = 0;
var followPlayer = '';
var lst;
var plistbtn;
var cavebtn;
var lstopen = true;
var oldplayerlst = '[Connecting]';
var servertime = 0;
function updateMarker(mi) {
if(mi.id in markers) {
var m = markers[mi.id];
if (!mi.visible) {
m.hide();
return;
}
else {
m.show();
}
var converted = mi.position;
m.setPosition(mi.position);
} else {
var contentfun = function(div,mi) {
div.className = 'Marker ' + mi.type + 'Marker';
div.innerHTML = '<img src="' + mi.type + '.png" /> <span>' + mi.text + '</span>';
};
if (mi.type == 'player') {
contentfun = function(div, mi) {
div.className = 'Marker playerMarker';
var span = document.createElement('span');
span.className = 'playerName';
span.appendChild(document.createTextNode(mi.text));
div.appendChild(span);
getMinecraftHead(mi.text, 32, function(head) {
head.className = 'playerIcon';
div.insertBefore(head, div.firstChild);
});
};
}
var marker = new CustomMarker(converted, map, contentfun, mi);
marker.markerType = mi.type;
markers[mi.id] = marker;
if (mi.type == 'player') {
var playerRow = document.createElement('div');
playerRow.id = 'playerrow_' + mi.text;
playerRow.className = 'playerrow';
var followButton = document.createElement('input');
followButton.type = 'checkbox';
followButton.name = 'followPlayer';
followButton.checked = false;
followButton.value = mi.text;
marker.followButton = followButton;
followButton.className = 'followButton';
followButton.onclick = function(e) {
plfollow(mi.id != followPlayer ? mi.id : '');
};
playerRow.appendChild(followButton);
var playerIconContainer = document.createElement('span');
playerRow.appendChild(playerIconContainer);
getMinecraftHead(mi.text, 16, function(head) {
head.className = 'playerIcon';
playerRow.icon = head;
playerIconContainer.appendChild(head);
});
var playerText = document.createElement('a');
playerText.appendChild(document.createTextNode(mi.text));
playerText.href = '#';
playerText.onclick = function(e) { map.panTo(markers[mi.id].getPosition()); };
playerRow.appendChild(playerText);
marker.playerRow = playerRow;
var playerlst = document.getElementById('playerlst');
playerlst.appendChild(playerRow);
}
}
if(mi.id == followPlayer) {
map.panTo(markers[mi.id].getPosition());
}
}
function mapUpdate()
{
makeRequest(config.updateUrl + lasttimestamp, function(res) {
var typeVisibleMap = {
'warp': document.getElementById('showWarps').checked,
'sign': document.getElementById('showSigns').checked,
'home': document.getElementById('showHomes').checked,
'spawn': document.getElementById('showSpawn').checked
};
var typeCount = {};
var rows = res.split('\n');
var loggedin = new Array();
var firstRow = rows[0].split(' ');
var lasttimestamp = firstRow[0];
servertime = firstRow[1];
delete rows[0];
for(var line in rows) {
var p = rows[line].split(' ');
if (p[0] == '') continue;
if(p.length == 5) {
var mi = {
id: p[0] + '_' + p[1],
text: p[0],
type: p[1],
position: fromWorldToLatLng(p[2], p[3], p[4]),
visible: ((p[1] in typeVisibleMap) ? typeVisibleMap[p[1]] : true)
};
updateMarker(mi);
loggedin[mi.id] = 1;
if (!mi.type in typeCount) typeCount[mi.type] = 0;
typeCount[mi.type]++;
} else if(p.length == 3) {
if(p[2] == 't') {
lastSeen['t_' + p[0]] = lasttimestamp;
lastSeen['zt_' + p[1]] = lasttimestamp;
if(!caveMode) {
imgSubst('t_' + p[0]);
imgSubst('zt_' + p[1]);
}
} else {
lastSeen['ct_' + p[0]] = lasttimestamp;
lastSeen['czt_' + p[1]] = lasttimestamp;
if(caveMode) {
imgSubst('ct_' + p[0]);
imgSubst('czt_' + p[1]);
}
}
}
}
var time = {
hours: parseInt(servertime / 1000),
minutes: parseInt(((servertime / 1000) % 1) * 60),
seconds: parseInt(((((servertime / 1000) % 1) * 60) % 1) * 60)
};
var clock = document.getElementById('clock');
clock.className = (servertime > 12000 ? 'night' : 'day');
clock.innerText = formatTime(time);
for(var m in markers) {
if(!(m in loggedin)) {
markers[m].remove(null);
if (markers[m].markerType == 'player') {
playerlst.removeChild(markers[m].playerRow);
}
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':'';
}, '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() {
lst = document.getElementById('lst');
plistbtn = document.getElementById('plistbtn');
cavebtn = document.getElementById('cavebtn');
var mapOptions = {
zoom: 1,
center: new google.maps.LatLng(0, 1),
navigationControl: true,
navigationControlOptions: {
style: google.maps.NavigationControlStyle.DEFAULT
},
scaleControl: false,
mapTypeControl: false,
streetViewControl: false,
mapTypeId: 'mcmap',
backgroundColor: '#000'
};
map = new google.maps.Map(document.getElementById("mcmap"), mapOptions);
mapType = new mcMapType();
mapType.projection = new MCMapProjection();
caveMapType = new mcMapType();
caveMapType.projection = new MCMapProjection();
map.zoom_changed = function() {
mapType.tileSize = new google.maps.Size(config.zoomSize[map.zoom], config.zoomSize[map.zoom]);
caveMapType.tileSize = mapType.tileSize;
};
google.maps.event.addListener(map, 'dragstart', function(mEvent) {
plfollow('');
});
google.maps.event.addListener(map, 'zoom_changed', function() {
makeLink();
});
google.maps.event.addListener(map, 'center_changed', function() {
makeLink();
});
map.dragstart = plfollow('');
map.mapTypes.set('mcmap', mapType);
map.mapTypes.set('cavemap', caveMapType);
map.setMapTypeId('mcmap');
mapUpdate();
}
function plistopen() {
if(lstopen) {
lstopen = false;
lst.style.display = 'none';
lst.style.visibility = 'hidden';
plistbtn.src = 'list_off.png';
} else {
lstopen = true;
lst.style.display = '';
lst.style.visibility = '';
plistbtn.src = 'list_on.png';
}
}
function plfollow(name) {
$('.followButton').removeAttr('checked');
if(name in markers) {
var m = markers[name];
$(m.followButton).attr('checked', 'checked');
map.panTo(m.getPosition());
}
followPlayer = name;
}
function makeLink() {
var a=location.href.substring(0,location.href.lastIndexOf("/")+1)
+ "?lat=" + map.getCenter().lat().toFixed(6)
+ "&lng=" + map.getCenter().lng().toFixed(6)
+ "&zoom=" + map.getZoom();
document.getElementById("link").innerHTML = a;
}
//remove item (string or number) from an array
function removeItem(originalArray, itemToRemove) {
var j = 0;
while (j < originalArray.length) {
// alert(originalArray[j]);
if (originalArray[j] == itemToRemove) {
originalArray.splice(j, 1);
} else { j++; }
}
// assert('hi');
return originalArray;
}