ignoxx / SocketIO-GMS2-Extension

Socket.io extension for GameMaker: Studio 2 (HTML5)
https://ignoxx.dev/socketio
MIT License
45 stars 16 forks source link

Getting the player names and number from the server? #6

Closed ItsDedSec00 closed 4 years ago

ItsDedSec00 commented 4 years ago

When I try to transfer the array players from the server to the client it has problems processing the array. Do you have to send each player name individually or can you send arrays as well?

ignoxx commented 4 years ago

Hey, you can send an array of players, make sure you send this array as a JSON string so you can decode it to a ds_map.

For example: Server:

var players = [..]
var json_string = JSON.stringify(players)

Client

// Decode the received JSON string to DSMap
var data = json_decode(my_just_received_json_string);

data[? "default"] will contain the list of players, you can iterate over them now. (The "default" key gets added automatically if you dont provide any key)

Does it resolve your issue?

ItsDedSec00 commented 4 years ago

I'm still learning .js scripts, but I already had the idea. Then I get this error:

PS E:\Users\David\Desktop\Socket IO> node .\sampleserver.js
Listening on port 3000
Player "player677", with ID: 0 created!
E:\Users\David\Desktop\Socket IO\sampleserver.js:87
                var json_string = JSON.stringify(players)
                                       ^

TypeError: Converting circular structure to JSON
    --> starting at object with constructor 'Namespace'
    |     property 'server' -> object with constructor 'Server'
    |     property 'nsps' -> object with constructor 'Object'
    --- property '/' closes the circle
    at JSON.stringify (<anonymous>)
    at Socket.<anonymous> (E:\Users\David\Desktop\Socket IO\sampleserver.js:87:26)
    at Socket.emit (events.js:311:20)
    at E:\Users\David\Desktop\Socket IO\node_modules\socket.io\lib\socket.js:528:12
    at processTicksAndRejections (internal/process/task_queues.js:79:11)
PS E:\Users\David\Desktop\Socket IO>

This is my server script:

   client.on('position_update', (data) => {
        data = JSON.parse(data);

        player.x = data.x;
        player.y = data.y;

        var json_string = JSON.stringify(players)

        client.broadcast.emit('position_update', player.toString());
        client.broadcast.emit('player_list',json_string);
    });

And this my Client: gmcallback_sio_on_player_list()

var data = json_decode(argument[0]);
global.playerlist = data[? "default"] 
ignoxx commented 4 years ago

Assuming your player class is like the one from the example project:

Try to send the player without the socket object. The reason why we use player.toString() is that we get rid of that socket and I can imagine that this is causing the circular structure error.

Maybe it'll also work if you use the same replacer function in this line:

var json_string = JSON.stringify(players, replacer)

ItsDedSec00 commented 4 years ago

Server:

    });

    // Broadcast our position to all players, ourself NOT included
    // This is just an example project, we don't care if the client cheats. But you might consider also sending your own position to yourself for security/sync reasons
    // it depends on your project, e.g. if player position is important on client side
    client.on('position_update', (data) => {
        data = JSON.parse(data);

        player.x = data.x;
        player.y = data.y;

        client.broadcast.emit('position_update', player.toString());
        client.broadcast.emit('player_list',players.toString());
    });

Script:

var resultMap = json_decode(argument[0]);
var list = ds_map_find_value(resultMap, "default");
var size = ds_list_size(list);
for (var n = 0; n < ds_list_size(list); n++;)
   {
   var map = ds_list_find_value(list, n);
   var curr = ds_map_find_first(map);
   while (is_string(curr))
      {
      global.playerlist[n] = ds_map_find_value(map, "username");
      curr = ds_map_find_next(map, curr);
      }
   ds_map_destroy(map);
   }
ds_list_destroy(list);
ds_map_destroy(resultMap);

Draw:

len = array_length_1d(global.playerlist)
if len>0
{
    for(var i=0; i<len; i++)
    {
        draw_text(x,y+10*i,global.playerlist[i])
    }
}

draw_text(x,y+10*i,global.debug)

Result:

Only "undefined" is displayed. No other text or number. Also the console does not display an error.

ItsDedSec00 commented 4 years ago

I solved the problem differently, it's not a problem now but rather a question: Can I somehow find out how many players are really online right now?

ignoxx commented 4 years ago

Converting a list to string will not return a JSON-string, that's why you get "undefined" displayed in your client. Take a look to the toString() function of the Player class in server.

It can help a lot to output the data you just received from the server<->client in order to understand why it's not working :)

Great to hear that you came up with a solution! Can you please post your solution here in case other people experiencing the same issue? Thanks :)

About your other question:

  1. You can count the amount of player-objects ingame (client)
  2. or you check the players-list size (server) and tell it to the client, make sure that you remove the player from the list if he disconnects