Jump to content

Recommended Posts

Posted (edited)

Hello everyone! In this tutorial I will try to show you how to create a Web map of your server.

Stage 0 - Some usefull stuff

We need to walk around GTA map, so lets create a resource to make it easier:


mp.events.addCommand('veh', (player, veh)=> {
	mp.vehicles.new(veh, player.position)
}) // Create a vehicle 
mp.events.addCommand('tp', (player, _, x, y, z)=> {
	player.giveWeapon(0xFBAB5776, 2) // Parachute, you need this, trust me
	player.position = new mp.Vector3(parseInt(x), parseInt(y), parseInt(z))
}) // Teleport a player
mp.events.addCommand('pos', (player)=>{
	console.log(player.position.x + ' ' + player.position.y + ' ' + player.position.z)
}) // Get player coords at write it to console

Stage 1 - Frontend

Step 1:  Get a map image, you can find some good images here: 

https://gtaforums.com/topic/595113-high-resolution-maps-satellite-roadmap-atlas/

I will use 4096*4096 satellite map.

http://blog.damonpollard.com/wp-content/uploads/2013/09/GTAV_SATELLITE_4096x4096.png

Step 2: Create a html file for our map: 

<img src='http://blog.damonpollard.com/wp-content/uploads/2013/09/GTAV_SATELLITE_4096x4096.png' style="position: absolute">
<canvas id='map' style='height: 4096px; width: 4096px; position: absolute; z-index: 9999'>

This code adds a picture and then puts a canvas over it, so we can draw above our map.

Step 3: Lets make some calculations

0) First of all, install commands from Stage 0 to your gamemode and then connect to your server.

1) Open your map picture with Paint

2) Determine zero point

Teleport to (0, 0, 72) position and determine this location at your map inside paint (put pointer on it), write down coordinates 

rUnPR6g.png

3) Determine map scale

Choose two points at map. I will use the most northen island and LS Aiport

WtPB1TS.png

8LNc5h3.png

Write down 'paint' coordinates for both.

It is (1889, 232) (1570, 3939) for me (if you use map with another size, you will get different numbers). 

Calculate range between this coords, it is 3720.7002 for me.

Then go to GTA and walk to both points

ImXUTtF.jpg

Write /pos to output your position to console

34.01333999633789 7689.458984375 2.8789443969726562 - northen island

-933.9918823242188 -3570.4599609375 14.037487030029297 - airport corner

Then calculate distance between this points only with x and y axis.

Result: 11301.451622046046 (meters)

Now lets finally get map scale: for me it is 11301.451622046046 (meters) / 3720.7 (pixels) = 3.037861303705727 (meters per pixel)

4) Determine axises

Red is world coords, green - picture/html coords

HqIfzwi.png

 

Step 4: Lets start with a code

First of all, we need a function that converts world coordinates to picture coordinates.

const ZeroX = 1903
const ZeroY = 2690
const Scale = 3.037861303705727
function getPictureCoords(x, y) {
  x = x/Scale
  y = y/Scale
  return {x: ZeroX + x , y: ZeroY - y} // Invert Y-axis
}

You can test it by teleporting to random coords and then finding that place in paint

Now it's time to start drawing.

const ctx = document.getElementById('map').getContext('2d')

Lets make a function that draws a player marker (red circle and a name above it)

function drawPlayerMarker(x, y, name) {
	newCoords = getPictureCoords(x, y)
	x = newCoords.x
	y = newCoords.y
	ctx.fillStyle = 'red'
	ctx.beginPath()
	ctx.arc(x, y, 5, 0, 2 * Math.PI)
	ctx.fill()
	ctx.font = "25px Arial";
	ctx.fillText(name, x - 15, y - 15)
}

Lets test it!

mVPjXqD.jpg

It works!

Stage 2 - Backend

We will use socket.io to communicate between browser and server.

Step 0: Install express and socket.io packages.

Run windows command line -> change directory to your /server-files directory -> run npm install express npm install socket.io 

Step 1: Create express app

//load map.html and socket.io
var fs = require('fs')
const port = 3000
var mapHTML = fs.readFileSync("./webmap/map.html", "utf8")
var socketIO = fs.readFileSync("./webmap/socket.io.js", "utf8")
//create app
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
//listen 3000 port
http.listen(3000, function(){
  console.log('webMap is active at 3000 port!');
});
//send map.html and socket.io to every client
app.get('/', function (req, res) {
  res.send(mapHTML);
});
app.get('/socket.io.js', function (req, res) {
  res.send(socketIO);
})

