From 80084bb032bf3078a6199b7dbc6155494b8bfed0 Mon Sep 17 00:00:00 2001 From: zicodxx <> Date: Sun, 15 Feb 2009 19:03:57 +0000 Subject: [PATCH] Added list to keep trace of received PDATA packets so receiver won't interpret them several times --- CHANGELOG.txt | 4 ++++ main/network.c | 8 ++++++-- main/noloss.c | 54 ++++++++++++++++++++++++++++++++++---------------- main/noloss.h | 10 ++++++++-- 4 files changed, 55 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index d07fc3c6a..705334234 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,5 +1,9 @@ D2X-Rebirth Changelog +20090215 +-------- +main/network.c, main/noloss.c, main/noloss.h: Added list to keep trace of received PDATA packets so receiver won't interpret them several times + 20090209 -------- main/kconfig.c: Removed PH_SCALE on Keyboard readings as caps movement not in sync to FrameTime; Removed scaled Joystick reading as it's not necessary anymore diff --git a/main/network.c b/main/network.c index 3f44cb748..28c1aad83 100644 --- a/main/network.c +++ b/main/network.c @@ -548,6 +548,8 @@ network_disconnect_player(int playernum) if (VerifyPlayerJoined==playernum) VerifyPlayerJoined=-1; + noloss_update_pdata_got(playernum); + // create_player_appearance_effect(&Objects[Players[playernum].objnum]); multi_make_player_ghost(playernum); @@ -4229,7 +4231,8 @@ void network_read_pdata_packet(ubyte *data ) TheirObjnum = Players[pd->playernum].objnum; if (pd->type == PID_PDATA_NOLOSS) - noloss_send_ack(pd->numpackets, pd->playernum); + if (noloss_validate_pdata(pd->numpackets, pd->playernum) == 0) + return; // got that one already! if (TheirPlayernum < 0) { Int3(); // This packet is bogus!! @@ -4388,7 +4391,8 @@ void network_read_pdata_short_packet(short_frame_info *pd ) TheirObjnum = Players[new_pd.playernum].objnum; if (new_pd.type == PID_PDATA_NOLOSS) - noloss_send_ack(new_pd.numpackets, new_pd.playernum); + if (noloss_validate_pdata(new_pd.numpackets, new_pd.playernum) == 0) + return; // got that one already! if (TheirPlayernum < 0) { Int3(); // This packet is bogus!! diff --git a/main/noloss.c b/main/noloss.c index bccb7919a..e51af9536 100644 --- a/main/noloss.c +++ b/main/noloss.c @@ -11,6 +11,7 @@ #include "noloss.h" struct pdata_noloss_store noloss_queue[NOLOSS_QUEUE_SIZE]; +struct pdata_recv noloss_pdata_got[MAX_PLAYERS]; extern frame_info MySyncPack; extern int MaxXDataSize; extern int N_players; @@ -31,6 +32,8 @@ void noloss_add_packet_to_queue(int urgent, int pkt_num, char *data, ushort data for (i = 0; i < NOLOSS_QUEUE_SIZE; i++) { + int j; + if (noloss_queue[i].used) continue; @@ -38,8 +41,13 @@ void noloss_add_packet_to_queue(int urgent, int pkt_num, char *data, ushort data noloss_queue[i].pkt_initial_timestamp = GameTime; noloss_queue[i].pkt_timestamp = GameTime; noloss_queue[i].pkt_num = pkt_num; - memset( &noloss_queue[i].player_ack, 0, sizeof(ubyte)*MAX_PLAYERS ); - noloss_queue[i].N_players = N_players; + for (j = 0; j < MAX_PLAYERS; j++) + { + if (Players[j].connected) + noloss_queue[i].player_ack[j] = 0; + else + noloss_queue[i].player_ack[j] = 1; // Player is not connected so set to positive in case he joins + } memcpy( &noloss_queue[i].data[0], data, data_size ); noloss_queue[i].data_size = data_size; @@ -139,9 +147,12 @@ void noloss_send_queued_packet(int queue_index) // We have received a PDATA packet. Send ACK response to sender! // ACK packet needs to contain: packet num, sender player num, receiver player num // Call in network_process_packet() at case PID_PDATA -void noloss_send_ack(int pkt_num, ubyte receiver_pnum) +// Also check in our noloss_pdata_got list, if we got this packet already. +// If yes, return 0 (not valid)! If not, add this pkt_num to our list and return 1 so the pdata packet will be processed! +int noloss_validate_pdata(int pkt_num, ubyte receiver_pnum) { noloss_ack ack; + int i; memset(&ack,0,sizeof(noloss_ack)); @@ -151,6 +162,17 @@ void noloss_send_ack(int pkt_num, ubyte receiver_pnum) ack.pkt_num = pkt_num; netdrv_send_packet_data( (ubyte *)&ack, sizeof(noloss_ack), NetPlayers.players[receiver_pnum].network.ipx.server, NetPlayers.players[receiver_pnum].network.ipx.node,Players[receiver_pnum].net_address ); + + for (i = 0; i < NOLOSS_QUEUE_SIZE; i++) + { + if (pkt_num == noloss_pdata_got[receiver_pnum].pkt_num[i]) + return 0; + } + noloss_pdata_got[receiver_pnum].cur_slot++; + if (noloss_pdata_got[receiver_pnum].cur_slot >= NOLOSS_QUEUE_SIZE) + noloss_pdata_got[receiver_pnum].cur_slot=0; + noloss_pdata_got[receiver_pnum].pkt_num[noloss_pdata_got[receiver_pnum].cur_slot] = pkt_num; + return 1; } // We got an ACK by a player. Set this player slot to positive! @@ -176,6 +198,14 @@ void noloss_got_ack(ubyte *data) void noloss_init_queue(void) { memset(&noloss_queue,0,sizeof(pdata_noloss_store)*NOLOSS_QUEUE_SIZE); + memset(&noloss_pdata_got,-1,sizeof(pdata_recv)*MAX_PLAYERS); +} + +// Reset the trace list for given player when disconnect happens +void noloss_update_pdata_got(int player_num) +{ + memset(&noloss_pdata_got[player_num].pkt_num,-1,sizeof(int)*NOLOSS_QUEUE_SIZE); + noloss_pdata_got[player_num].cur_slot = -1; } // The main queue-process function. @@ -192,22 +222,12 @@ void noloss_process_queue(void) if (!noloss_queue[i].used) continue; - // If N_players differs (because of disconnet), we resend to all to make sure we we get the right ACK packets for the right players - if (N_players != noloss_queue[i].N_players) + // Check if at least one connected player has not ACK'd the packet + for (j = 0; j < N_players; j++) { - memset( noloss_queue[i].player_ack, 0, sizeof(ubyte)*8 ); - noloss_queue[i].N_players = N_players; - resend = 1; - } - else - { - // Check if at least one connected player has not ACK'd the packet - for (j = 0; j < N_players; j++) + if (!noloss_queue[i].player_ack[j] && Players[j].connected && j != Player_num) { - if (!noloss_queue[i].player_ack[j] && Players[j].connected && j != Player_num) - { - resend = 1; - } + resend = 1; } } diff --git a/main/noloss.h b/main/noloss.h index 2879bb26f..e041828da 100644 --- a/main/noloss.h +++ b/main/noloss.h @@ -22,7 +22,6 @@ typedef struct pdata_noloss_store { fix pkt_timestamp; // Packet timestamp int pkt_num; // Packet number ubyte player_ack[MAX_PLAYERS]; // 0 if player has not ACK'd this packet, 1 if ACK'd or not connected - int N_players; // Save N_players, too - so if a player disconnects we will resend to make sure all acks are related to the right players char data[NET_XDATA_SIZE]; // extra data of a packet - contains all multibuf data we don't want to loose ushort data_size; } __pack__ pdata_noloss_store; @@ -35,8 +34,15 @@ typedef struct noloss_ack { int pkt_num; } __pack__ noloss_ack; +// keeps track of PDATA packets we've already got +typedef struct pdata_recv { + int pkt_num[NOLOSS_QUEUE_SIZE]; + int cur_slot; // index we can use for a new pkt_num +} __pack__ pdata_recv; + void noloss_add_packet_to_queue(int urgent, int pkt_num, char *data, ushort data_size); -void noloss_send_ack(int pkt_num, ubyte receiver_pnum); +int noloss_validate_pdata(int pkt_num, ubyte receiver_pnum); void noloss_got_ack(ubyte *data); void noloss_init_queue(void); +void noloss_update_pdata_got(int player_num); void noloss_process_queue(void);