@@ -41,6 +41,7 @@ import VSection from './../../Components/Section';
4141import L from " leaflet" ;
4242import {GestureHandling } from " leaflet-gesture-handling" ;
4343import " leaflet-rotatedmarker" ;
44+ import custom_icons from " ../../data/vehicles.json" ;
4445
4546(function (global ){
4647 let MarkerMixin = {
@@ -72,7 +73,8 @@ export default {
7273 data: this .t (' map.loading' ),
7374 connection: null ,
7475 isPaused: false ,
75- isDevelopment: false // For local development set it to true
76+ trackedPlayer: window .location .hash .substr (1 ),
77+ firstRefresh: true
7678 };
7779 },
7880 methods: {
@@ -86,10 +88,12 @@ export default {
8688 }
8789 },
8890 hostname (isSocket ) {
91+ const isDev = window .location .hostname === ' localhost' ;
92+
8993 if (isSocket) {
90- return this . isDevelopment ? ' ws://' + window .location .hostname + ' :8080/ ' : ' wss://' + window .location .hostname + ' :8443' ;
94+ return isDev ? ' ws://' + window .location .hostname + ' :8080' : ' wss://' + window .location .hostname + ' :8443' ;
9195 } else {
92- return this . isDevelopment ? ' http://' + window .location .hostname + ' :8080/ ' : ' https://' + window .location .hostname + ' :8443' ;
96+ return isDev ? ' http://' + window .location .hostname + ' :8080' : ' https://' + window .location .hostname + ' :8443' ;
9397 }
9498 },
9599 async doMapRefresh (server ) {
@@ -107,6 +111,8 @@ export default {
107111 const data = JSON .parse (event .data );
108112
109113 _this .renderMapData (data);
114+
115+ _this .firstRefresh = false ;
110116 } catch (e) {
111117 console .error (' Failed to parse socket message ' , e)
112118 }
@@ -121,22 +127,88 @@ export default {
121127 console .error (' Failed to connect to socket' , e);
122128 }
123129 },
130+ getVehicleType (vehicle ) {
131+ if (! vehicle) {
132+ return null ;
133+ }
134+
135+ let ret = {
136+ type: ' car' ,
137+ size: 23
138+ };
139+
140+ $ .each (custom_icons, function (type , cfg ) {
141+ if (cfg .models .includes (vehicle .model )) {
142+ ret .type = type;
143+ ret .size = cfg .size ;
144+ }
145+ });
146+
147+ return ret;
148+ },
149+ getIcon (player , isDriving , isPassenger , isInvisible ) {
150+ let size = {
151+ circle: 17 ,
152+ circle_red: 12 ,
153+ circle_green: 13
154+ };
155+
156+ let icon = new L.Icon (
157+ {
158+ iconUrl: ' /images/circle.png' ,
159+ iconSize: [size .circle , size .circle ]
160+ }
161+ );
162+
163+ if (isInvisible) {
164+ icon = new L.Icon (
165+ {
166+ iconUrl: ' /images/circle_green.png' ,
167+ iconSize: [size .circle_green , size .circle_green ]
168+ }
169+ );
170+ } else if (isDriving) {
171+ const info = this .getVehicleType (player .vehicle );
172+
173+ icon = new L.Icon (
174+ {
175+ iconUrl: ' /images/' + info .type + ' .png' ,
176+ iconSize: [info .size , info .size ]
177+ }
178+ );
179+ } else if (isPassenger) {
180+ icon = new L.Icon (
181+ {
182+ iconUrl: ' /images/circle_red.png' ,
183+ iconSize: [size .circle_red , size .circle_red ]
184+ }
185+ )
186+ }
187+
188+ return icon;
189+ },
124190 renderMapData (data ) {
125191 if (this .isPaused ) {
126192 return ;
127193 }
128194
195+ if (this .trackedPlayer && this .trackedPlayer in this .markers ) {
196+ this .map .dragging .disable ();
197+ } else {
198+ this .map .dragging .enable ();
199+ }
200+
129201 const conf = {
130202 game: {
131203 bounds: {
132- min: {x: - 2870 , y: 7000 },
133- max: {x: 4000 , y: - 3500 }
204+ min: {x: - 2862.10546875 , y: 7616.0966796875 },
205+ max: {x: 4195.29248046875 , y: - 3579.89013671875 }
134206 }
135207 },
136208 map: {
137209 bounds: {
138- min: {x: 85.5 , y: - 67.1 },
139- max: {x: 172.1 , y: - 199.4 }
210+ min: {x: 85.546875 , y: - 59.62890625 },
211+ max: {x: 174.2109375 , y: - 200.24609375 }
140212 }
141213 }
142214 };
@@ -147,52 +219,39 @@ export default {
147219
148220 return _this .coords (coords);
149221 };
150- const getIcon = (isDriving , isPassenger ) => {
151- const zoom = _this .map .getZoom ();
152- const zoomModifier = zoom === 7 ? 1.1 : 1 ;
153-
154- let icon = new L.Icon (
155- {
156- iconUrl: ' /images/circle.png' ,
157- iconSize: [17 * zoomModifier, 17 * zoomModifier],
158- iconAnchor: [(17 * zoomModifier) / 2 , (17 * zoomModifier) / 2 ]
159- }
160- );
161-
162- if (isDriving) {
163- icon = new L.Icon (
164- {
165- iconUrl: ' /images/car.png' ,
166- iconSize: [20 * zoomModifier, 20 * zoomModifier],
167- iconAnchor: [(20 * zoomModifier) / 2 , (20 * zoomModifier) / 2 ]
168- }
169- );
170- } else if (isPassenger) {
171- icon = new L.Icon (
172- {
173- iconUrl: ' /images/circle_red.png' ,
174- iconSize: [12 * zoomModifier, 12 * zoomModifier],
175- iconAnchor: [(12 * zoomModifier) / 2 , (12 * zoomModifier) / 2 ]
176- }
177- )
178- }
179-
180- return icon;
181- };
182222
183223 if (data && Array .isArray (data)) {
184224 if (this .map ) {
185225 const _this = this ;
186226 let markers = this .markers ;
187227
228+ let vehicles = {};
229+ $ .each (data, function (index , player ) {
230+ if (! (' character' in player) || ! player .character ) {
231+ player .character = {
232+ id: 0 ,
233+ fullName: ' N/A'
234+ };
235+ }
236+
237+ if (' vehicle' in player && player .vehicle && player .vehicle .driving ) {
238+ vehicles[player .vehicle .id ] = player .character .id === 0 ? ' Nobody' : player .character .fullName ;
239+ }
240+
241+ data[index] = player
242+ });
243+
188244 let validIds = [];
189245 $ .each (data, function (_ , player ) {
190246 const id = " player_" + player .character .id ,
191247 coords = convert (player .coords ),
192248 heading = _this .mapNumber (- player .heading , - 180 , 180 , 0 , 360 ) - 180 ,
193249 isDriving = ' vehicle' in player && player .vehicle && player .vehicle .driving ,
194250 isPassenger = ' vehicle' in player && player .vehicle && ! player .vehicle .driving ,
195- icon = getIcon (isDriving, isPassenger);
251+ isInvisible = ' invisible' in player && player .invisible ,
252+ speed = ' vehicle' in player && player .vehicle && ' speed' in player .vehicle ? player .vehicle .speed : null ,
253+ icon = _this .getIcon (player, isDriving, isPassenger, isInvisible),
254+ vehicle = _this .getVehicleType (player .vehicle );
196255
197256 validIds .push (id);
198257
@@ -215,19 +274,33 @@ export default {
215274 markers[id] = marker;
216275 }
217276
218- let extra = ' ' ;// '<br>Altitude: ' + Math.round(player.coords.z);
277+ let extra = ' <br>Altitude: ' + Math .round (player .coords .z ) + ' m' ;
278+ if (speed) {
279+ extra += ' <br>Speed: ' + Math .round (speed * 2.236936 ) + ' mph' ;
280+ }
281+
282+ let attributes = [];
283+ if (isInvisible) {
284+ attributes .push (' invisible' );
285+ markers[id].options .forceZIndex = 101 ;
286+ }
219287 if (isDriving) {
220- extra += ' <br>Is driving ' ;
288+ attributes . push ( ' driving ( ' + vehicle . type + ' ) ' ) ;
221289 markers[id].options .forceZIndex = 100 ;
222- // markers[id].setZIndexOffset(2);
223290 } else if (isPassenger) {
224- extra += ' <br>Is a passenger ' ;
291+ attributes . push ( ' passenger of ' + ( player . vehicle . id in vehicles ? vehicles[ player . vehicle . id ] : ' Nobody ' )) ;
225292 markers[id].options .forceZIndex = 102 ;
226- // markers[id].setZIndexOffset(3);
227293 } else {
228- extra += ' <br>Is on foot' ;
294+ attributes . push ( ' on foot' ) ;
229295 markers[id].options .forceZIndex = 101 ;
230- // markers[id].setZIndexOffset(1);
296+ }
297+ extra += ' <br><i>Is ' + attributes .shift () + (attributes .length > 0 ? ' and ' + attributes .join (' , ' ) : ' ' ) + ' </i>' ;
298+ if (_this .trackedPlayer === id) {
299+ extra += ' <br><br><a href="#" class="track-cid" data-trackid="stop"">' + _this .t (' map.stop_track' ) + ' </a>' ;
300+
301+ _this .map .setView (coords, _this .firstRefresh ? 6 : _this .map .getZoom ());
302+ } else {
303+ extra += ' <br><br><a href="#" class="track-cid" data-trackid="' + id + ' "">' + _this .t (' map.track' ) + ' </a>' ;
231304 }
232305
233306 markers[id]._popup .setContent (player .character .fullName + ' (<a href="/players/' + player .steamIdentifier + ' ">#' + player .character .id + ' </a>)' + extra);
@@ -264,8 +337,7 @@ export default {
264337
265338 L .Map .addInitHook (" addHandler" , " gestureHandling" , GestureHandling);
266339
267- const _this = this ,
268- url = this .hostname (false );
340+ const url = this .hostname (false );
269341 L .TileLayer .GTA = L .TileLayer .extend ({
270342 getTileUrl : function (coords ) {
271343 coords .x = coords .x < 0 ? 0 : coords .x ;
@@ -323,6 +395,24 @@ export default {
323395 this .map .on (' click' , function (e ) {
324396 console .log (' map' , e .latlng );
325397 });
398+
399+ const _this = this ;
400+ $ (' #map' ).on (' click' , ' .track-cid' , function (e ) {
401+ e .preventDefault ();
402+
403+ const track = $ (this ).data (' trackid' );
404+ if (track === ' stop' ) {
405+ _this .trackedPlayer = null ;
406+ window .location .hash = ' ' ;
407+ } else {
408+ _this .trackedPlayer = track;
409+ window .location .hash = track;
410+
411+ _this .map .closePopup ();
412+ }
413+ });
414+
415+ $ (' #map' ).append (' <style>.leaflet-marker-icon {transform-origin: center center !important;}</style>' );
326416 }
327417 },
328418 mounted () {
0 commit comments