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

Last change on this file since 180 was 179, checked in by alloc, 10 years ago

Webserver files

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