Remove call to window_close(Game_wind) when multiplayer level syncing fails

Replace call to window_close(Game_wind) with returning window_event_result::close to game_handler. Applies to when there is a failure in net_udp_level_sync(). Closing a window within its handler is problematic - it can result in an unstable state.
This commit is contained in:
Chris Taylor 2017-01-10 13:02:59 +08:00
parent 2ecc4c4a07
commit a418f8caec
7 changed files with 27 additions and 29 deletions

View file

@ -60,7 +60,7 @@ namespace dsx {
void StartNewGame(int start_level);
// starts the next level
void StartNewLevel(int level_num);
window_event_result StartNewLevel(int level_num);
}
#endif

View file

@ -559,7 +559,7 @@ void multi_add_lifetime_kills(int count);
void multi_send_bounty( void );
void multi_consistency_error(int reset);
int multi_level_sync(void);
window_event_result multi_level_sync();
int multi_endlevel(int *secret);
using multi_endlevel_poll = int(newmenu *menu,const d_event &event, const unused_newmenu_userdata_t *);
multi_endlevel_poll *get_multi_endlevel_poll2();

View file

@ -44,7 +44,7 @@ int net_udp_kmatrix_poll2( newmenu *menu,const d_event &event, const unused_newm
void net_udp_send_endlevel_packet();
void net_udp_dump_player(const _sockaddr &dump_addr, int why);
void net_udp_disconnect_player(int playernum);
int net_udp_level_sync();
window_event_result net_udp_level_sync();
void net_udp_send_mdata_direct(const ubyte *data, int data_len, int pnum, int priority);
void net_udp_send_netgame_update();

View file

@ -34,6 +34,7 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
#ifdef __cplusplus
#include <cstddef>
#include "dsx-ns.h"
#include "fwd-window.h"
extern unsigned state_game_id;
extern int state_quick_item;
@ -101,11 +102,11 @@ static inline int state_restore_all(int in_game, secret_restore, std::nullptr_t,
{
return state_restore_all(in_game, nullptr, blind);
}
void StartNewLevelSub(int level_num, int page_in_textures);
window_event_result StartNewLevelSub(int level_num, int page_in_textures);
// Actually does the work to start new level
static inline void StartNewLevelSub(int level_num, int page_in_textures, secret_restore)
static inline window_event_result StartNewLevelSub(int level_num, int page_in_textures, secret_restore)
{
StartNewLevelSub(level_num, page_in_textures);
return StartNewLevelSub(level_num, page_in_textures);
}
void init_player_stats_level();
static inline void init_player_stats_level(secret_restore)
@ -117,7 +118,7 @@ int state_restore_all_sub(const char *filename, secret_restore);
void set_pos_from_return_segment(void);
int state_save_all(secret_save, blind_save);
int state_restore_all(int in_game, secret_restore, const char *filename_override, blind_save);
void StartNewLevelSub(int level_num, int page_in_textures, secret_restore);
window_event_result StartNewLevelSub(int level_num, int page_in_textures, secret_restore);
void init_player_stats_level(secret_restore);
#endif
}

View file

@ -1450,7 +1450,7 @@ static window_event_result AdvanceLevel(int secret_flag)
}
// END NMN
#endif
StartNewLevel(Next_level_num);
rval = std::max(StartNewLevel(Next_level_num), rval);
}
return rval;
@ -1563,9 +1563,9 @@ window_event_result DoPlayerDead()
//called when the player is starting a new level for normal game mode and restore state
// secret_flag set if came from a secret level
#if defined(DXX_BUILD_DESCENT_I)
void StartNewLevelSub(const int level_num, const int page_in_textures)
window_event_result StartNewLevelSub(const int level_num, const int page_in_textures)
#elif defined(DXX_BUILD_DESCENT_II)
void StartNewLevelSub(const int level_num, const int page_in_textures, const secret_restore secret_flag)
window_event_result StartNewLevelSub(const int level_num, const int page_in_textures, const secret_restore secret_flag)
#endif
{
if (!(Game_mode & GM_MULTI)) {
@ -1597,11 +1597,11 @@ void StartNewLevelSub(const int level_num, const int page_in_textures, const sec
if (Game_mode & GM_NETWORK)
{
multi_prep_level_objects();
if(multi_level_sync()) // After calling this, Player_num is set
multi_prep_level_objects();
if (multi_level_sync() == window_event_result::close) // After calling this, Player_num is set
{
songs_play_song( SONG_TITLE, 1 ); // level song already plays but we fail to start level...
return;
return window_event_result::close;
}
}
@ -1690,6 +1690,8 @@ void StartNewLevelSub(const int level_num, const int page_in_textures, const sec
if (!Game_wind)
game();
return window_event_result::handled;
}
}
@ -1799,7 +1801,7 @@ static void maybe_set_first_secret_visit(int level_num)
//called when the player is starting a new level for normal game model
// secret_flag if came from a secret level
namespace dsx {
void StartNewLevel(int level_num)
window_event_result StartNewLevel(int level_num)
{
hide_menus();
@ -1818,7 +1820,7 @@ void StartNewLevel(int level_num)
ShowLevelIntro(level_num);
#endif
StartNewLevelSub(level_num, 1, secret_restore::none);
return StartNewLevelSub(level_num, 1, secret_restore::none);
}
}

View file

@ -3445,7 +3445,7 @@ void multi_prep_level_player(void)
}
int multi_level_sync(void)
window_event_result multi_level_sync(void)
{
switch (multi_protocol)
{
@ -3458,6 +3458,8 @@ int multi_level_sync(void)
Error("Protocol handling missing in multi_level_sync\n");
break;
}
return window_event_result::ignored;
}
namespace dsx {

View file

@ -4330,11 +4330,8 @@ static int net_udp_start_game(void)
Netgame.protocol.udp.your_index = 0; // I am Host. I need to know that y'know? For syncing later.
if(net_udp_select_players())
{
StartNewLevel(Netgame.levelnum);
}
else
if (!net_udp_select_players()
|| StartNewLevel(Netgame.levelnum) == window_event_result::close)
{
Game_mode = GM_GAME_OVER;
return 0; // see if we want to tweak the game we setup
@ -4447,7 +4444,7 @@ menu:
}
/* Do required syncing after each level, before starting new one */
int net_udp_level_sync()
window_event_result net_udp_level_sync()
{
int result = 0;
@ -4471,13 +4468,11 @@ int net_udp_level_sync()
{
get_local_player().connected = CONNECT_DISCONNECTED;
net_udp_send_endlevel_packet();
if (Game_wind)
window_close(Game_wind);
show_menus();
net_udp_close();
return -1;
return window_event_result::close;
}
return(0);
return window_event_result::handled;
}
namespace dsx {
@ -4537,9 +4532,7 @@ int net_udp_do_join_game()
net_udp_set_game_mode(Netgame.gamemode);
StartNewLevel(Netgame.levelnum);
return 1; // look ma, we're in a game!!!
return StartNewLevel(Netgame.levelnum) == window_event_result::handled; // look ma, we're in a game!!! (If level syncing didn't fail -kreatordxx)
}
}