Reworked object sending/receiving to work without unnecessary type casting and a bit less error prone; Also increased UDP max packet size to 2048 so we can send 7 objects per frame

This commit is contained in:
zicodxx 2010-12-23 22:42:06 +01:00
parent da06d9889e
commit 9f138fbf2a
3 changed files with 184 additions and 227 deletions

View file

@ -1,5 +1,9 @@
D1X-Rebirth Changelog
20101223
--------
main/net_udp.c, main/net_udp.h: Reworked object sending/receiving to work without unnecessary type casting and a bit less error prone; Also increased UDP max packet size to 2048 so we can send 7 objects per frame
20101222
--------
arch/sdl/window.c: In window_close() prev window did not get EVENT_WINDOW_ACTIVATED but the recent closed window got it causing previous window not being activated anymore and a bunch of memory errors

View file

@ -1323,15 +1323,9 @@ ubyte object_buffer[UPKT_MAX_SIZE];
void net_udp_send_objects(void)
{
short remote_objnum;
sbyte owner;
int loc, i, h;
sbyte owner, player_num = UDP_sync_player.player.connected;
static int obj_count = 0;
static int frame_num = 0;
int obj_count_frame = 0;
int player_num = UDP_sync_player.player.connected;
int loc = 0, i = 0, remote_objnum = 0, obj_count_frame = 0;
// Send clear objects array trigger and send player num
@ -1343,107 +1337,204 @@ void net_udp_send_objects(void)
{
// Endlevel started before we finished sending the goods, we'll
// have to stop and try again after the level.
net_udp_dump_player(UDP_sync_player.player.protocol.udp.addr, DUMP_ENDLEVEL);
Network_send_objects = 0;
return;
}
for (h = 0; h < UDP_OBJ_PACKETS_PER_FRAME; h++) // Do more than 1 per frame, try to speed it up without
// over-stressing the receiver.
memset(object_buffer, 0, UPKT_MAX_SIZE);
object_buffer[0] = UPID_OBJECT_DATA;
loc = 5;
if (Network_send_objnum == -1)
{
obj_count_frame = 0;
memset(object_buffer, 0, UPKT_MAX_SIZE);
object_buffer[0] = UPID_OBJECT_DATA;
loc = 3;
obj_count = 0;
Network_send_object_mode = 0;
PUT_INTEL_INT(object_buffer+loc, -1); loc += 4;
object_buffer[loc] = player_num; loc += 1;
/* Placeholder for remote_objnum, not used here */ loc += 4;
Network_send_objnum = 0;
obj_count_frame = 1;
}
if (Network_send_objnum == -1)
{
obj_count = 0;
Network_send_object_mode = 0;
*(short *)(object_buffer+loc) = INTEL_SHORT(-1); loc += 2;
object_buffer[loc] = player_num; loc += 1;
loc += 2; // Placeholder for remote_objnum, not used here
Network_send_objnum = 0;
obj_count_frame = 1;
frame_num = 0;
}
for (i = Network_send_objnum; i <= Highest_object_index; i++)
{
if ((Objects[i].type != OBJ_POWERUP) && (Objects[i].type != OBJ_PLAYER) &&
(Objects[i].type != OBJ_CNTRLCEN) && (Objects[i].type != OBJ_GHOST) &&
(Objects[i].type != OBJ_ROBOT) && (Objects[i].type != OBJ_HOSTAGE))
continue;
if ((Network_send_object_mode == 0) && ((object_owner[i] != -1) && (object_owner[i] != player_num)))
continue;
if ((Network_send_object_mode == 1) && ((object_owner[i] == -1) || (object_owner[i] == player_num)))
continue;
if ( loc + sizeof(object_rw) + 5 > UPKT_MAX_SIZE-1 )
break; // Not enough room for another object
for (i = Network_send_objnum; i <= Highest_object_index; i++)
{
if ((Objects[i].type != OBJ_POWERUP) && (Objects[i].type != OBJ_PLAYER) &&
(Objects[i].type != OBJ_CNTRLCEN) && (Objects[i].type != OBJ_GHOST) &&
(Objects[i].type != OBJ_ROBOT) && (Objects[i].type != OBJ_HOSTAGE))
continue;
if ((Network_send_object_mode == 0) && ((object_owner[i] != -1) && (object_owner[i] != player_num)))
continue;
if ((Network_send_object_mode == 1) && ((object_owner[i] == -1) || (object_owner[i] == player_num)))
continue;
obj_count_frame++;
obj_count++;
remote_objnum = objnum_local_to_remote((short)i, &owner);
Assert(owner == object_owner[i]);
if ( loc + sizeof(object_rw) + 9 > UPKT_MAX_SIZE-1 )
break; // Not enough room for another object
*(short *)(object_buffer+loc) = INTEL_SHORT(i); loc += 2;
object_buffer[loc] = owner; loc += 1;
*(short *)(object_buffer+loc) = INTEL_SHORT(remote_objnum); loc += 2;
// use object_rw to send objects for now. if object sometime contains some day contains something useful the client should know about, we should use it. but by now it's also easier to use object_rw because then we also do not need fix64 timer values.
multi_object_to_object_rw(&Objects[i], (object_rw *)&object_buffer[loc]);
obj_count_frame++;
obj_count++;
remote_objnum = objnum_local_to_remote(i, &owner);
Assert(owner == object_owner[i]);
PUT_INTEL_INT(object_buffer+loc, i); loc += 4;
object_buffer[loc] = owner; loc += 1;
PUT_INTEL_INT(object_buffer+loc, remote_objnum); loc += 4;
// use object_rw to send objects for now. if object sometime contains some day contains something useful the client should know about, we should use it. but by now it's also easier to use object_rw because then we also do not need fix64 timer values.
multi_object_to_object_rw(&Objects[i], (object_rw *)&object_buffer[loc]);
#ifdef WORDS_BIGENDIAN
object_rw_swap((object_rw *)&object_buffer[loc], 1);
object_rw_swap((object_rw *)&object_buffer[loc], 1);
#endif
loc += sizeof(object_rw);
}
loc += sizeof(object_rw);
}
if (obj_count_frame) // Send any objects we've buffered
if (obj_count_frame) // Send any objects we've buffered
{
Network_send_objnum = i;
PUT_INTEL_INT(object_buffer+1, obj_count_frame);
Assert(loc <= UPKT_MAX_SIZE);
sendto (UDP_Socket[0], object_buffer, loc, 0, (struct sockaddr *)&UDP_sync_player.player.protocol.udp.addr, sizeof(struct _sockaddr));
}
if (i > Highest_object_index)
{
if (Network_send_object_mode == 0)
{
frame_num++;
Network_send_objnum = 0;
Network_send_object_mode = 1; // go to next mode
}
else
{
Assert(Network_send_object_mode == 1);
// Send count so other side can make sure he got them all
object_buffer[0] = UPID_OBJECT_DATA;
PUT_INTEL_INT(object_buffer+1, 1);
PUT_INTEL_INT(object_buffer+5, -2);
PUT_INTEL_INT(object_buffer+9, obj_count);
sendto (UDP_Socket[0], object_buffer, 13, 0, (struct sockaddr *)&UDP_sync_player.player.protocol.udp.addr, sizeof(struct _sockaddr));
// Send sync packet which tells the player who he is and to start!
net_udp_send_rejoin_sync(player_num);
// Turn off send object mode
Network_send_objnum = -1;
Network_send_objects = 0;
obj_count = 0;
return;
} // mode == 1;
} // i > Highest_object_index
}
int net_udp_verify_objects(int remote, int local)
{
int i, nplayers = 0;
if ((remote-local) > 10)
return(2);
for (i = 0; i <= Highest_object_index; i++)
{
if ((Objects[i].type == OBJ_PLAYER) || (Objects[i].type == OBJ_GHOST))
nplayers++;
}
if (MaxNumNetPlayers<=nplayers)
return(0);
return(1);
}
void net_udp_read_object_packet( ubyte *data )
{
// Object from another net player we need to sync with
object *obj;
sbyte obj_owner, my_pnum = 0;
static int mode = 0, object_count = 0;
int i = 0, segnum = 0, objnum = 0, remote_objnum = 0, nobj = 0, loc = 5;
Network_send_objnum = i;
object_buffer[1] = obj_count_frame;
object_buffer[2] = frame_num;
nobj = GET_INTEL_INT(data + 1);
Assert(loc <= UPKT_MAX_SIZE);
for (i = 0; i < nobj; i++)
{
objnum = GET_INTEL_INT(data + loc); loc += 4;
obj_owner = data[loc]; loc += 1;
remote_objnum = GET_INTEL_INT(data + loc); loc += 4;
sendto (UDP_Socket[0], object_buffer, loc, 0, (struct sockaddr *)&UDP_sync_player.player.protocol.udp.addr, sizeof(struct _sockaddr));
}
if (i > Highest_object_index)
if (objnum == -1)
{
if (Network_send_object_mode == 0)
// Clear object array
init_objects();
Network_rejoined = 1;
my_pnum = obj_owner;
change_playernum_to(my_pnum);
mode = 1;
object_count = 0;
}
else if (objnum == -2)
{
// Special debug checksum marker for entire send
if (mode == 1)
{
Network_send_objnum = 0;
Network_send_object_mode = 1; // go to next mode
special_reset_objects();
mode = 0;
}
else
if (remote_objnum != object_count) {
Int3();
}
if (net_udp_verify_objects(remote_objnum, object_count))
{
Assert(Network_send_object_mode == 1);
frame_num++;
// Send count so other side can make sure he got them all
object_buffer[0] = UPID_OBJECT_DATA;
object_buffer[1] = 1;
object_buffer[2] = frame_num;
*(short *)(object_buffer+3) = INTEL_SHORT(-2);
*(short *)(object_buffer+6) = INTEL_SHORT(obj_count);
sendto (UDP_Socket[0], object_buffer, 8, 0, (struct sockaddr *)&UDP_sync_player.player.protocol.udp.addr, sizeof(struct _sockaddr));
// Send sync packet which tells the player who he is and to start!
net_udp_send_rejoin_sync(player_num);
// Turn off send object mode
Network_send_objnum = -1;
Network_send_objects = 0;
obj_count = 0;
// Failed to sync up
nm_messagebox(NULL, 1, TXT_OK, TXT_NET_SYNC_FAILED);
Network_status = NETSTAT_MENU;
return;
} // mode == 1;
} // i > Highest_object_index
} // For PACKETS_PER_FRAME
}
}
else
{
object_count++;
if ((obj_owner == my_pnum) || (obj_owner == -1))
{
if (mode != 1)
Int3(); // SEE ROB
objnum = remote_objnum;
}
else {
if (mode == 1)
{
special_reset_objects();
mode = 0;
}
objnum = obj_allocate();
}
if (objnum != -1) {
obj = &Objects[objnum];
if (obj->segnum != -1)
obj_unlink(objnum);
Assert(obj->segnum == -1);
Assert(objnum < MAX_OBJECTS);
#ifdef WORDS_BIGENDIAN
object_rw_swap((object_rw *)&data[loc], 1);
#endif
multi_object_rw_to_object((object_rw *)&data[loc], obj);
loc += sizeof(object_rw);
segnum = obj->segnum;
obj->next = obj->prev = obj->segnum = -1;
obj->attached_obj = -1;
if (segnum > -1)
obj_link(obj-Objects,segnum);
if (obj_owner == my_pnum)
map_objnum_local_to_local(objnum);
else if (obj_owner != -1)
map_objnum_local_to_remote(objnum, remote_objnum, obj_owner);
else
object_owner[objnum] = -1;
}
} // For a standard onbject
} // For each object in packet
}
void net_udp_send_rejoin_sync(int player_num)
@ -2279,143 +2370,6 @@ void net_udp_read_endlevel_packet( ubyte *data, int data_len, struct _sockaddr s
}
}
void
net_udp_pack_objects(void)
{
// Switching modes, pack the object array
special_reset_objects();
}
int
net_udp_verify_objects(int remote, int local)
{
int i, nplayers = 0;
if ((remote-local) > 10)
return(2);
for (i = 0; i <= Highest_object_index; i++)
{
if ((Objects[i].type == OBJ_PLAYER) || (Objects[i].type == OBJ_GHOST))
nplayers++;
}
if (MaxNumNetPlayers<=nplayers)
return(0);
return(1);
}
void
net_udp_read_object_packet( ubyte *data )
{
// Object from another net player we need to sync with
short objnum, remote_objnum;
sbyte obj_owner;
int segnum, i;
object *obj;
static int my_pnum = 0;
static int mode = 0;
static int object_count = 0;
static int frame_num = 0;
int nobj = data[1];
int loc = 3;
int remote_frame_num = data[2];
frame_num++;
for (i = 0; i < nobj; i++)
{
objnum = INTEL_SHORT(*(short *)(data+loc)); loc += 2;
obj_owner = data[loc]; loc += 1;
remote_objnum = INTEL_SHORT(*(short *)(data+loc)); loc += 2;
if (objnum == -1)
{
// Clear object array
init_objects();
Network_rejoined = 1;
my_pnum = obj_owner;
change_playernum_to(my_pnum);
mode = 1;
object_count = 0;
frame_num = 1;
}
else if (objnum == -2)
{
// Special debug checksum marker for entire send
if (mode == 1)
{
net_udp_pack_objects();
mode = 0;
}
if (remote_objnum != object_count) {
Int3();
}
if (net_udp_verify_objects(remote_objnum, object_count))
{
// Failed to sync up
nm_messagebox(NULL, 1, TXT_OK, TXT_NET_SYNC_FAILED);
Network_status = NETSTAT_MENU;
return;
}
frame_num = 0;
}
else
{
if (frame_num != remote_frame_num)
Int3();
object_count++;
if ((obj_owner == my_pnum) || (obj_owner == -1))
{
if (mode != 1)
Int3(); // SEE ROB
objnum = remote_objnum;
//if (objnum > Highest_object_index)
//{
// Highest_object_index = objnum;
// num_objects = Highest_object_index+1;
//}
}
else {
if (mode == 1)
{
net_udp_pack_objects();
mode = 0;
}
objnum = obj_allocate();
}
if (objnum != -1) {
obj = &Objects[objnum];
if (obj->segnum != -1)
obj_unlink(objnum);
Assert(obj->segnum == -1);
Assert(objnum < MAX_OBJECTS);
#ifdef WORDS_BIGENDIAN
object_rw_swap((object_rw *)&data[loc], 1);
#endif
multi_object_rw_to_object((object_rw *)&data[loc], obj);
loc += sizeof(object_rw);
segnum = obj->segnum;
obj->next = obj->prev = obj->segnum = -1;
obj->attached_obj = -1;
if (segnum > -1)
obj_link(obj-Objects,segnum);
if (obj_owner == my_pnum)
map_objnum_local_to_local(objnum);
else if (obj_owner != -1)
map_objnum_local_to_remote(objnum, remote_objnum, obj_owner);
else
object_owner[objnum] = -1;
}
} // For a standard onbject
} // For each object in packet
}
/*
* Polling loop waiting for sync packet to start game after having sent request
*/

View file

@ -34,10 +34,9 @@ int net_udp_level_sync();
#define UDP_NETGAMES_PAGES 50 // Pages available on Netlist (UDP_MAX_NETGAMES/UDP_NETGAMES_PPAGE)
#define UDP_TIMEOUT (10*F1_0) // 10 seconds disconnect timeout
#define UDP_MDATA_STOR_QUEUE_SIZE 500 // Store up to 500 MDATA packets
#define UDP_OBJ_PACKETS_PER_FRAME 1
// Following are static defines for the buffer size of various packets. IF you change the packets, you must change the size, too.
#define UPKT_MAX_SIZE 1024 // Max size for a packet - just for the buffers
#define UPKT_MAX_SIZE 2048 // Max size for a packet
#define UPKT_GAME_INFO_REQ_SIZE 11
#define UPKT_SEQUENCE_SIZE 14
#define UPKT_PING_SIZE 37