Raised This Month: $ Target: $400
 0% 

[CSGO] Live game data (Open source)


  
 
 
Thread Tools Display Modes
Prev Previous Post   Next Post Next
Author Message
Lagoni
New Member
Join Date: Sep 2017
Old 09-06-2017 , 15:50   [CSGO] Live game data (Open source)
Reply With Quote #1

So I made this simple example which reflects some of the ingame events such as positions, kills, smokes for the de_dust map. Feel free to further develop, or use this for inspiration for your own projects. If you have any questions feel free to contact me here or on github.

If anybody have some optimization ideérs, feel free to let me know! Since this, was one of the only ways I could see, how to reflect the ingame data and control it on a webpage the way you choose to. Hope some of you find some inspiration from this or can use part of it

The project is achieved with Javascript, JQuery, Node.js, MySQL and sourcemod.

Github link for the project https://github.com/jonaslagoni/csgoLiveServer

Updating the position data for players
First lets break down the timer used to control the interval for players positions. Ill start off with the sourcemod plugin located here.


Code:
public Action Timer_player_positions(Handle timer){
//First I make sure that there are active players and not just an empty server. Since we dont want to update positions of no one.
	if(activePlayersCount != 0){
//Next I prepare the query for the database.
		StrCat(position_query, sizeof(position_query), "INSERT INTO positions (client_id, timestamp, pos_x, pos_y, pos_z) VALUES");
//This is used for determin if I already added a position to the query or not.
		new ran = false;
//Go through each of the players
		for(new i = 0; i < activePlayersCount; i++){
			new clientId = GetArrayCell(activePlayers, i);
			new client = GetClientOfUserId(clientId);
//Make sure they are in game and alive. Else we dont want to update their position
			if(IsClientInGame(client) && IsPlayerAlive(client)){
				if(ran){
					StrCat(position_query, sizeof(position_query), ",");
				}
				char player_walked_name[64];
				GetClientName(client, player_walked_name, sizeof(player_walked_name));
				new float:position[3];
				GetEntPropVector(client, Prop_Send, "m_vecOrigin", position);
				float pos_x = position[0];
				float pos_y = position[1];
				float pos_z = position[2];
				int timestamp = GetTime();
//Format the string with the correct values for this client
				Format(pp_query, sizeof(pp_query), " (%d, %d, %f, %f, %f)", clientId, timestamp, pos_x, pos_y, pos_z);
//Add the String to the query
				StrCat(position_query, sizeof(position_query), pp_query);
				ran = true;
			}
		}
		if(ran){
//When done end the query and send it async*
			StrCat(position_query, sizeof(position_query), ";");
			csgoDatabase.Query(T_queryDone, position_query);
//Reset the query for next time
			position_query = "";
		}
	}
	return Plugin_Continue;
}
When the position is updated from the game server the Node.js server takes over by checking each 100ms for new updates. The server code is located here. Ill walk you though it here:
Code:
//Using setInterval as a timer to get the data each 100ms
setInterval(function(){
  var query = "SELECT * FROM positions WHERE position_id > " + last_position_id;
  con.query(query, function(error, rows, fields){
    if(error) throw error;
//Check if the query returned some results
    if(rows.length > 0){
      console.log("found footstep");
//If there is only one new position only send 1 by socket to the clients
      if(rows.length == 1){
        io.emit('position', rows[0].pos_x, rows[0].pos_y, rows[0].pos_z, rows[0].client_id);
//Update the last retrieved position
        last_position_id = rows[0].position_id;
      }else{
//Since there are more then one position update send them all at once
        console.log("length = " + rows.length);
        var o = {};
        var key = '0';
        o[key] = [];
//Go though each position
        for(var i = 0; i < rows.length; i++){
          console.log("found footstep " + i + " of " + rows.length);
//Construct the data
          var data = {
            pos_x : rows[i].pos_x,
            pos_y : rows[i].pos_y,
            pos_z : rows[i].pos_z,
            client_id : rows[i].client_id
          };
//Push the data to the array
          o[key].push(data);
//Update the last retrieved position
          last_position_id = rows[i].position_id;
        }
//Send all the positions by socket
        io.emit('positions', o);
      }
    }
  });
}, 100);
When the Node.js server, located here, sends the message to the socket the client send the message to the map.js class located here.

Code:
//On a single position update
socket.on('position', function(pos_x, pos_y, pos_z, client_id){
    map.drawPlayer(pos_x, pos_y, pos_z, client_id);
});
//On multiple positions
socket.on('positions', function(data){
    map.drawPlayers(data);
});
Code:
function getPosX(pos_x){
//Correct location on the de_dust map for x-axis
  return ((Math.abs(pos_x+2850))/6.0)-10;
}
function getPosY(pos_y){
//Correct location on the de_dust map for y-axis
  return ((Math.abs(pos_y-4073))/6.0)-10;
}
  drawPlayer:function(pos_x, pos_y, pos_z, client_id){
//Get the correct positions of the user to reflect the correct position on the website
    var real_pos_x = getPosX(pos_x);
    var real_pos_y = getPosY(pos_y);
//Change the css to fit the correct position of the client
    $("#player".concat(client_id)).css("left", real_pos_x + "px");
    $("#player".concat(client_id)).css("top", real_pos_y + "px");
  },
  drawPlayers:function(data){
//Go through each of the positions in the array
    for(var i = 0; i < data['0'].length; i++){
//Get the correct positions of the user to reflect the correct position on the website
        var real_pos_x = getPosX(data['0'][i].pos_x);
        var real_pos_y = getPosY(data['0'][i].pos_y);
//Change the css to fit the correct position of the client
      $("#player".concat(data['0'][i].client_id)).css("left", real_pos_x + "px");
      $("#player".concat(data['0'][i].client_id)).css("top", real_pos_y + "px");
    }
  },
__________________

Last edited by Lagoni; 09-07-2017 at 07:28. Reason: Added tutorial on how I made the positioning work
Lagoni is offline
 



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 18:52.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode