/* 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 = '' + tilename + ''; 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 mapUpdate() { makeRequest(config.updateUrl + lasttimestamp, function(res) { var rows = res.split('\n'); var loggedin = new Array(); var showWarps = document.getElementById('showWarps').checked; var showSigns = document.getElementById('showSigns').checked; var showHomes = document.getElementById('showHomes').checked; var showSpawn = document.getElementById('showSpawn').checked; var firstRow = rows[0].split(' '); var lasttimestamp = firstRow[0]; servertime = firstRow[1]; delete rows[0]; var numwarps = 0; var numsigns = 0; var numhomes = 0; var numspawns = 0; var numplayers = 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]) }; loggedin[mi.id] = 1; if (mi.type == 'warp') numwarps++; if (mi.type == 'sign') numsigns++; if (mi.type == 'home') numhomes++; if (mi.type == 'spawn') numspawns++; if (mi.type == 'player') numplayers++; var hideMarker = ( (mi.type == 'warp' && showWarps == false) || (mi.type == 'sign' && showSigns == false) || (mi.type == 'home' && showHomes == false) || (mi.type == 'spawn' && showSpawn == false) ); if(mi.id == followPlayer) { map.panTo(fromWorldToLatLng(p[2], p[3], p[4])); } if(mi.id in markers) { var m = markers[mi.id]; if (hideMarker) { m.hide(); continue; } 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 = ' ' + mi.text + ''; }; 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); //if (hideMarker) // marker.hide(); 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'; getMinecraftHead(mi.text, 16, function(head) { head.className = 'playerIcon'; playerRow.icon = head; playerRow.insertBefore(head, playerRow.firstChild); }); var playerText = document.createElement('a'); playerText.appendChild(document.createTextNode(' ' + mi.text)); playerText.href = '#'; playerText.onclick = function(e) { plclick(mi.id); }; playerRow.appendChild(playerText); marker.playerRow = playerRow; playerlst.appendChild(playerRow); } } } 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 = (numwarps == 0)?'none':''; document.getElementById('signsDiv').style.display = (numsigns == 0)?'none':''; document.getElementById('homesDiv').style.display = (numhomes == 0)?'none':''; document.getElementById('spawnsDiv').style.display = (numspawns == 0)?'none':''; //document.getElementById('plist').style.display = (numplayers == 0)?'none':''; document.getElementById('controls').style.display = ((numwarps + numsigns + numhomes + numspawns) == 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 plclick(name) { if(name in markers) { if(name != followPlayer) plfollow(''); map.panTo(markers[name].getPosition()); } } function plfollow(name) { var icon; if(followPlayer == name) { icon = document.getElementById('icon_' + followPlayer); if(icon) icon.src = 'follow_off.png'; followPlayer = ''; return; } if(followPlayer) { icon = document.getElementById('icon_' + followPlayer); if(icon) icon.src = 'follow_off.png'; followPlayer = ''; } if(!name) return; icon = document.getElementById('icon_' + name); if(icon) icon.src = 'follow_on.png'; followPlayer = name; if(name in markers) { map.panTo(markers[name].getPosition()); } } 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; }