Hola a todos. Esoty intentando hacer un juego online y es mi primer proyecto donde lo aplico, por lo que estoy bastante verde en el tema.
Mi duda es la siguiente: Quiero hacer un servidor y un cliente por aplicaciones separadas, y de momento los clientes se conectan y se desconectan de forma correcta. Pero al intercambiar datos sobre los estados de los clientes (posiciones "x" e "y", u otras variables) el servidor no recibe los datos, y por consecuencia, tampoco los demás usuarios conectados. Para ser más específico, los clientes se mueven en la room y todo, pero en el servidor no pasa nada; y si ahí no sucede nada, los clientes no reciben información sobre el estado de los otros usuarios. Creo que mi error puede estar en que los paquetes los envío desde el evento STEP y no desde el asincróncio NETWORKING, pero no sé mucho sobre el tema. En mi caso, tanto el cliente como el servidor envían los datos desde el evento STEP. Gracias de antemano.

Hola Hezz
Asegúrate que la aplicación que ejecuta el código del servidor esté leyendo los packetes enviados por los clientes en el evento NETWORKING.
Si el cliente le manda un packete de datos al server, hace que el tipo de evento que genera la DS MAP del server sea la constante "network_type_data".

Saludos

Si, eso lo tengo.

Este es el código en el evento create del servidor:
//Características del servidor
port = 1024;
max_user = 8;
type = network_create_socket(network_socket_tcp);

//Crear el servidor
server = network_create_server(type, port, max_user);

//Si no se pudo crear el servidor
while (server < 0){ //Mientras no sea creado
    server = network_create_server(type, port, max_user);
    port++; //Cambiar el port aumentándolo en 1
}



//Características del servidor ya creado
player_list = ds_list_create();
instance_list = ds_list_create();


Esto es el evento NETWORKING:
//Tipo de evento a ejecutar
var type_event = ds_map_find_value(async_load, "type");

//Operaciones según el evento
switch (type_event){
    case network_type_connect:
        //Tomar el socket del jugador que se conecta
        var client = ds_map_find_value(async_load, "socket");

        //Añadir el socket del jugador a la lista de jugadores
        ds_list_add(player_list, client);

        //Enviar el identificador de cliente al cliente conectado (Client ID)
        var package = buffer_create(64, buffer_grow, 1);
        var players = ds_list_size(player_list)-1;

        buffer_write(package, buffer_u8, client);
        buffer_write(package, buffer_u8, players);
        for(i=0;i<players;i++){
            var player_id = ds_list_find_value(instance_list, i);
            buffer_write(package, buffer_u8, player_id);
        }
        network_send_packet(client, package, buffer_tell(package));

        //Enviar la información a los otros clientes sobre el nuevo usuario
        var package2 = buffer_create(64, buffer_grow, 1);
        buffer_write(package2, buffer_u8, 1);      //El valor es 1 porque significa un nuevo usuario conectado
        buffer_write(package2, buffer_u8, client); //Enviar la ID del cliente conectado
        network_send_packet(client, package, buffer_tell(package));

        //Crear un jugador en la sala
        var inst;
        inst = instance_create(obj_spawn_player.x, obj_spawn_player.y, obj_player);
        //Añadir la instancia a la lista de instancias
        ds_list_add(instance_list, inst);
        break;

    case network_type_disconnect:
        //Remover al jugador de la lista de jugadores
        var socket = ds_map_find_value(async_load, "socket");
        var position = ds_list_find_index(player_list, socket);

        //Remover la id de la lista
        ds_list_delete(player_list, position);
        //Remover la instancia y la id de la instancia de la lista
        with (ds_list_find_value(instance_list, position)) {instance_destroy();}
        ds_list_delete(instance_list, position);

        //Enviar la información a los demás clientes sobre el usuario desconectado
        //for(i=0;i<ds_list_size(player_list);i++){
            var package = buffer_create(64, buffer_grow, 1);
            buffer_write(package, buffer_u8, 2); //Es 2 porque significa que un usuario se desconectó
            buffer_write(package, buffer_u8, position);
            network_send_packet(type, package, buffer_tell(package));
        //}
        break;

    case network_type_data:
        //Leer los datos recibidos
        var data = ds_map_find_value(async_load, "buffer");
        buffer_seek(data, buffer_seek_start, 0);
        scr_received_packet(buffer);
        break;
}


