SOLVED Multiplayer Bot Syncronizing

Gamerev147

Member
Background
I have a fairly basic server system setup, and it is as follows:

My server and client are two separate projects. My server simply receives data from each client and sends that data back out to every client that is connected. This way, on the client end I can say something like “if my id isn’t the same as the one being sent to me, update the instance of that id”. My client retrieves the data sent from the server and decides what to do with it and who to assign it to in the Async Networking event.

Issue Description
I’m attempting to create bots (I.e Police or Swat team) that players connected to the server will have to work together to defeat. Within attempting this, I realized I have no idea how to do this, as I’m pretty familiar with player PvP and such in GM's networking (not bots). So I used GravityShift Game’s tutorial on Native Networking NPC’s for reference. I created an object to spawn and also send the data of these enemies on the client-side.

The code I’m using to try and create these bots is listed below. I organized it in the best way that I could.

obj_net_SpawnEnemy - Create Event
GML:
instance_create_layer(x, y, layer, net_SwatEnemy);
obj_net_SpawnEnemy - Step Event
Code:
//Send the data of each enemy to the server
for (var i = 0; i < instance_number(net_SwatEnemy); i++) {
    var enemy = instance_find(net_SwatEnemy, i);
    
    //Send our data
    var ebuff = buffer_create(64, buffer_grow, 1);
    buffer_seek(ebuff, buffer_seek_start, 0);
    buffer_write(ebuff, buffer_u8, network.swat);
    buffer_write(ebuff, buffer_u16, enemy.enemy_id);
    buffer_write(ebuff, buffer_s16, enemy.x);
    buffer_write(ebuff, buffer_s16, enemy.y);
    buffer_write(ebuff, buffer_s16, enemy.image_angle);
    network_send_packet(obj_Client.client, ebuff, buffer_tell(ebuff));
    buffer_delete(ebuff);
}
The server then receives this data and sends it back to all of the clients.

Obj_Client - Async Networking

Code:
//Snippet from full code:
case network.swat:
    var _enemy_id = buffer_read(packet, buffer_u16);
    var _enemy_x = buffer_read(packet, buffer_s16);
    var _enemy_y = buffer_read(packet, buffer_s16);
    var _enemy_angle = buffer_read(packet, buffer_s16);
        
    var e = instance_create_layer(_enemy_x, _enemy_y, layer, net_SwatEnemy);
    e.enemy_id = _enemy_id;
    e.image_angle = _enemy_angle;
break;
Obviously, the issue is that about a million instances of the enemy spawns because there’s nothing really keeping track of them. How could I implement a way to track each instance of the enemy, and sync that with all of the other clients? Any help would be appreciated.

Thanks!
 

woods

Member
first thing that comes to mind..
store a global variable for total_SwatEnemy on the server

Enemy Create Event
Code:
instance_create_layer(x, y, layer, net_SwatEnemy);
total_SwatEnemy ++;

and on enemy death or destruction event
Code:
total_SwatEnemy --;

sidenote:
shouldnt all this be handled on the server-side?
couple reasons come to mind..
prevent clients from hacking and cheating
maybe preventing lag issues with the instance count..// updating the server before updating the clients
 

Gamerev147

Member
first thing that comes to mind..
store a global variable for total_SwatEnemy on the server

Enemy Create Event
Code:
instance_create_layer(x, y, layer, net_SwatEnemy);
total_SwatEnemy ++;

and on enemy death or destruction event
Code:
total_SwatEnemy --;

sidenote:
shouldnt all this be handled on the server-side?
couple reasons come to mind..
prevent clients from hacking and cheating
maybe preventing lag issues with the instance count..// updating the server before updating the clients
How can I sync the bot positions to each client though? As of now, when a bot is spawned, it sends its data to the server with a random ID. Then every other client checks a list to see if that enemy is created or not. If it doesn't exist, create it and add it to the list. If it does exist, then get the instance ID of that enemy, and update it accordingly.

However, as you can imagine this creates duplicates because the list on every other client is empty before the first one.
 

woods

Member
How can I sync the bot positions to each client though?
only the server creates and sends data to the clients


in general wouldnt we have everything handled serverside?
the client shouldnt be creating/changing anything .. only making requests of the server.
this way, there is only one entity changing things around, thus avoiding duplicate entries.

with the server always right approach, you have one list that needs to be sent. simply overwrite the old info on all the clients. no need for the client to check anything.
everything happening in one spot with one controller(the server)


it may require a bit of reworking, but you will deff be better off.
 

Gamerev147

Member
only the server creates and sends data to the clients


in general wouldnt we have everything handled serverside?
the client shouldnt be creating/changing anything .. only making requests of the server.
this way, there is only one entity changing things around, thus avoiding duplicate entries.

with the server always right approach, you have one list that needs to be sent. simply overwrite the old info on all the clients. no need for the client to check anything.
everything happening in one spot with one controller(the server)


it may require a bit of reworking, but you will deff be better off.
So I've created somewhat of a fix. The enemy now is created on the server-side. Upon its creation, it sends a packet with its ID to all of the clients.
The clients then get this packet and check a map to see if that enemy already exists or not.

Still having some issues with it throwing errors about an unknown object ID, but I'm sure I can manage.
Thanks for your help!
 
Top