2

Yellow,

so, I'm making a multiplayer online game on node (for funzies) and I'm stuck on a problem for over a week now. Perhaps the solution is simple, but I'm oblivious to it. Long story short:

  1. Data gets sent from client to server, this emit happens every 16.66ms.
  2. Server receives them correctly and we collect all the data (lots of fireballs in this case). We save them in player.skills_to_execute array.
  3. Every 5 seconds, we copy the data to seperate array (player_information), because we are gona clean the current one, so it can keep collecting new data, and then we send all the collected data back to the client.

Problem is definitely on server side. Sometimes this works, and sometimes it doesn't. player_information is the array that I'm sending back to front, but before I send it, I do check with console.log on server if it does actually contain the data, and it does! But somehow that data gets deleted/overwritten right before sending it and it sends empty array (cause I check on frontend and I receive empty).

Code is fairly more complex, but I've minimized it here so it's easier to understand it.

This code stays on client side, and works as it should:

// front.js
socket.on("update-player-information", function(player_data_from_server){
   console.log( player_data_from_server.skills_to_execute );
});

socket.emit("update-player-information", {
    skills_to_execute: "fireball"
});

This code stays on server side, and works as it should:

// server.js    
socket.on("update-player-information", function(data){

   // only update if there are actually skills received
   // we dont want every request here to overwrite actual array with empty []                     // data.skills_to_execute = this will usually be 1 to few skills that are in need to be executed on a single client cycle
   // naturally, we receive multiple requests in these 5 seconds, 
   // so we save them all in player object, where it has an array for this

   if ( data.skills_to_execute.length > 0 ) {
      player.skills_to_execute.push( data.skills_to_execute );    
   }

});

Now this is the code, where shit hits the fan.

// server.js
// Update player information
setInterval(function(){
   // for every cycle, reset the bulk data that we are gona send, just to be safe
   var player_information = [];

   // collect the data from player
   player_information.push(
      { 
         skills_to_execute: player.skills_to_execute
      }
   );

   // we reset the collected actions here, cause they are now gona be sent to front.js
   // and we want to keep collecting new skills_to_execute that come in
   player.skills_to_execute = [];

   socket.emit("update-player-information", player_information);

}, 5000);

Perhaps anybody has any ideas?

Starwave
  • 2,352
  • 2
  • 23
  • 30
  • since you use `socket.io` it might fallback to ajax or other transportation methods, are you sure it happens in `websocket` – Gntem Mar 03 '16 at 11:40
  • Yup, `console.log(socket.conn.transport.name);` returns `websocket` – Starwave Mar 03 '16 at 12:04
  • If I comment out `player.skills_to_execute = [];`, then data gets transfered. It's a question of why does it clean off the array. – Starwave Mar 03 '16 at 12:06
  • you have to output more information it seems like it should work like you expect , but it doesn't , try `debug` module and output information on everything you do in your code, also try `node-inspector` and set a break on before `socket.emit` it should provide enough information – Gntem Mar 03 '16 at 18:34

1 Answers1

1

Copy the array by value instead of by reference.

Try this:

player_information.push(
  { 
     skills_to_execute: player.skills_to_execute.slice()
  }
);

Read more about copying arrays in JavaScript by value or by reference here: Copying array by value in JavaScript

Community
  • 1
  • 1
bolav
  • 6,938
  • 2
  • 18
  • 42