Y este es del evento STEP:
var players = instance_number(obj_player);
if (players > 0) {
    var package = buffer_create(64, buffer_grow, 1);
    //Enviar el tipo de dato que se va a enviar. En este caso, informacion de la partida (0)
    buffer_write(package, buffer_u8, 0);
   
    //Enviar la cantidad de jugadores que hay en partida
    buffer_write(package, buffer_u8, players);

    for(i=0;i<players;i++){
        //Enviar todos los datos en orden de la lista de jugadores
        var socket = ds_list_find_value(player_list, i);
        var inst = ds_list_find_value(instance_list, i);
        buffer_write(package, buffer_u8, socket);  //Identificador de cliente
        buffer_write(package, buffer_u16, inst.x); //Posición x
        buffer_write(package, buffer_u16, inst.y); //Posición y
    }
    network_send_packet(type, package, buffer_tell(package));
}


Este es el script que recibe los datos:
///scr_received_packet(buffer);
var buffer = argument0;

//Comprobar el ID del cliente
var pack = buffer_read(buffer, buffer_u8);

//Analizar a qué instancia corresponde esa ID
var position = ds_list_find_index(instance_list, pack);

//Aplicar los datos recibidos a la instancia
with (ds_list_find_value(instance_list, position)){
    //Leer las teclas que presiona el cliente
    var key_left = buffer_read(buffer, buffer_bool);
    var key_right = buffer_read(buffer, buffer_bool);
    var key_jump = buffer_read(buffer, buffer_bool);
}

Hola Hezz

A simple vista tu código se ve bien, qué información está enviando el cliente?
Puedes pegar la parte del código donde el cliente llena el buffer que le envía al server? Quizás estás pasando mal un dato o una variable.

Saludos

Dale, gracias por la ayuda :D.

Este es el evento create del cliente:
//Variables de conexion multiplayer
socket = 0;
ip = 0; //La IP se elige con una función en el evento step, al igual que el port
port = 0;
socket_type = network_create_socket(network_socket_tcp);
global.client_id = -1;

//Lista de instancias y jugadores
player_list = ds_list_create();
instance_list = ds_list_create();


Este es el evento STEP:
if (keyboard_check_pressed(vk_enter)){
//Conectarse al servidor
network_connect(socket_type,ip,real(port));
room_goto(rm_play_mp)
}

//////////////
//NETWORKING//
//////////////
//Enviar los datos al servidor
if (room == rm_play_mp){
    var package = buffer_create(64, buffer_grow, 1);
    key_left = keyboard_check_pressed(ord("A"));
    key_right = keyboard_check_pressed(ord("D"));
    key_jump = keyboard_check_pressed(vk_space);
   
    buffer_write(package, buffer_bool, key_left);
    buffer_write(package, buffer_bool, key_right);
    buffer_write(package, buffer_bool, key_jump);
    network_send_packet(socket_type, package, buffer_tell(package));
}


Este en el evento NETWORKING:
var type_data = async_load[? "type"]
if (type_data = network_type_data){
    //Leer los datos recibidos
    var buffer = async_load[? "buffer"];
    buffer_seek(buffer, buffer_seek_start, 0);
    scr_received_packet(buffer);
}


Y este el script. Está separado por partes según la variable "pack_id":
///scr_received_packet(buffer);
var buffer = argument0;

//Si el jugador reciés se conecta, debe recibir un paquete de información especial
if (global.client_id < 0){
    global.client_id = buffer_read(buffer, buffer_u8);
    var players = buffer_read(buffer, buffer_u8);
   
    for(i=0;i<players;i++){
        var inst = instance_create(0,0,obj_other_player);
        var socket = buffer_read(buffer, buffer_u8);
        ds_list_add(player_list, socket);
        ds_list_add(instance_list, inst);
    }
}

