• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

GameMaker Having problems with gameserver sending udp packets to clients

BMatjasic

Member
Hello dear GMC Community,

I'm having few issues last days while working on the Gameserver, which I've made working with TCP, but since TCP is not reliable for game servers, I've attempted to rewrite the server to support UDP. So what's the case?
I've successfully managed to send the packets to server and also broadcast them to clients with using a function: network_send_broadcast();
After that I've tried to implement my own function for data broadcast, so I did the following:
script: message_broadcast(socket, port);
Code:
var s = argument0;
var p = argument1;



for(var i = 0; i < ds_list_size(playerList); i++) {
    var map = ds_list_find_value(playerList, i);
    var soc = ds_map_find_value(map, "socket");
    var _ip = ds_map_find_value(map, "ip");

    if(s != soc) {
    network_send_udp(soc, _ip, p, m_buffer, buffer_tell(m_buffer));
    }
}
So I have figured out that the second client gets the data of the first player being there, but after that, it doesn't react to any of the inputs. So that means that the master server RECEIVES information, but doesn't want to deliver it to all of the clients or even any :(


I've really been wondering what's the case here. Am I missing something?

CODE FOR CLIENT-SERVER IN SPOILER BELOW:

Client-side sending: (example of keyboard_check(vk_left) )

Code:
x-=3;
buffer_seek(global.buffer, buffer_seek_start, 0);
buffer_write(global.buffer, buffer_u8, 1);//1 x = 1
buffer_write(global.buffer, buffer_string, global.username);
buffer_write(global.buffer, buffer_u16, x);

network_send_udp(global.socket, global.ip, global.port,  global.buffer, buffer_tell(global.buffer));
obj_client async event:

Code:
/// @description Insert description here
// You can write your code in this editor
var type_event = ds_map_find_value(async_load, "type");

switch(type_event) {
    
case network_type_data:
rec_buffer = ds_map_find_value(async_load, "buffer");
buffer_seek(rec_buffer, buffer_seek_start, 0);

var mid = buffer_read(rec_buffer, buffer_u8);
switch(mid) {



case 0: //new player has joined

    var _name = buffer_read(rec_buffer, buffer_string);
    var xx = buffer_read(rec_buffer, buffer_u16);
    var yy = buffer_read(rec_buffer, buffer_u16);
    if(!_name == global.username)  {
    var ins = instance_create_depth(xx,yy,50, obj_player_other);
    ins.name = _name;
    }
break;

case 1:

    var pname = buffer_read(rec_buffer, buffer_string);
    if(!pname == global.username) {
    var ins = instance_create_depth(55, 55, 50, obj_player_other);
    ins.name = pname;
    }
    show_debug_message("creating player: "+string(pname));
break;

case 2: //update position

    var _name = buffer_read(rec_buffer, buffer_string);
    var xx = buffer_read(rec_buffer, buffer_u16);
    if(!_name == global.username)  {
    for(var i=0; i < instance_number(obj_player_other); i++) {
        
        var ins = instance_find(obj_player_other, i);
        if(ins.name == _name) {
        
            ins.x = xx;
            
        }
        }
        show_debug_message("Moving player "+string(_name)+"; x: "+string(xx));
        
    }
    

break;

case 3: //update position

    var _name = buffer_read(rec_buffer, buffer_string);
    var yy = buffer_read(rec_buffer, buffer_u16);
    if(!_name == global.username)  {
    for(var i=0; i < instance_number(obj_player_other); i++) {
        
        var ins = instance_find(obj_player_other, i);
        if(ins.name == _name) {
        
            ins.y = yy;
            
        }
        }
        show_debug_message("Moving player "+string(_name)+"; y: "+string(yy));
    }

break;
}

break;



}

Obj_server async event:


Code:
/// @description Insert description here
// You can write your code in this editor
//Checks for the type of the event
var type_event = ds_map_find_value(async_load, "type");

switch(type_event) { //checks for incoming data


case network_type_data:

var buffer = ds_map_find_value(async_load, "buffer");
var socket = ds_map_find_value(async_load, "id");
var ip = ds_map_find_value(async_load, "ip");
remote_port = async_load[? "port"];
buffer_seek(buffer, buffer_seek_start, 0);
var mid = buffer_read(buffer, buffer_u8);
switch(mid) {
case 0:
    //Let's add player to our list and send user existing list of players
    
    for(var i = 0; i < ds_list_size(playerList); i++) {
        
        var m = ds_list_find_value(playerList, i);
        
        var pname = ds_map_find_value(m, "name");
        
    buffer_seek(m_buffer, buffer_seek_start, 0);
    buffer_write(m_buffer, buffer_u8, 1);
    buffer_write(m_buffer, buffer_string, pname);
    network_send_udp_raw(socket, ip, remote_port, m_buffer, buffer_tell(m_buffer));
        
    }
    var ip = ds_map_find_value(async_load, "ip");
    var name = buffer_read(buffer, buffer_string);
    add_player(socket, name, -1, -1, -1, -1, -1, ip, remote_port);
    buffer_seek(m_buffer, buffer_seek_start, 0);
    buffer_write(m_buffer, buffer_u8, 0);
    buffer_write(m_buffer, buffer_string, name);
    buffer_write(m_buffer, buffer_u16, 55);
    buffer_write(m_buffer, buffer_u16, 55);
    message_broadcast(socket,remote_port);
    

break;

case 1: //Update x and y
var ip = ds_map_find_value(async_load, "ip");
    var name = buffer_read(buffer, buffer_string);
    var xx = buffer_read(buffer, buffer_u16);
    show_debug_message("name: "+string(name) + " . "+string(xx));
    buffer_seek(m_buffer, buffer_seek_start, 0);
    buffer_write(m_buffer, buffer_u8, 2);
    buffer_write(m_buffer, buffer_string, name);
    buffer_write(m_buffer, buffer_u16, xx);

    message_broadcast(socket,remote_port);

break;

case 3: //Update x and y
    var ip = ds_map_find_value(async_load, "ip");
    var name = buffer_read(buffer, buffer_string);
    
    var yy = buffer_read(buffer, buffer_u16);
    buffer_seek(m_buffer, buffer_seek_start, 0);
    buffer_write(m_buffer, buffer_u8, 3);
    buffer_write(m_buffer, buffer_string, name);

    buffer_write(m_buffer, buffer_u16, yy);
    message_broadcast(socket,remote_port);

break;
}


break;


}

Thank you for reading this post. Any kind of help is really appreciated!

Thank you very much in advance!
 
A

Arnet

Guest
First of all why are you using network_send_udp_raw function its only useful when your receiving end is not Gamemaker application. There might be issue with "remote_port", In server async
"remote_port = async_load[? "port"];"
The value of remote port is the client port server has received data from but you forward it to the message_broadcast script
"message_broadcast(socket,remote_port);"
As written in script
"var p = argument1;" p (port) is the remote_port value and you send all the packets to this port
" network_send_udp(soc, _ip, p, m_buffer, buffer_tell(m_buffer)); " Not all clients have same ports, try changing port and use value from the player list just like ip.
P.S If your whole network structure is based on UDP Connected socket thing is useless because UDP is connection less
here "if(s != soc) {" try removing this line
 

BMatjasic

Member
Client actually recieves data, but somehow not all of them do. I'm using:
network_send_broadcast(m_server, p, m_buffer, buffer_tell(m_buffer));

This seems really strange to me. I've tried to do it the way you've suggested but it doesn't work...
 

The-any-Key

Member
Do you test run in LAN or online?

If you run on the same computer the broadcast command can only send to one client on the same machine. The message gets eaten and can't be received by other instances of the game. But this only apply if you test run and have multiple instances of a the game on the same machine.

Do you have any antivirus/internet security running?
 
Top