diff --git a/TODO.md b/TODO.md index 8d73e97..eec6f9a 100644 --- a/TODO.md +++ b/TODO.md @@ -4,17 +4,10 @@ crash 1. Fix bugs: - - Some races around game state: clients are in intermission, then level, then - intermission again when loading a new map - - `G_DoLoadLevel` - - `...` - - `G_WorldDone` - - `G_DoLoadLevel` - - Connection sometimes takes multiple tries + - Sometimes the server doesn't call `G_WorldDone` when `gameaction` is set to + `ga_worlddone`; something sets it back to `ga_nothing` first. - Nothing displays in console - - Probably scripting bug - - Should fix silently failing scripting... then again that probably goes to - the console to haha + - Checked, (probably) not a scripting bug - Console and messages widget should render during intermission - I think widgets need a "render during intermission" flag - Windows crashes pretty early on diff --git a/src/cl_net.c b/src/cl_net.c index ee473ae..9cc4ca1 100644 --- a/src/cl_net.c +++ b/src/cl_net.c @@ -432,6 +432,10 @@ bool CL_RePredicting(void) { return (CLIENT && cl_repredicting); } +void CL_SetNeedsInitNew(void) { + cl_needs_init_new = true; +} + void CL_ResetSync(void) { netpeer_t *server = CL_GetServerPeer(); diff --git a/src/cl_net.h b/src/cl_net.h index bc8709b..7fe8db0 100644 --- a/src/cl_net.h +++ b/src/cl_net.h @@ -37,6 +37,7 @@ bool CL_OccurredDuringRePrediction(int tic); bool CL_LoadingState(void); bool CL_Synchronizing(void); bool CL_RePredicting(void); +void CL_SetNeedsInitNew(void); void CL_ResetSync(void); #endif diff --git a/src/d_msg.c b/src/d_msg.c index ef5bab5..534a84d 100644 --- a/src/d_msg.c +++ b/src/d_msg.c @@ -172,6 +172,7 @@ void D_Msg(msg_channel_e chan, const char *fmt, ...) { va_list args; va_list log_args; va_list console_args; + va_list cmdline_args; message_channel_t *mc; check_message_channel(chan); @@ -202,6 +203,11 @@ void D_Msg(msg_channel_e chan, const char *fmt, ...) { fflush(mc->fobj); } + va_copy(cmdline_args, args); + vprintf(fmt, cmdline_args); + va_end(cmdline_args); + fflush(stdout); + va_end(args); } diff --git a/src/g_game.c b/src/g_game.c index 4b041ea..2d8696b 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -969,7 +969,7 @@ void G_RestartLevel(void) { // G_DoLoadLevel // -static void G_DoLoadLevel(void) { +void G_DoLoadLevel(void) { int i; if (CLIENT) { @@ -1473,8 +1473,9 @@ void G_Ticker(void) { switch (gameaction) { case ga_loadlevel: // force players to be initialized on level reload - for (i = 0; i < MAXPLAYERS; i++) + for (i = 0; i < MAXPLAYERS; i++) { players[i].playerstate = PST_REBORN; + } G_DoLoadLevel(); break; @@ -4029,8 +4030,47 @@ gameaction_t G_GetGameAction(void) { } void G_SetGameAction(gameaction_t new_gameaction) { + if (CLIENT) { + if (new_gameaction == ga_nothing) { + gameaction = ga_nothing; + } + return; + } + gameaction = new_gameaction; +#if 0 + switch (new_gameaction) { + case ga_nothing: + puts("ga_nothing"); + break; + case ga_loadlevel: + puts("ga_loadlevel"); + break; + case ga_newgame: + puts("ga_newgame"); + break; + case ga_loadgame: + puts("ga_loadgame"); + break; + case ga_savegame: + puts("ga_savegame"); + break; + case ga_playdemo: + puts("ga_playdemo"); + break; + case ga_completed: + puts("ga_completed"); + break; + case ga_victory: + puts("ga_victory"); + break; + case ga_worlddone: + puts("ga_worlddone"); + break; + } +#endif + if (SERVER && gameaction != ga_nothing) { SV_BroadcastGameActionChange(); } diff --git a/src/g_game.h b/src/g_game.h index a997090..525d1a3 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -462,6 +462,7 @@ void G_DoReborn(int playernum); void G_DoPlayDemo(void); void G_DoCompleted(void); void G_DoWorldDone(void); +void G_DoLoadLevel(void); void G_Compatibility(void); void G_ReadOptions(unsigned char game_options[]); void G_WriteOptions(unsigned char game_options[]); diff --git a/src/n_main.c b/src/n_main.c index 29368fb..9ac97d8 100644 --- a/src/n_main.c +++ b/src/n_main.c @@ -121,6 +121,7 @@ static bool should_render(void) { void N_InitNetGame(void) { int i; + time_t start_request_time; netgame = false; solonet = false; @@ -210,22 +211,36 @@ void N_InitNetGame(void) { "N_InitNetGame: Connecting to server %s:%u...\n", host, port ); - if (!N_Connect(host, port)) { - I_Error("N_InitNetGame: Connection refused"); - } + for (int i = 0; i < MAX_SETUP_REQUEST_ATTEMPTS; i++) { + if (!N_Connect(host, port)) { + I_Error("N_InitNetGame: Connection refused"); + } - D_Msg(MSG_INFO, "N_InitNetGame: Connected!\n"); + D_Msg(MSG_INFO, "N_InitNetGame: Connected!\n"); - if (!CL_GetServerPeer()) { - I_Error("N_InitNetGame: Server peer was NULL"); - } + if (!CL_GetServerPeer()) { + I_Error("N_InitNetGame: Server peer was NULL"); + } - G_ReloadDefaults(); + G_ReloadDefaults(); - for (size_t i = 1; i <= MAX_SETUP_REQUEST_ATTEMPTS; i++) { D_Msg(MSG_INFO, "N_InitNetGame: Requesting setup information...\n"); - CL_SendSetupRequest(); - N_ServiceNetworkTimeout(1000); + + start_request_time = time(NULL); + + while (N_Connected()) { + CL_SendSetupRequest(); + N_ServiceNetwork(); + + if (CL_ReceivedSetup()) { + break; + } + + if (difftime(time(NULL), start_request_time) > 10.0) { + break; + } + } + if (CL_ReceivedSetup()) { break; } diff --git a/src/n_main.h b/src/n_main.h index d247d69..25a74e1 100644 --- a/src/n_main.h +++ b/src/n_main.h @@ -120,6 +120,7 @@ void N_Disconnect(void); void N_Shutdown(void); bool N_Listen(const char *host, uint16_t port); bool N_Connect(const char *host, uint16_t port); +bool N_Connected(void); bool N_Reconnect(void); bool N_ConnectToServer(const char *address); void N_DisconnectPeer(netpeer_t *np); diff --git a/src/n_net.c b/src/n_net.c index a913dd8..74cfa7a 100644 --- a/src/n_net.c +++ b/src/n_net.c @@ -197,11 +197,13 @@ bool N_Connect(const char *host, uint16_t port) { previous_host = host; previous_port = port; - D_Msg(MSG_INFO, "N_Connect: connected"); - return true; } +bool N_Connected(void) { + return (net_host != NULL); +} + bool N_Reconnect(void) { if ((!previous_host) || (previous_port == 0)) { D_Msg(MSG_INFO, "No previous connection\n"); @@ -301,7 +303,6 @@ static void handle_enet_disconnection(ENetEvent *net_event) { if (CLIENT) { N_Disconnect(); - I_SafeExit(0); } N_PeerRemove(np); diff --git a/src/n_pack.c b/src/n_pack.c index f6e5ca2..49e9a8c 100644 --- a/src/n_pack.c +++ b/src/n_pack.c @@ -801,8 +801,6 @@ void N_PackSync(netpeer_t *np) { M_PBufWriteULong(pbuf, bitmap); - M_PBufWriteInt(pbuf, G_GetGameState()); - NETPEER_FOR_EACH(iter) { unsigned int playernum = N_PeerGetPlayernum(iter.np); @@ -839,14 +837,9 @@ bool N_UnpackSync(netpeer_t *np) { read_ulong(pbuf, m_bitmap, "sync player bitmap"); if (CLIENT) { - gamestate_t m_gamestate; int m_delta_from_tic; int m_delta_to_tic; - read_int(pbuf, m_gamestate, "game state"); - - CL_SetNewGameState(m_gamestate); - for (int i = 0; i < MAXPLAYERS; i++) { if ((m_bitmap & (1 << i)) == 0) { continue; diff --git a/src/n_proto.c b/src/n_proto.c index 6a27be0..8d7cdf5 100644 --- a/src/n_proto.c +++ b/src/n_proto.c @@ -203,7 +203,6 @@ static void handle_setup_request(netpeer_t *np) { static void handle_full_state(netpeer_t *np) { N_UnpackFullState(np); N_PeerSyncSetHasGameState(np); - CL_SetNewGameState(GS_LEVEL); } static void handle_auth_response(netpeer_t *np) { @@ -457,8 +456,29 @@ static void handle_game_action_change(netpeer_t *np) { return; } - G_SetGameAction(new_gameaction); gametic = new_gametic; + + switch (new_gameaction) { + case ga_loadlevel: + puts("got ga_loadlevel"); + // force players to be initialized on level reload + for (size_t i = 0; i < MAXPLAYERS; i++) { + players[i].playerstate = PST_REBORN; + } + + G_DoLoadLevel(); + break; + case ga_completed: + puts("got ga_completed"); + G_DoCompleted(); + break; + case ga_worlddone: + puts("got ga_worlddone"); + G_DoWorldDone(); + break; + default: + break; + } } static void handle_rcon(netpeer_t *np) {