From 9990b806a5649a3fe71e0eac6a7d3a3514f4188d Mon Sep 17 00:00:00 2001 From: zicodxx Date: Thu, 12 Apr 2012 02:15:23 +0200 Subject: [PATCH] Fixed some Multiplayer bugs: Reactor invulnerable time did not checked for hours spent in level so reactor would become invulnerable again after 60 minutes; Fixed the fix (heh) for misordered explode/reappear packets; Reset Player_eggs_dropped when initializing new ship so eggs are properly dropped when player disconnects two times without respawning; Cleaned player disconnecting a little bit and made code more straightforward --- CHANGELOG.txt | 4 ++ main/collide.c | 6 +-- main/gameseq.c | 1 + main/multi.c | 102 +++++++++++++++++++++++++++++++------------------ main/multi.h | 2 +- main/net_udp.c | 65 +++---------------------------- 6 files changed, 79 insertions(+), 101 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 3ccb87e9a..74500f7e3 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,5 +1,9 @@ D1X-Rebirth Changelog +20120412 +-------- +main/collide.c, main/gameseq.c, main/multi.c, main/multi.h, main/net_udp.c: Fixed some Multiplayer bugs: Reactor invulnerable time did not checked for hours spent in level so reactor would become invulnerable again after 60 minutes; Fixed the fix (heh) for misordered explode/reappear packets; Reset Player_eggs_dropped when initializing new ship so eggs are properly dropped when player disconnects two times without respawning; Cleaned player disconnecting a little bit and made code more straightforward + 20120411 -------- editor/ehostage.c, editor/medrobot.c, ui/file.c, ui/inputbox.c, ui/keypress.c, ui/listbox.c, ui/message.c, ui/uidraw.c: Draw the object rotation velocity, file browser and MessageBox dialogs properly diff --git a/main/collide.c b/main/collide.c index 5f5f5da93..b2f59fb1e 100644 --- a/main/collide.c +++ b/main/collide.c @@ -691,11 +691,11 @@ void apply_damage_to_controlcen(object *controlcen, fix damage, short who) #ifdef NETWORK #ifndef SHAREWARE - if ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) && (Players[Player_num].time_level < Netgame.control_invul_time)) + if ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) && ((i2f(Players[Player_num].hours_level*3600)+Players[Player_num].time_level) < Netgame.control_invul_time)) { if (Objects[who].id == Player_num) { - int secs = f2i(Netgame.control_invul_time-Players[Player_num].time_level) % 60; - int mins = f2i(Netgame.control_invul_time-Players[Player_num].time_level) / 60; + int secs = f2i(Netgame.control_invul_time-(i2f(Players[Player_num].hours_level*3600)+Players[Player_num].time_level)) % 60; + int mins = f2i(Netgame.control_invul_time-(i2f(Players[Player_num].hours_level*3600)+Players[Player_num].time_level)) / 60; HUD_init_message(HM_DEFAULT, "%s %d:%02d.", TXT_CNTRLCEN_INVUL, mins, secs); } return; diff --git a/main/gameseq.c b/main/gameseq.c index 3063d8c51..3979e2d81 100644 --- a/main/gameseq.c +++ b/main/gameseq.c @@ -390,6 +390,7 @@ void init_player_stats_new_ship() Players[Player_num].invulnerable_time = 0; Player_is_dead = 0; //player no longer dead + Player_eggs_dropped = 0; Players[Player_num].homing_object_dist = -F1_0; // Added by RH } diff --git a/main/multi.c b/main/multi.c index 7528fa537..699c9c19b 100644 --- a/main/multi.c +++ b/main/multi.c @@ -105,7 +105,7 @@ int Show_kill_list = 1; int Show_reticle_name = 1; fix Show_kill_list_timer = 0; -char PKilledFlags[MAX_NUM_NET_PLAYERS]; +sbyte PKilledFlags[MAX_NUM_NET_PLAYERS]; int Bounty_target = 0; int multi_sending_message[MAX_NUM_NET_PLAYERS] = { 0,0,0,0,0,0,0,0 }; @@ -571,8 +571,6 @@ void multi_compute_kill(int killer, int killed) killed_pnum = Objects[killed].id; - PKilledFlags[killed_pnum]=1; - Assert ((killed_pnum >= 0) && (killed_pnum < N_players)); if (Game_mode & GM_TEAM) @@ -1506,18 +1504,18 @@ multi_do_reappear(char *buf) objnum = GET_INTEL_SHORT(buf + 2); Assert(objnum >= 0); + if (pnum != Objects[objnum].id) + return; - if (Objects[Players[pnum].objnum].type != OBJ_GHOST) + if (PKilledFlags[pnum]<=0) // player was not reported dead, so do not accept this packet { - early_resp[pnum] = objnum; + PKilledFlags[pnum]--; return; } multi_make_ghost_player(Objects[objnum].id); - create_player_appearance_effect(&Objects[objnum]); - PKilledFlags[Objects[objnum].id]=0; - early_resp[pnum] = -1; + PKilledFlags[pnum]=0; } void @@ -1612,11 +1610,12 @@ multi_do_player_explode(char *buf) Players[pnum].flags &= ~(PLAYER_FLAGS_CLOAKED | PLAYER_FLAGS_INVULNERABLE); Players[pnum].cloak_time = 0; - if (early_resp[pnum] >= 0) + PKilledFlags[pnum]++; + if (PKilledFlags[pnum] < 1) // seems we got reappear already so make him player again! { - multi_make_ghost_player(Objects[early_resp[pnum]].id); - create_player_appearance_effect(&Objects[early_resp[pnum]]); - early_resp[pnum] = -1; + multi_make_ghost_player(Objects[Players[pnum].objnum].id); + create_player_appearance_effect(&Objects[Players[pnum].objnum]); + PKilledFlags[pnum] = 0; } } @@ -1791,11 +1790,46 @@ void multi_disconnect_player(int pnum) int i, n = 0; if (!(Game_mode & GM_NETWORK)) - return + return; - digi_play_sample( SOUND_HUD_MESSAGE, F1_0 ); + if (Players[pnum].connected == CONNECT_PLAYING) + { + digi_play_sample( SOUND_HUD_MESSAGE, F1_0 ); + HUD_init_message(HM_MULTI, "%s %s", Players[pnum].callsign, TXT_HAS_LEFT_THE_GAME); - HUD_init_message(HM_MULTI, "%s %s", Players[pnum].callsign, TXT_HAS_LEFT_THE_GAME); + multi_sending_message[pnum] = 0; + + if (Network_status == NETSTAT_PLAYING) + { + multi_make_player_ghost(pnum); + multi_strip_robots(pnum); + } + + if (Newdemo_state == ND_STATE_RECORDING) + newdemo_record_multi_disconnect(pnum); + + // Bounty target left - select a new one + if( Game_mode & GM_BOUNTY && pnum == Bounty_target && multi_i_am_master() ) + { + /* Select a random number */ + int new = d_rand() % MAX_NUM_NET_PLAYERS; + + /* Make sure they're valid: Don't check against kill flags, + * just in case everyone's dead! */ + while( !Players[new].connected ) + new = d_rand() % MAX_NUM_NET_PLAYERS; + + /* Select new target */ + multi_new_bounty_target( new ); + + /* Send this new data */ + multi_send_bounty(); + } + } + + Players[pnum].connected = CONNECT_DISCONNECTED; + Netgame.players[pnum].connected = CONNECT_DISCONNECTED; + PKilledFlags[pnum] = 1; switch (multi_protocol) { @@ -1809,32 +1843,27 @@ void multi_disconnect_player(int pnum) break; } + if (pnum == multi_who_is_master()) // Host has left - Quit game! + { + if (Network_status==NETSTAT_PLAYING) + multi_leave_game(); + if (Game_wind) + window_set_visible(Game_wind, 0); + nm_messagebox(NULL, 1, TXT_OK, "Host left the game!"); + if (Game_wind) + window_set_visible(Game_wind, 1); + multi_quit_game = 1; + game_leave_menus(); + multi_reset_stuff(); + return; + } + for (i = 0; i < N_players; i++) if (Players[i].connected) n++; if (n == 1) { HUD_init_message(HM_MULTI, "You are the only person remaining in this netgame"); } - - // Bounty target left - select a new one - if( Game_mode & GM_BOUNTY && pnum == Bounty_target && multi_i_am_master() ) - { - /* Select a random number */ - int new = d_rand() % MAX_NUM_NET_PLAYERS; - - /* Make sure they're valid: Don't check against kill flags, - * just in case everyone's dead! */ - while( !Players[new].connected ) - new = d_rand() % MAX_NUM_NET_PLAYERS; - - /* Select new target */ - multi_new_bounty_target( new ); - - /* Send this new data */ - multi_send_bounty(); - } - - multi_sending_message[pnum] = 0; } void @@ -2999,8 +3028,7 @@ multi_prep_level(void) for (i=0;i 4 DXX-Rebirth -#define MULTI_PROTO_VERSION 7 +#define MULTI_PROTO_VERSION 8 // PROTOCOL VARIABLES AND DEFINES - END diff --git a/main/net_udp.c b/main/net_udp.c index 60865ee25..7a11f9add 100644 --- a/main/net_udp.c +++ b/main/net_udp.c @@ -77,7 +77,6 @@ void net_udp_send_pdata(); void net_udp_process_pdata ( ubyte *data, int data_len, struct _sockaddr sender_addr ); void net_udp_read_pdata_short_packet(UDP_frame_info *pd); void net_udp_timeout_check(fix64 time); -void net_udp_timeout_player(int playernum); int net_udp_get_new_player_num (UDP_sequence_packet *their); void net_udp_noloss_add_queue_pkt(uint32_t pkt_num, fix64 time, ubyte *data, ushort data_size, ubyte pnum, ubyte player_ack[MAX_PLAYERS]); int net_udp_noloss_validate_mdata(uint32_t pkt_num, ubyte sender_pnum, struct _sockaddr sender_addr); @@ -1203,8 +1202,8 @@ net_udp_can_join_netgame(netgame_info *game) return 0; } -void -net_udp_disconnect_player(int playernum) +// do UDP stuff to disconnect a player. Should ONLY be called from multi_disconnect_player() +void net_udp_disconnect_player(int playernum) { // A player has disconnected from the net game, take whatever steps are // necessary @@ -1215,36 +1214,10 @@ net_udp_disconnect_player(int playernum) return; } - Players[playernum].connected = CONNECT_DISCONNECTED; - Netgame.players[playernum].connected = CONNECT_DISCONNECTED; - if (VerifyPlayerJoined==playernum) VerifyPlayerJoined=-1; - if (Network_status == NETSTAT_PLAYING) - { - multi_make_player_ghost(playernum); - multi_strip_robots(playernum); - } - - if (Newdemo_state == ND_STATE_RECORDING) - newdemo_record_multi_disconnect(playernum); - net_udp_noloss_clear_mdata_got(playernum); - - if (playernum == 0) // Host has left - Quit game! - { - if (Network_status==NETSTAT_PLAYING) - multi_leave_game(); - if (Game_wind) - window_set_visible(Game_wind, 0); - nm_messagebox(NULL, 1, TXT_OK, "Host left the game!"); - if (Game_wind) - window_set_visible(Game_wind, 1); - multi_quit_game = 1; - game_leave_menus(); - multi_reset_stuff(); - } } void @@ -1970,7 +1943,7 @@ void net_udp_dump_player(struct _sockaddr dump_addr, int why) if (multi_i_am_master()) for (i = 1; i < N_players; i++) if (!memcmp((struct _sockaddr *)&dump_addr, (struct _sockaddr *)&Netgame.players[i].protocol.udp.addr, sizeof(struct _sockaddr))) - net_udp_disconnect_player(i); + multi_disconnect_player(i); } void net_udp_update_netgame(void) @@ -4019,7 +3992,7 @@ void net_udp_timeout_check(fix64 time) } else if ((time - Netgame.players[i].LastPacketTime) > UDP_TIMEOUT) { - net_udp_timeout_player(i); + multi_disconnect_player(i); } } } @@ -4027,34 +4000,6 @@ void net_udp_timeout_check(fix64 time) } } -void net_udp_timeout_player(int playernum) -{ - // Remove a player from the game if we haven't heard from them in - // a long time. - int i, n = 0; - - Assert(playernum < N_players); - Assert(playernum > -1); - - net_udp_disconnect_player(playernum); - - if (Network_status == NETSTAT_PLAYING) - { - create_player_appearance_effect(&Objects[Players[playernum].objnum]); - digi_play_sample(SOUND_HUD_MESSAGE, F1_0); - HUD_init_message(HM_MULTI, "%s %s", Players[playernum].callsign, TXT_DISCONNECTING); - } - - for (i = 0; i < N_players; i++) - if (Players[i].connected) - n++; - - if (n == 1 && Network_status == NETSTAT_PLAYING) - { - HUD_init_message(HM_MULTI, "You are the only person remaining in this netgame"); - } -} - void net_udp_do_frame(int force, int listen) { fix64 time = 0; @@ -4682,7 +4627,7 @@ void net_udp_read_pdata_short_packet(UDP_frame_info *pd) if ( Players[TheirPlayernum].connected != CONNECT_DISCONNECTED && pd->connected == CONNECT_DISCONNECTED ) { Netgame.players[TheirPlayernum].LastPacketTime = timer_query() - UDP_TIMEOUT; - net_udp_timeout_player(TheirPlayernum); + multi_disconnect_player(TheirPlayernum); return; } if ( Players[TheirPlayernum].connected == CONNECT_DISCONNECTED && pd->connected == CONNECT_PLAYING )