//Si el jugador ya está conectado, recibir información de la partida
else {
    //Identificar el tipo de dato recibido. 0 es de la partida, 1 es la conexión de un nuevo usuario, 2 es la desconexión de un usuario
    var pack_id = buffer_read(buffer, buffer_u8);
   
    //Si es información de la partida
    if (pack_id == 0){
        var players = buffer_read(buffer, buffer_u8);
        //Repetir esta acción según la cantidad de usuarios conectados
        for(i=0;i<players;i++){
            //Obtener el identificador de cliente
            var player_id = buffer_read(buffer, buffer_u8);

            //Si el identificador de cliente es el mismo que el cliente, entonces aplicarlo a la instancia jugador
            if (player_id == global.client_id){
                obj_player.x = buffer_read(buffer, buffer_u16);
                obj_player.y = buffer_read(buffer, buffer_u16);
            }
            //Si no es el mismo, entonces aplicarlo a las instancias "otros jugadores"
            else {
                var pos = ds_list_find_index(player_list, player_id);
                var inst = ds_list_find_value(instance_list, pos);
       
                inst.x = buffer_read(buffer, buffer_u16);
                inst.y = buffer_read(buffer, buffer_u16);
            }
        }
    }
    //Si es la conexión de un nuevo usuario
    else if (pack_id == 1){
        var inst = instance_create(0,0,obj_other_player);
        var player_id = buffer_read(buffer, buffer_u8);

        //Añadir en la lista de jugadores la nueva id del nuevo cliente
        ds_list_add(player_list, player_id);
        //Añadir en la lista de instancias la ID de la nueva instancia
        ds_list_add(instance_list, inst);
    }
    //Si se desconecta un jugador
    else if (pack_id == 2){
        var pos = buffer_read(buffer, buffer_u8);

        //Eliminar de las listas en la posicion recibida
        ds_list_delete(player_list, pos);
        ds_list_delete(instance_list, pos);
    }
}


Acabé de darme cuenta que en el evento networking del servidor estaba leyendo un buffer llamado buffer, pero busca uno llamado data. Arreglé eso, pero no me solucionó el problema  :-[.

Hola Hezz
Es bastante enrredado tu código, pero leyendo e interpretando lo que has escrito, me doy cuenta que el error es que estás enviando una información, pero estás leyendo otra diferente.

Antes de intentar dar con una solución, quiero comentarte que no es necesario crear un nuevo buffer cada vez que necesites uno, basta con crear uno y reutilizarlo, o si no quieres reutilizar, lo eliminas cuando ya no es útil. Los buffers son recursos dinámicos tal como los DS LIST, por lo que reservarán una parte de la memoria que tu computador le asigna a Game Maker, si creas muchos corres el riesgo de quedarte sin memoria mientras el juego está funcionando.

Ahora, detecté dos errores críticos, uno es que tu cliente, le manda al server un buffer con 3 datos de tipo "boolean"
Pero el server, lee 4!. Esto es lo que pusiste en el script "scr_received_packet" del server. Primero lees un u8
var pack = buffer_read(buffer, buffer_u8);
Y luego lees 3 boolean, pero los booleans los lees dentro de un evento "with" y los asignas como variables locales (las que se borran xD)
var key_left = buffer_read(buffer, buffer_bool);
var key_right = buffer_read(buffer, buffer_bool);
var key_jump = buffer_read(buffer, buffer_bool);


Para solucionarlo, antes que el cliente mande los 3 booleans, hace que escriba un u8 con su socket ID.
buffer_write(package, buffer_u8, global.client_id); //Esto añade mi socket ID
    buffer_write(package, buffer_bool, key_left);
    buffer_write(package, buffer_bool, key_right);
    buffer_write(package, buffer_bool, key_jump);
    network_send_packet(socket_type, package, buffer_tell(package));
    buffer_delete(package) //esto eliminará el buffer que ya ha sido utilizado y no es necesario.
}

Y en el código de lectura del cliente, debes crear las variables como "instance variables" (sin la palabra var adelante) para que se asignen al objeto del with.
key_left = buffer_read(buffer, buffer_bool);
key_right = buffer_read(buffer, buffer_bool);
key_jump = buffer_read(buffer, buffer_bool);

Eso hará que en el lado del server se le asigne las tres variables a la instance que encontró en la DS LIST.

Es complicado de explicar, espero que se haya entendido.
Nos comentas si se soluciona o si el problema persiste.

Saludos