Put your map.html file to /server-files/webmap folder

Then go to \server-files\node_modules\socket.io-client\dist, find socket.io.js file and put it to server-files/webmap folder

Step 2: Prepare and send data to client

function prepareAndSendPlayersData() {
	var toSend = []
	mp.players.forEach((player)=> {
		toSend.push({
			x: player.position.x,
			y: player.position.y,
			name: player.name
		})
	})
	sendPlayersData(toSend)
}

function sendPlayersData(data) {
	io.sockets.emit('playersData', data) // Send our data to every client
}

Step 3: Create interval

setInterval(prepareAndSendPlayersData, 200) // Update every 200 ms

 Stage 3 - Receiving data on client

Step 1: Add socket.io script to your html file

<script src="/socket.io.js"></script>

Step 2: Add variable and event to handle data

var playersData = []

var socket = io('localhost:3000') // Your server ip here

socket.on('playersData', (data) => {
	playersData = data
	redraw()
})

Step 3: Redraw map with new data

function redraw() {
	ctx.clearRect(0, 0, 4096, 4096);
	playersData.forEach((player)=> {
		drawPlayerMarker(player.x, player.y, player.name)
})

Thats all! You can run your server, then open browser and go to youserverip:3000 and test it.

HjVgqHf.jpg

map.js (server package)

Скрытый текст

//load map.html
var fs = require('fs')
var mapHTML = fs.readFileSync("./webmap/map.html", "utf8")
var socketIO = fs.readFileSync("./webmap/socket.io.js", "utf8")

//create app
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
//send map.html to every client
app.get('/', function (req, res) {
  res.send(mapHTML);
});
app.get('/socket.io.js', function (req, res) {
  res.send(socketIO);
})

http.listen(3000, function(){
  console.log('listening on *:3000');
});


function prepareAndSendPlayersData() {
	var toSend = []
	mp.players.forEach((player)=> {
		toSend.push({
			x: player.position.x,
			y: player.position.y,
			name: player.name
		})
	})
	sendPlayersData(toSend)
}

function sendPlayersData(data) {
	io.sockets.emit('playersData', data) // Send our data to every client
}

setInterval(prepareAndSendPlayersData, 200)

 

map.html (put it to server-files/webmap folder)

Скрытый текст

<img src='http://blog.damonpollard.com/wp-content/uploads/2013/09/GTAV_SATELLITE_4096x4096.png' style="position: absolute">
<canvas height='4096', width='4096', id='map' style='height: 4096px; width: 4096px; position: absolute; z-index: 9999'>
<script src="/socket.io.js"></script>
<script>
const ZeroX = 1903
const ZeroY = 2690
const Scale = 3.037861303705727
function getPictureCoords(x, y) {
  x = x/Scale
  y = y/Scale
  return {x: ZeroX + x , y: ZeroY - y} // Invert Y-axis
}

const ctx = document.getElementById('map').getContext('2d')
ctx.fillStyle = 'red'

function drawPlayerMarker(x, y, name) {
	newCoords = getPictureCoords(x, y)
	x = newCoords.x
	y = newCoords.y
	ctx.beginPath()
	ctx.arc(x, y, 5, 0, 2 * Math.PI)
	ctx.fill()
	ctx.font = "25px Arial";
	ctx.fillText(name, x - 15, y - 15)
}

var playersData = []

var socket = io('localhost:3000')

socket.on('playersData', (data) => {
	playersData = data
	redraw()
})

function redraw() {
	ctx.clearRect(0, 0, 4096, 4096);
	playersData.forEach((player)=> {
		drawPlayerMarker(player.x, player.y, player.name)
	})
}
</script>

 

This tutorial will be continued 

Have a good day!

Edited by Hanvod
  • Like 14
  • 2 years later...
Posted (edited)

To avoid additional confuses, I miscalculated zero pixel positions on map picture by picking the wrong house (fool!). Right position is 

const ZeroX = 1878.00;
const ZeroY = 2761.10;

 Credit to @SunTex from Discord for right positions.

(Cloudflare doesn't allow me to edit this thread for some reason)

Edited by Hanvod

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...