source: binary-improvements/webserver/js/index.js@ 188

Last change on this file since 188 was 186, checked in by alloc, 10 years ago

webfiles

  • Property svn:executable set to *
File size: 13.8 KB
Line 
1// ===============================================================================================
2// Constants
3
4var REGIONSIZE = 512;
5var CHUNKSIZE = 16;
6var TILESIZE = 128;
7var MAXZOOM = 4;
8
9var BAG_COLS = 8;
10var BAG_ROWS = 4;
11var BELT_COLS = 8;
12var INV_ITEM_WIDTH = 58;
13var INV_ITEM_HEIGHT = 40;
14
15
16function initMap() {
17 // ===============================================================================================
18 // 7dtd coordinate transformations
19
20 SDTD_Projection = {
21 project: function (latlng) {
22 return new L.Point(
23 (latlng.lat) / Math.pow(2, MAXZOOM),
24 (latlng.lng) / Math.pow(2, MAXZOOM) );
25 },
26
27 unproject: function (point) {
28 return new L.LatLng(
29 point.x * Math.pow(2, MAXZOOM),
30 point.y * Math.pow(2, MAXZOOM) );
31 }
32 };
33
34 SDTD_CRS = L.extend({}, L.CRS.Simple, {
35 projection: SDTD_Projection,
36 transformation: new L.Transformation(1, 0, -1, 0),
37
38 scale: function (zoom) {
39 return Math.pow(2, zoom);
40 }
41 });
42
43 var CoordToChunk = function(latlng) {
44 var x = Math.floor(((latlng.lat + 16777216) / CHUNKSIZE) - (16777216 / CHUNKSIZE));
45 var y = Math.floor(((latlng.lng + 16777216) / CHUNKSIZE) - (16777216 / CHUNKSIZE));
46 return L.latLng(x, y);
47 }
48
49 var CoordToRegion = function(latlng) {
50 var x = Math.floor(((latlng.lat + 16777216) / REGIONSIZE) - (16777216 / REGIONSIZE));
51 var y = Math.floor(((latlng.lng + 16777216) / REGIONSIZE) - (16777216 / REGIONSIZE));
52 return L.latLng(x, y);
53 }
54
55 var FormatCoord = function(latlng) {
56 return "" +
57 Math.abs(latlng.lng) + (latlng.lng>=0 ? " N" : " S") + " / " +
58 Math.abs(latlng.lat) + (latlng.lat>=0 ? " E" : " W");
59 }
60
61 var FormatRegionFileName = function(latlng) {
62 return "r." + latlng.lat + "." + latlng.lng + ".7rg";
63 }
64
65
66
67 // ===============================================================================================
68 // Map and basic tile layers
69
70 var tileTime = new Date().getTime();
71
72 map = L.map('map', {
73 zoomControl: false, // Added by Zoomslider
74 zoomsliderControl: true,
75 attributionControl: false,
76 crs: SDTD_CRS
77 }).setView([0, 0], Math.max(0, MAXZOOM-5));
78
79 var tileLayer = L.tileLayer('../map/{z}/{x}/{y}.png?t={time}', {
80 maxZoom:MAXZOOM+1,
81 minZoom: Math.max(0, MAXZOOM-5),
82 maxNativeZoom: MAXZOOM,
83 tileSize: TILESIZE,
84 continuousWorld: true,
85 tms: true,
86 unloadInvisibleTiles: false,
87 time: function() { return tileTime; }
88 }).addTo(map);
89
90 var tileLayerMiniMap = L.tileLayer('../map/{z}/{x}/{y}.png?t={time}', {
91 maxZoom: MAXZOOM,
92 minZoom: 0,
93 maxNativeZoom: MAXZOOM,
94 tileSize: TILESIZE,
95 continuousWorld: true,
96 tms: true,
97 unloadInvisibleTiles: false,
98 time: function() { return tileTime; }
99 });
100
101 var regionLayer = L.tileLayer.canvas({
102 maxZoom: MAXZOOM+1,
103 minZoom: 0,
104 maxNativeZoom: MAXZOOM+1,
105 tileSize: TILESIZE,
106 continuousWorld: true
107 });
108
109 regionLayer.drawTile = function(canvas, tilePoint, zoom) {
110 var blockWorldSize = TILESIZE * Math.pow(2, MAXZOOM-zoom);
111 var tileLeft = tilePoint.x * blockWorldSize;
112 var tileBottom = (-1-tilePoint.y) * blockWorldSize;
113 var blockPos = L.latLng(tileLeft, tileBottom);
114
115 var ctx = canvas.getContext('2d');
116
117 ctx.strokeStyle = "lightblue";
118 ctx.fillStyle = "lightblue";
119 ctx.lineWidth = 1;
120 ctx.font="14px Arial";
121
122 var lineCount = blockWorldSize / REGIONSIZE;
123 if (lineCount >= 1) {
124 var pos = 0;
125 while (pos < TILESIZE) {
126 // Vertical
127 ctx.beginPath();
128 ctx.moveTo(pos, 0);
129 ctx.lineTo(pos, TILESIZE);
130 ctx.stroke();
131
132 // Horizontal
133 ctx.beginPath();
134 ctx.moveTo(0, pos);
135 ctx.lineTo(TILESIZE, pos);
136 ctx.stroke();
137
138 pos += TILESIZE / lineCount;
139 }
140 ctx.fillText(FormatRegionFileName(CoordToRegion(blockPos)), 4, TILESIZE-5);
141 } else {
142 if ((tileLeft % REGIONSIZE) == 0) {
143 // Vertical
144 ctx.beginPath();
145 ctx.moveTo(0, 0);
146 ctx.lineTo(0, TILESIZE);
147 ctx.stroke();
148 }
149 if ((tileBottom % REGIONSIZE) == 0) {
150 // Horizontal
151 ctx.beginPath();
152 ctx.moveTo(0, TILESIZE);
153 ctx.lineTo(TILESIZE, TILESIZE);
154 ctx.stroke();
155 }
156 if ((tileLeft % REGIONSIZE) == 0 && (tileBottom % REGIONSIZE) == 0) {
157 ctx.fillText(FormatRegionFileName(CoordToRegion(blockPos)), 4, TILESIZE-5);
158 }
159 }
160
161 var pos = tileLeft;
162
163 }
164
165
166 // ===============================================================================================
167 // Reload control
168
169 L.Control.ReloadTiles = L.Control.extend({
170 options: {
171 position: 'bottomleft'
172 },
173
174 onAdd: function (map) {
175 var name = 'control-reloadtiles',
176 container = L.DomUtil.create('div', name + ' leaflet-bar');
177
178 this._map = map;
179
180 this._reloadbutton = this._createButton(
181 "Reload tiles", "Reload tiles",
182 name + "-btn", container, this._reload, this);
183
184 return container;
185 },
186
187 onRemove: function (map) {
188 },
189
190 _reload: function (e) {
191 tileTime = new Date().getTime();
192 tileLayer.redraw();
193 tileLayerMiniMap.redraw();
194 },
195
196 _createButton: function (html, title, className, container, fn, context) {
197 var link = L.DomUtil.create('a', className, container);
198 link.innerHTML = html;
199 link.href = '#';
200 link.title = title;
201
202 var stop = L.DomEvent.stopPropagation;
203
204 L.DomEvent
205 .on(link, 'click', stop)
206 .on(link, 'mousedown', stop)
207 .on(link, 'dblclick', stop)
208 .on(link, 'click', L.DomEvent.preventDefault)
209 .on(link, 'click', fn, context)
210 .on(link, 'click', this._refocusOnMap, context);
211
212 return link;
213 }
214
215 });
216
217 new L.Control.ReloadTiles({
218 }).addTo(map);
219
220
221 // ===============================================================================================
222 // Coordinates control
223 // <div id="info">
224 // MouseCoords: <span id="pos"></span>
225 // </div>
226
227 L.Control.Coordinates = L.Control.extend({
228 options: {
229 position: 'bottomleft'
230 },
231
232 onAdd: function (map) {
233 var name = 'control-coordinates',
234 container = L.DomUtil.create('div', name + ' leaflet-bar');
235
236 container.innerHTML = "- N / - E"
237
238 this._map = map;
239 this._div = container;
240
241 map.on('mousemove', this._onMouseMove, this);
242
243 return container;
244 },
245
246 onRemove: function (map) {
247 },
248
249 _onMouseMove: function (e) {
250 this._div.innerHTML = FormatCoord(e.latlng);
251 }
252
253
254 });
255
256 new L.Control.Coordinates({
257 }).addTo(map);
258
259
260
261
262 // ===============================================================================================
263 // Overlays and controls
264
265 var playersOnlineMarkerGroup = L.layerGroup();
266 var playersOfflineMarkerGroup = L.markerClusterGroup({
267 maxClusterRadius: function(zoom) { return zoom == MAXZOOM ? 10 : 50; }
268 });
269
270
271 var landClaimsGroup = L.layerGroup();
272 var landClaimsClusterGroup = L.markerClusterGroup({
273 disableClusteringAtZoom: MAXZOOM,
274 singleMarkerMode: true,
275 maxClusterRadius: 50
276 });
277 var landClaimsRectGroup = L.layerGroup();
278 landClaimsGroup.addLayer(landClaimsClusterGroup);
279 landClaimsGroup.addLayer(landClaimsRectGroup);
280 var maxZoomForCluster = 4;
281
282 var baseLayers = {
283 //"Map": tileLayer
284 };
285
286 var overlays = {
287 "Land claims" : landClaimsGroup,
288 "Players (offline) (<span id='mapControlOfflineCount'>0</span>)" : playersOfflineMarkerGroup,
289 "Players (online) (<span id='mapControlOnlineCount'>0</span>)" : playersOnlineMarkerGroup,
290 "Region files": regionLayer,
291 };
292
293
294 L.control.layers(baseLayers, overlays, {
295 collapsed: false
296 }).addTo(map);
297
298 //map.on('mousemove', function(e) {
299 // L.DomUtil.get('pos').textContent = FormatCoord(e.latlng);
300 //});
301
302 var miniMap = new L.Control.MiniMap(tileLayerMiniMap, {
303 zoomLevelOffset: -6,
304 toggleDisplay: true
305 }).addTo(map);
306
307
308 var playersMappingList = {};
309
310
311
312 // ===============================================================================================
313 // Inventory dialog
314
315 var showInv = function(steamid) {
316 $.getJSON( "../api/getplayerinventory", { steamid: steamid })
317 .done(function(data) {
318 $("#invPlayerName").text(playersMappingList[steamid].name);
319 for (var y = 0; y < BAG_ROWS; y++) {
320 for (var x = 0; x < BAG_COLS; x++) {
321 if (data.bag[y*BAG_COLS+x].count > 0) {
322 $("#bagField"+x+"_"+y).attr("style", "background-image: url(itemimages/" + data.bag[y*BAG_COLS+x].name + ".png);");
323 $("#bagFieldText"+x+"_"+y).text(data.bag[y*BAG_COLS+x].count);
324 } else {
325 $("#bagField"+x+"_"+y).attr("style", "background-image: none;");
326 $("#bagFieldText"+x+"_"+y).text("");
327 }
328 }
329 }
330
331 for (var x = 0; x < BELT_COLS; x++) {
332 if (data.belt[x].count > 0) {
333 $("#beltField"+x).attr("style", "background-image: url(itemimages/" + data.belt[x].name + ".png);");
334 $("#beltFieldText"+x).text(data.belt[x].count);
335 } else {
336 $("#beltField"+x).attr("style", "background-image: none;");
337 $("#beltFieldText"+x).text("");
338 }
339 }
340
341 $( "#playerInventoryDialog" ).css("z-index", "1010").dialog({
342 modal: true,
343 width: BAG_COLS*(INV_ITEM_WIDTH+14) + 20,
344 buttons: {
345 Ok: function() {
346 $( this ).dialog( "close" );
347 }
348 }
349 });
350 })
351 .fail(function(jqxhr, textStatus, error) {
352 console.log("Error fetching player inventory");
353 })
354 .always(function() {
355 });
356 };
357
358 for (var y = 0; y < BAG_ROWS; y++) {
359 $("#bagTable").append("<tr id=\"bagRow"+y+"\"></tr>");
360 for (var x = 0; x < BAG_COLS; x++) {
361 $("#bagRow"+y).append(
362 "<td class=\"invField\" id=\"bagField"+x+"_"+y+"\">" +
363 "<span class=\"invFieldText\" id=\"bagFieldText"+x+"_"+y+"\"></span>" +
364 "</td>");
365 }
366 }
367
368 $("#beltTable").append("<tr id=\"beltRow0\"></tr>");
369 for (var x = 0; x < BELT_COLS; x++) {
370 $("#beltRow0").append(
371 "<td class=\"invField\" id=\"beltField"+x+"\">" +
372 "<span class=\"invFieldText\" id=\"beltFieldText"+x+"\"></span>" +
373 "</td>");
374 }
375
376
377
378 // ===============================================================================================
379 // Player markers
380
381 $(".leaflet-popup-pane").on('click.action', '.inventoryButton', function(event) {
382 showInv($(this).data('steamid'));
383 });
384
385 var setPlayerMarkers = function(data) {
386 var online = 0;
387 var offline = 0;
388 $.each( data, function( key, val ) {
389 var marker;
390 if (playersMappingList.hasOwnProperty(val.steamid)) {
391 marker = playersMappingList[val.steamid].currentPosMarker;
392 marker.setLatLng([val.position.x, val.position.z]);
393 } else {
394 marker = L.marker([val.position.x, val.position.z]).bindPopup(
395 "Player: " + val.name + "<br/>" +
396 "<a class='inventoryButton' data-steamid='"+val.steamid+"'>Show inventory</a>"
397 );
398 playersMappingList[val.steamid] = { online: !val.online };
399 }
400 if (playersMappingList[val.steamid].online != val.online) {
401 if (val.online) {
402 marker.setOpacity(1.0);
403 playersOfflineMarkerGroup.removeLayer(marker);
404 playersOnlineMarkerGroup.addLayer(marker);
405 } else {
406 marker.setOpacity(0.5);
407 playersOnlineMarkerGroup.removeLayer(marker);
408 playersOfflineMarkerGroup.addLayer(marker);
409 }
410 }
411 val.currentPosMarker = marker;
412 playersMappingList[val.steamid] = val;
413
414 if (val.online)
415 online++;
416 else
417 offline++;
418 });
419 $( "#mapControlOnlineCount" ).text( online );
420 $( "#mapControlOfflineCount" ).text( offline );
421 }
422
423 var updatePlayerEvent = function() {
424 $.getJSON( "../api/getplayerslocation")
425 .done(setPlayerMarkers)
426 .fail(function(jqxhr, textStatus, error) {
427 console.log("Error fetching players list");
428 })
429 .always(function() {
430 window.setTimeout(updatePlayerEvent, 2000);
431 });
432 }
433
434 window.setTimeout(updatePlayerEvent, 500);
435
436
437
438 // ===============================================================================================
439 // Land claim markers
440
441 var setLandClaims = function(data) {
442 landClaimsClusterGroup.clearLayers();
443 landClaimsRectGroup.clearLayers();
444
445 var claimPower = Math.floor(Math.log(data.claimsize) / Math.LN2);
446 var maxClusterZoomUnlimited = MAXZOOM - (claimPower - 3);
447 var maxClusterZoomLimitedMax = Math.min(maxClusterZoomUnlimited, MAXZOOM+1);
448 maxZoomForCluster = Math.max(maxClusterZoomLimitedMax, 0);
449
450 checkClaimClustering({target: map});
451
452 var sizeHalf = Math.floor(data.claimsize / 2);
453
454 $.each( data.claimowners, function( key, val ) {
455 var steamid = val.steamid;
456 var active = val.claimactive;
457 var color = active ? "#55ff55" : "#ff0000";
458
459 $.each( val.claims, function( key, val ) {
460 var pos = L.latLng(val.x, val.z);
461 var bounds = L.latLngBounds(L.latLng(val.x - sizeHalf, val.z - sizeHalf), L.latLng(val.x + sizeHalf, val.z + sizeHalf));
462 var r = L.rectangle(bounds, {color: color, weight: 1, opacity: 0.8, fillOpacity: 0.15});
463 var m = L.marker(pos, { clickable: false, keyboard: false, zIndexOffset:-1000, iconSize: [0,0], icon: L.divIcon({className: 'invisIcon', iconSize:[0,0]}) });
464 if (playersMappingList.hasOwnProperty(steamid)) {
465 r.bindPopup("Owner: " + playersMappingList[steamid].name);
466 } else {
467 r.bindPopup("Owner: unknown ("+steamid+")");
468 }
469 landClaimsRectGroup.addLayer(r);
470 landClaimsClusterGroup.addLayer(m);
471 });
472 });
473 }
474
475 var updateClaimsEvent = function() {
476 $.getJSON( "../api/getlandclaims")
477 .done(setLandClaims)
478 .fail(function(jqxhr, textStatus, error) {
479 console.log("Error fetching land claim list");
480 })
481 .always(function() {
482 //updateClaimTimer = window.setTimeout(updateClaimsEvent, 3000);
483 });
484 }
485
486
487
488 // ===============================================================================================
489 // Layer events
490
491 var updateClaimTimer;
492 map.on('overlayadd', function(e) {
493 if (e.layer == landClaimsGroup) {
494 updateClaimsEvent();
495 }
496 });
497
498 map.on('overlayremove', function(e) {
499 if (e.layer == landClaimsGroup) {
500 //window.clearTimeout(updateClaimTimer);
501 }
502 });
503
504 var checkClaimClustering = function(e) {
505 if (e.target._zoom >= maxZoomForCluster) {
506 landClaimsGroup.removeLayer(landClaimsClusterGroup);
507 } else {
508 landClaimsGroup.addLayer(landClaimsClusterGroup);
509 }
510 };
511
512 map.on('zoomend', checkClaimClustering);
513
514}
515
516
517
518$.getJSON( "../map/mapinfo.json")
519.done(function(data) {
520 TILESIZE = data.blockSize;
521 MAXZOOM = data.maxZoom;
522 initMap();
523})
524.fail(function(jqxhr, textStatus, error) {
525 console.log("Error fetching map information");
526})
527.always(function() {
528 //updateClaimTimer = window.setTimeout(updateClaimsEvent, 3000);
529});
530
Note: See TracBrowser for help on using the repository browser.