From dee3724a13a1c141a36ecdc859858aa7de3f60ec Mon Sep 17 00:00:00 2001 From: Thilo Schulz Date: Tue, 21 Jun 2011 11:18:35 +0000 Subject: [PATCH] - Improve game_restart: * differing screen resolutions and network settings are now honoured when changing fs_game * Fix hunk memory leak on game_restart * Move cls.state and cls.servername to clc so connection state is fully preserved over game_restart * Revert back to previous fs_game after disconnecting from a server that triggered a game_restart * Fix error dialog popping up after every game_restart if an error happened previously (reported by Ensiform) - Fixed that not all commands added by CL_Init() would be removed by CL_Shutdown() --- code/client/cl_cgame.c | 14 +-- code/client/cl_cin.c | 10 +- code/client/cl_console.c | 23 +++- code/client/cl_input.c | 86 ++++++++++++- code/client/cl_keys.c | 18 +-- code/client/cl_main.c | 266 +++++++++++++++++++++++---------------- code/client/cl_parse.c | 7 +- code/client/cl_scrn.c | 8 +- code/client/cl_ui.c | 8 +- code/client/client.h | 17 +-- code/null/null_client.c | 16 ++- code/qcommon/common.c | 39 ++++-- code/qcommon/files.c | 7 +- code/qcommon/qcommon.h | 16 ++- code/sdl/sdl_input.c | 2 +- code/server/sv_init.c | 2 +- code/sys/sys_main.c | 6 +- 17 files changed, 354 insertions(+), 191 deletions(-) diff --git a/code/client/cl_cgame.c b/code/client/cl_cgame.c index 3794e56e..7a564848 100644 --- a/code/client/cl_cgame.c +++ b/code/client/cl_cgame.c @@ -743,7 +743,7 @@ void CL_InitCGame( void ) { if ( !cgvm ) { Com_Error( ERR_DROP, "VM_Create on cgame failed" ); } - cls.state = CA_LOADING; + clc.state = CA_LOADING; // init for this gamestate // use the lastExecutedServerCommand instead of the serverCommandSequence @@ -756,7 +756,7 @@ void CL_InitCGame( void ) { // we will send a usercmd this frame, which // will cause the server to send us the first snapshot - cls.state = CA_PRIMED; + clc.state = CA_PRIMED; t2 = Sys_Milliseconds(); @@ -894,7 +894,7 @@ void CL_FirstSnapshot( void ) { if ( cl.snap.snapFlags & SNAPFLAG_NOT_ACTIVE ) { return; } - cls.state = CA_ACTIVE; + clc.state = CA_ACTIVE; // set the timedelta so we are exactly on this first frame cl.serverTimeDelta = cl.snap.serverTime - cls.realtime; @@ -965,8 +965,8 @@ CL_SetCGameTime */ void CL_SetCGameTime( void ) { // getting a valid frame message ends the connection process - if ( cls.state != CA_ACTIVE ) { - if ( cls.state != CA_PRIMED ) { + if ( clc.state != CA_ACTIVE ) { + if ( clc.state != CA_PRIMED ) { return; } if ( clc.demoplaying ) { @@ -982,7 +982,7 @@ void CL_SetCGameTime( void ) { cl.newSnapshots = qfalse; CL_FirstSnapshot(); } - if ( cls.state != CA_ACTIVE ) { + if ( clc.state != CA_ACTIVE ) { return; } } @@ -1095,7 +1095,7 @@ void CL_SetCGameTime( void ) { // feed another messag, which should change // the contents of cl.snap CL_ReadDemoMessage(); - if ( cls.state != CA_ACTIVE ) { + if ( clc.state != CA_ACTIVE ) { return; // end of demo } } diff --git a/code/client/cl_cin.c b/code/client/cl_cin.c index 3bb20cce..54e72b4b 100644 --- a/code/client/cl_cin.c +++ b/code/client/cl_cin.c @@ -1281,7 +1281,7 @@ static void RoQShutdown( void ) { } if (cinTable[currentHandle].alterGameState) { - cls.state = CA_DISCONNECTED; + clc.state = CA_DISCONNECTED; // we can't just do a vstr nextmap, because // if we are aborting the intro cinematic with // a devmap command, nextmap would be valid by @@ -1314,7 +1314,7 @@ e_status CIN_StopCinematic(int handle) { } if (cinTable[currentHandle].alterGameState) { - if ( cls.state != CA_CINEMATIC ) { + if ( clc.state != CA_CINEMATIC ) { return cinTable[currentHandle].status; } } @@ -1355,7 +1355,7 @@ e_status CIN_RunCinematic (int handle) currentHandle = handle; if (cinTable[currentHandle].alterGameState) { - if ( cls.state != CA_CINEMATIC ) { + if ( clc.state != CA_CINEMATIC ) { return cinTable[currentHandle].status; } } @@ -1479,7 +1479,7 @@ int CIN_PlayCinematic( const char *arg, int x, int y, int w, int h, int systemBi Com_DPrintf("trFMV::play(), playing %s\n", arg); if (cinTable[currentHandle].alterGameState) { - cls.state = CA_CINEMATIC; + clc.state = CA_CINEMATIC; } Con_Close(); @@ -1614,7 +1614,7 @@ void CL_PlayCinematic_f(void) { int bits = CIN_system; Com_DPrintf("CL_PlayCinematic_f\n"); - if (cls.state == CA_CINEMATIC) { + if (clc.state == CA_CINEMATIC) { SCR_StopCinematic(); } diff --git a/code/client/cl_console.c b/code/client/cl_console.c index 196b5911..26317bee 100644 --- a/code/client/cl_console.c +++ b/code/client/cl_console.c @@ -72,7 +72,7 @@ Con_ToggleConsole_f */ void Con_ToggleConsole_f (void) { // Can't toggle the console when it's the only thing available - if ( cls.state == CA_DISCONNECTED && Key_GetCatcher( ) == KEYCATCH_CONSOLE ) { + if ( clc.state == CA_DISCONNECTED && Key_GetCatcher( ) == KEYCATCH_CONSOLE ) { return; } @@ -343,6 +343,21 @@ void Con_Init (void) { Cmd_SetCommandCompletionFunc( "condump", Cmd_CompleteTxtName ); } +/* +================ +Con_Shutdown +================ +*/ +void Con_Shutdown(void) +{ + Cmd_RemoveCommand("toggleconsole"); + Cmd_RemoveCommand("messagemode"); + Cmd_RemoveCommand("messagemode2"); + Cmd_RemoveCommand("messagemode3"); + Cmd_RemoveCommand("messagemode4"); + Cmd_RemoveCommand("clear"); + Cmd_RemoveCommand("condump"); +} /* =============== @@ -487,7 +502,7 @@ Draw the editline after a ] prompt void Con_DrawInput (void) { int y; - if ( cls.state != CA_DISCONNECTED && !(Key_GetCatcher( ) & KEYCATCH_CONSOLE ) ) { + if ( clc.state != CA_DISCONNECTED && !(Key_GetCatcher( ) & KEYCATCH_CONSOLE ) ) { return; } @@ -704,7 +719,7 @@ void Con_DrawConsole( void ) { Con_CheckResize (); // if disconnected, render console full screen - if ( cls.state == CA_DISCONNECTED ) { + if ( clc.state == CA_DISCONNECTED ) { if ( !( Key_GetCatcher( ) & (KEYCATCH_UI | KEYCATCH_CGAME)) ) { Con_DrawSolidConsole( 1.0 ); return; @@ -715,7 +730,7 @@ void Con_DrawConsole( void ) { Con_DrawSolidConsole( con.displayFrac ); } else { // draw notify lines - if ( cls.state == CA_ACTIVE ) { + if ( clc.state == CA_ACTIVE ) { Con_DrawNotify (); } } diff --git a/code/client/cl_input.c b/code/client/cl_input.c index 898a7b5a..60c26be4 100644 --- a/code/client/cl_input.c +++ b/code/client/cl_input.c @@ -640,7 +640,7 @@ void CL_CreateNewCommands( void ) { int cmdNum; // no need to create usercmds until we have a gamestate - if ( cls.state < CA_PRIMED ) { + if ( clc.state < CA_PRIMED ) { return; } @@ -677,7 +677,7 @@ qboolean CL_ReadyToSendPacket( void ) { int delta; // don't send anything if playing back a demo - if ( clc.demoplaying || cls.state == CA_CINEMATIC ) { + if ( clc.demoplaying || clc.state == CA_CINEMATIC ) { return qfalse; } @@ -689,8 +689,8 @@ qboolean CL_ReadyToSendPacket( void ) { // if we don't have a valid gamestate yet, only send // one packet a second - if ( cls.state != CA_ACTIVE && - cls.state != CA_PRIMED && + if ( clc.state != CA_ACTIVE && + clc.state != CA_PRIMED && !*clc.downloadTempName && cls.realtime - clc.lastPacketSentTime < 1000 ) { return qfalse; @@ -754,7 +754,7 @@ void CL_WritePacket( void ) { int count, key; // don't send anything if playing back a demo - if ( clc.demoplaying || cls.state == CA_CINEMATIC ) { + if ( clc.demoplaying || clc.state == CA_CINEMATIC ) { return; } @@ -949,7 +949,7 @@ Called every frame to builds and sends a command packet to the server. */ void CL_SendCmd( void ) { // don't send any message if not connected - if ( cls.state < CA_CONNECTED ) { + if ( clc.state < CA_CONNECTED ) { return; } @@ -1047,3 +1047,77 @@ void CL_InitInput( void ) { cl_nodelta = Cvar_Get ("cl_nodelta", "0", 0); cl_debugMove = Cvar_Get ("cl_debugMove", "0", 0); } + +/* +============ +CL_ShutdownInput +============ +*/ +void CL_ShutdownInput(void) +{ + Cmd_RemoveCommand("centerview"); + + Cmd_RemoveCommand("+moveup"); + Cmd_RemoveCommand("-moveup"); + Cmd_RemoveCommand("+movedown"); + Cmd_RemoveCommand("-movedown"); + Cmd_RemoveCommand("+left"); + Cmd_RemoveCommand("-left"); + Cmd_RemoveCommand("+right"); + Cmd_RemoveCommand("-right"); + Cmd_RemoveCommand("+forward"); + Cmd_RemoveCommand("-forward"); + Cmd_RemoveCommand("+back"); + Cmd_RemoveCommand("-back"); + Cmd_RemoveCommand("+lookup"); + Cmd_RemoveCommand("-lookup"); + Cmd_RemoveCommand("+lookdown"); + Cmd_RemoveCommand("-lookdown"); + Cmd_RemoveCommand("+strafe"); + Cmd_RemoveCommand("-strafe"); + Cmd_RemoveCommand("+moveleft"); + Cmd_RemoveCommand("-moveleft"); + Cmd_RemoveCommand("+moveright"); + Cmd_RemoveCommand("-moveright"); + Cmd_RemoveCommand("+speed"); + Cmd_RemoveCommand("-speed"); + Cmd_RemoveCommand("+attack"); + Cmd_RemoveCommand("-attack"); + Cmd_RemoveCommand("+button0"); + Cmd_RemoveCommand("-button0"); + Cmd_RemoveCommand("+button1"); + Cmd_RemoveCommand("-button1"); + Cmd_RemoveCommand("+button2"); + Cmd_RemoveCommand("-button2"); + Cmd_RemoveCommand("+button3"); + Cmd_RemoveCommand("-button3"); + Cmd_RemoveCommand("+button4"); + Cmd_RemoveCommand("-button4"); + Cmd_RemoveCommand("+button5"); + Cmd_RemoveCommand("-button5"); + Cmd_RemoveCommand("+button6"); + Cmd_RemoveCommand("-button6"); + Cmd_RemoveCommand("+button7"); + Cmd_RemoveCommand("-button7"); + Cmd_RemoveCommand("+button8"); + Cmd_RemoveCommand("-button8"); + Cmd_RemoveCommand("+button9"); + Cmd_RemoveCommand("-button9"); + Cmd_RemoveCommand("+button10"); + Cmd_RemoveCommand("-button10"); + Cmd_RemoveCommand("+button11"); + Cmd_RemoveCommand("-button11"); + Cmd_RemoveCommand("+button12"); + Cmd_RemoveCommand("-button12"); + Cmd_RemoveCommand("+button13"); + Cmd_RemoveCommand("-button13"); + Cmd_RemoveCommand("+button14"); + Cmd_RemoveCommand("-button14"); + Cmd_RemoveCommand("+mlook"); + Cmd_RemoveCommand("-mlook"); + +#ifdef USE_VOIP + Cmd_RemoveCommand("+voiprecord"); + Cmd_RemoveCommand("-voiprecord"); +#endif +} diff --git a/code/client/cl_keys.c b/code/client/cl_keys.c index 17bed13e..80e66754 100644 --- a/code/client/cl_keys.c +++ b/code/client/cl_keys.c @@ -586,7 +586,7 @@ void Console_Key (int key) { // enter finishes the line if ( key == K_ENTER || key == K_KP_ENTER ) { // if not in the game explicitly prepend a slash if needed - if ( cls.state != CA_ACTIVE && + if ( clc.state != CA_ACTIVE && g_consoleField.buffer[0] && g_consoleField.buffer[0] != '\\' && g_consoleField.buffer[0] != '/' ) { @@ -625,7 +625,7 @@ void Console_Key (int key) { CL_SaveConsoleHistory( ); - if ( cls.state == CA_DISCONNECTED ) { + if ( clc.state == CA_DISCONNECTED ) { SCR_UpdateScreen (); // force an update, because the command } // may take some time return; @@ -731,7 +731,7 @@ void Message_Key( int key ) { if ( key == K_ENTER || key == K_KP_ENTER ) { - if ( chatField.buffer[0] && cls.state == CA_ACTIVE ) { + if ( chatField.buffer[0] && clc.state == CA_ACTIVE ) { if (chat_playerNum != -1 ) Com_sprintf( buffer, sizeof( buffer ), "tell %i \"%s\"\n", chat_playerNum, chatField.buffer ); @@ -1196,7 +1196,7 @@ void CL_KeyDownEvent( int key, unsigned time ) // keys can still be used for bound actions if ( ( key < 128 || key == K_MOUSE1 ) && - ( clc.demoplaying || cls.state == CA_CINEMATIC ) && Key_GetCatcher( ) == 0 ) { + ( clc.demoplaying || clc.state == CA_CINEMATIC ) && Key_GetCatcher( ) == 0 ) { if (Cvar_VariableValue ("com_cameraMode") == 0) { Cvar_Set ("nextdemo",""); @@ -1220,10 +1220,10 @@ void CL_KeyDownEvent( int key, unsigned time ) } if ( !( Key_GetCatcher( ) & KEYCATCH_UI ) ) { - if ( cls.state == CA_ACTIVE && !clc.demoplaying ) { + if ( clc.state == CA_ACTIVE && !clc.demoplaying ) { VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_INGAME ); } - else if ( cls.state != CA_DISCONNECTED ) { + else if ( clc.state != CA_DISCONNECTED ) { CL_Disconnect_f(); S_StopAllSounds(); VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_MAIN ); @@ -1248,7 +1248,7 @@ void CL_KeyDownEvent( int key, unsigned time ) } } else if ( Key_GetCatcher( ) & KEYCATCH_MESSAGE ) { Message_Key( key ); - } else if ( cls.state == CA_DISCONNECTED ) { + } else if ( clc.state == CA_DISCONNECTED ) { Console_Key( key ); } else { // send the bound action @@ -1285,7 +1285,7 @@ void CL_KeyUpEvent( int key, unsigned time ) // console mode and menu mode, to keep the character from continuing // an action started before a mode switch. // - if( cls.state != CA_DISCONNECTED ) + if( clc.state != CA_DISCONNECTED ) CL_ParseBinding( key, qfalse, time ); if ( Key_GetCatcher( ) & KEYCATCH_UI && uivm ) { @@ -1336,7 +1336,7 @@ void CL_CharEvent( int key ) { { Field_CharEvent( &chatField, key ); } - else if ( cls.state == CA_DISCONNECTED ) + else if ( clc.state == CA_DISCONNECTED ) { Field_CharEvent( &g_consoleField, key ); } diff --git a/code/client/cl_main.c b/code/client/cl_main.c index 4f328b49..804e9a95 100644 --- a/code/client/cl_main.c +++ b/code/client/cl_main.c @@ -231,7 +231,7 @@ void CL_Voip_f( void ) const char *cmd = Cmd_Argv(1); const char *reason = NULL; - if (cls.state != CA_ACTIVE) + if (clc.state != CA_ACTIVE) reason = "Not connected to a server"; else if (!clc.speexInitialized) reason = "Speex not initialized"; @@ -329,7 +329,7 @@ void CL_CaptureVoip(void) if (cl_voipSend->modified) { qboolean dontCapture = qfalse; - if (cls.state != CA_ACTIVE) + if (clc.state != CA_ACTIVE) dontCapture = qtrue; // not connected to a server. else if (!cl_connectedToVoipServer) dontCapture = qtrue; // server doesn't support VoIP. @@ -623,7 +623,7 @@ void CL_Record_f( void ) { return; } - if ( cls.state != CA_ACTIVE ) { + if ( clc.state != CA_ACTIVE ) { Com_Printf ("You must be in a level to record.\n"); return; } @@ -1009,12 +1009,12 @@ void CL_PlayDemo_f( void ) { Con_Close(); - cls.state = CA_CONNECTED; + clc.state = CA_CONNECTED; clc.demoplaying = qtrue; - Q_strncpyz( cls.servername, Cmd_Argv(1), sizeof( cls.servername ) ); + Q_strncpyz( clc.servername, Cmd_Argv(1), sizeof( clc.servername ) ); // read demo messages until connected - while ( cls.state >= CA_CONNECTED && cls.state < CA_PRIMED ) { + while ( clc.state >= CA_CONNECTED && clc.state < CA_PRIMED ) { CL_ReadDemoMessage(); } // don't get the first snapshot this frame, to prevent the long @@ -1068,7 +1068,13 @@ void CL_NextDemo( void ) { CL_ShutdownAll ===================== */ -void CL_ShutdownAll(void) { +void CL_ShutdownAll(qboolean shutdownRef) +{ + if(CL_VideoRecording()) + CL_CloseAVI(); + + if(clc.demorecording) + CL_StopRecord_f(); #ifdef USE_CURL CL_cURL_Shutdown(); @@ -1081,9 +1087,10 @@ void CL_ShutdownAll(void) { CL_ShutdownUI(); // shutdown the renderer - if ( re.Shutdown ) { - re.Shutdown( qfalse ); // don't destroy window or context - } + if(shutdownRef) + CL_ShutdownRef(); + else if(re.Shutdown) + re.Shutdown(qfalse); // don't destroy window or context cls.uiStarted = qfalse; cls.cgameStarted = qfalse; @@ -1093,17 +1100,15 @@ void CL_ShutdownAll(void) { /* ================= -CL_FlushMemory +CL_ClearMemory -Called by CL_MapLoading, CL_Connect_f, CL_PlayDemo_f, and CL_ParseGamestate the only -ways a client gets into a game -Also called by Com_Error +Called by Com_GameRestart ================= */ -void CL_FlushMemory( void ) { - +void CL_ClearMemory(qboolean shutdownRef) +{ // shutdown all the client stuff - CL_ShutdownAll(); + CL_ShutdownAll(shutdownRef); // if not running a server clear the whole hunk if ( !com_sv_running->integer ) { @@ -1116,8 +1121,21 @@ void CL_FlushMemory( void ) { // clear all the client data on the hunk Hunk_ClearToMark(); } +} - CL_StartHunkUsers( qfalse ); +/* +================= +CL_FlushMemory + +Called by CL_MapLoading, CL_Connect_f, CL_PlayDemo_f, and CL_ParseGamestate the only +ways a client gets into a game +Also called by Com_Error +================= +*/ +void CL_FlushMemory(void) +{ + CL_ClearMemory(qfalse); + CL_StartHunkUsers(qfalse); } /* @@ -1131,7 +1149,7 @@ memory on the hunk from cgame, ui, and renderer */ void CL_MapLoading( void ) { if ( com_dedicated->integer ) { - cls.state = CA_DISCONNECTED; + clc.state = CA_DISCONNECTED; Key_SetCatcher( KEYCATCH_CONSOLE ); return; } @@ -1144,8 +1162,8 @@ void CL_MapLoading( void ) { Key_SetCatcher( 0 ); // if we are already connected to the local host, stay connected - if ( cls.state >= CA_CONNECTED && !Q_stricmp( cls.servername, "localhost" ) ) { - cls.state = CA_CONNECTED; // so the connect screen is drawn + if ( clc.state >= CA_CONNECTED && !Q_stricmp( clc.servername, "localhost" ) ) { + clc.state = CA_CONNECTED; // so the connect screen is drawn Com_Memset( cls.updateInfoString, 0, sizeof( cls.updateInfoString ) ); Com_Memset( clc.serverMessage, 0, sizeof( clc.serverMessage ) ); Com_Memset( &cl.gameState, 0, sizeof( cl.gameState ) ); @@ -1155,12 +1173,12 @@ void CL_MapLoading( void ) { // clear nextmap so the cinematic shutdown doesn't execute it Cvar_Set( "nextmap", "" ); CL_Disconnect( qtrue ); - Q_strncpyz( cls.servername, "localhost", sizeof(cls.servername) ); - cls.state = CA_CHALLENGING; // so the connect screen is drawn + Q_strncpyz( clc.servername, "localhost", sizeof(clc.servername) ); + clc.state = CA_CHALLENGING; // so the connect screen is drawn Key_SetCatcher( 0 ); SCR_UpdateScreen(); clc.connectTime = -RETRANSMIT_TIMEOUT; - NET_StringToAdr( cls.servername, &clc.serverAddress, NA_UNSPEC); + NET_StringToAdr( clc.servername, &clc.serverAddress, NA_UNSPEC); // we don't need a challenge on the localhost CL_CheckForResend(); @@ -1203,6 +1221,17 @@ static void CL_UpdateGUID( const char *prefix, int prefix_len ) prefix, prefix_len ) ); } +static void CL_OldGame(void) +{ + char *curGame = Cvar_VariableString("fs_game"); + + if(cls.oldGame[0] || *curGame) + { + // change back to previous fs_game + Cvar_Set("fs_game", cls.oldGame); + Com_GameRestart(0, qtrue); + } +} /* ===================== @@ -1277,7 +1306,7 @@ void CL_Disconnect( qboolean showMainMenu ) { // send a disconnect message to the server // send it a few times in case one is dropped - if ( cls.state >= CA_CONNECTED ) { + if ( clc.state >= CA_CONNECTED ) { CL_AddReliableCommand("disconnect", qtrue); CL_WritePacket(); CL_WritePacket(); @@ -1292,7 +1321,7 @@ void CL_Disconnect( qboolean showMainMenu ) { // wipe the client connection Com_Memset( &clc, 0, sizeof( clc ) ); - cls.state = CA_DISCONNECTED; + clc.state = CA_DISCONNECTED; // allow cheats locally Cvar_Set( "sv_cheats", "1" ); @@ -1311,7 +1340,9 @@ void CL_Disconnect( qboolean showMainMenu ) { SCR_UpdateScreen( ); CL_CloseAVI( ); } + CL_UpdateGUID( NULL, 0 ); + CL_OldGame(); } @@ -1334,7 +1365,7 @@ void CL_ForwardCommandToServer( const char *string ) { return; } - if ( clc.demoplaying || cls.state < CA_CONNECTED || cmd[0] == '+' ) { + if ( clc.demoplaying || clc.state < CA_CONNECTED || cmd[0] == '+' ) { Com_Printf ("Unknown command \"%s" S_COLOR_WHITE "\"\n", cmd); return; } @@ -1477,7 +1508,7 @@ CL_ForwardToServer_f ================== */ void CL_ForwardToServer_f( void ) { - if ( cls.state != CA_ACTIVE || clc.demoplaying ) { + if ( clc.state != CA_ACTIVE || clc.demoplaying ) { Com_Printf ("Not connected to a server.\n"); return; } @@ -1496,7 +1527,7 @@ CL_Disconnect_f void CL_Disconnect_f( void ) { SCR_StopCinematic(); Cvar_Set("ui_singlePlayerActive", "0"); - if ( cls.state != CA_DISCONNECTED && cls.state != CA_CINEMATIC ) { + if ( clc.state != CA_DISCONNECTED && clc.state != CA_CINEMATIC ) { Com_Error (ERR_DISCONNECT, "Disconnected from server"); } } @@ -1509,12 +1540,12 @@ CL_Reconnect_f ================ */ void CL_Reconnect_f( void ) { - if ( !strlen( cls.servername ) || !strcmp( cls.servername, "localhost" ) ) { + if ( !strlen( clc.servername ) || !strcmp( clc.servername, "localhost" ) ) { Com_Printf( "Can't reconnect to localhost.\n" ); return; } Cvar_Set("ui_singlePlayerActive", "0"); - Cbuf_AddText( va("connect %s\n", cls.servername ) ); + Cbuf_AddText( va("connect %s\n", clc.servername ) ); } /* @@ -1568,11 +1599,11 @@ void CL_Connect_f( void ) { CL_Disconnect( qtrue ); Con_Close(); - Q_strncpyz( cls.servername, server, sizeof(cls.servername) ); + Q_strncpyz( clc.servername, server, sizeof(clc.servername) ); - if (!NET_StringToAdr(cls.servername, &clc.serverAddress, family) ) { + if (!NET_StringToAdr(clc.servername, &clc.serverAddress, family) ) { Com_Printf ("Bad server address\n"); - cls.state = CA_DISCONNECTED; + clc.state = CA_DISCONNECTED; return; } if (clc.serverAddress.port == 0) { @@ -1581,7 +1612,7 @@ void CL_Connect_f( void ) { serverString = NET_AdrToStringwPort(clc.serverAddress); - Com_Printf( "%s resolved to %s\n", cls.servername, serverString); + Com_Printf( "%s resolved to %s\n", clc.servername, serverString); if( cl_guidServerUniq->integer ) CL_UpdateGUID( serverString, strlen( serverString ) ); @@ -1591,10 +1622,10 @@ void CL_Connect_f( void ) { // if we aren't playing on a lan, we need to authenticate // with the cd key if(NET_IsLocalAddress(clc.serverAddress)) - cls.state = CA_CHALLENGING; + clc.state = CA_CHALLENGING; else { - cls.state = CA_CONNECTING; + clc.state = CA_CONNECTING; // Set a client challenge number that ideally is mirrored back by the server. clc.challenge = ((rand() << 16) ^ rand()) ^ Com_Milliseconds(); @@ -1659,7 +1690,7 @@ void CL_Rcon_f( void ) { // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=543 Q_strcat (message, MAX_RCON_MESSAGE, Cmd_Cmd()+5); - if ( cls.state >= CA_CONNECTED ) { + if ( clc.state >= CA_CONNECTED ) { to = clc.netchan.remoteAddress; } else { if (!strlen(rconAddress->string)) { @@ -1723,49 +1754,55 @@ void CL_Vid_Restart_f( void ) { // don't let them loop during the restart S_StopAllSounds(); - // shutdown the UI - CL_ShutdownUI(); - // shutdown the CGame - CL_ShutdownCGame(); - // shutdown the renderer and clear the renderer interface - CL_ShutdownRef(); - // client is no longer pure untill new checksums are sent - CL_ResetPureClientAtServer(); - // clear pak references - FS_ClearPakReferences( FS_UI_REF | FS_CGAME_REF ); - // reinitialize the filesystem if the game directory or checksum has changed - FS_ConditionalRestart( clc.checksumFeed ); - cls.rendererStarted = qfalse; - cls.uiStarted = qfalse; - cls.cgameStarted = qfalse; - cls.soundRegistered = qfalse; + if(!FS_ConditionalRestart(clc.checksumFeed, qtrue)) + { + // if not running a server clear the whole hunk + if(com_sv_running->integer) + { + // clear all the client data on the hunk + Hunk_ClearToMark(); + } + else + { + // clear the whole hunk + Hunk_Clear(); + } + + // shutdown the UI + CL_ShutdownUI(); + // shutdown the CGame + CL_ShutdownCGame(); + // shutdown the renderer and clear the renderer interface + CL_ShutdownRef(); + // client is no longer pure untill new checksums are sent + CL_ResetPureClientAtServer(); + // clear pak references + FS_ClearPakReferences( FS_UI_REF | FS_CGAME_REF ); + // reinitialize the filesystem if the game directory or checksum has changed - // unpause so the cgame definately gets a snapshot and renders a frame - Cvar_Set( "cl_paused", "0" ); + cls.rendererStarted = qfalse; + cls.uiStarted = qfalse; + cls.cgameStarted = qfalse; + cls.soundRegistered = qfalse; - // if not running a server clear the whole hunk - if ( !com_sv_running->integer ) { - // clear the whole hunk - Hunk_Clear(); - } - else { - // clear all the client data on the hunk - Hunk_ClearToMark(); - } + // unpause so the cgame definately gets a snapshot and renders a frame + Cvar_Set("cl_paused", "0"); - // initialize the renderer interface - CL_InitRef(); + // initialize the renderer interface + CL_InitRef(); - // startup all the client stuff - CL_StartHunkUsers( qfalse ); + // startup all the client stuff + CL_StartHunkUsers(qfalse); - // start the cgame if connected - if ( cls.state > CA_CONNECTED && cls.state != CA_CINEMATIC ) { - cls.cgameStarted = qtrue; - CL_InitCGame(); - // send pure checksums - CL_SendPureChecksums(); + // start the cgame if connected + if(clc.state > CA_CONNECTED && clc.state != CA_CINEMATIC) + { + cls.cgameStarted = qtrue; + CL_InitCGame(); + // send pure checksums + CL_SendPureChecksums(); + } } } @@ -1826,7 +1863,7 @@ void CL_Configstrings_f( void ) { int i; int ofs; - if ( cls.state != CA_ACTIVE ) { + if ( clc.state != CA_ACTIVE ) { Com_Printf( "Not connected to a server.\n"); return; } @@ -1847,8 +1884,8 @@ CL_Clientinfo_f */ void CL_Clientinfo_f( void ) { Com_Printf( "--------- Client Information ---------\n" ); - Com_Printf( "state: %i\n", cls.state ); - Com_Printf( "Server: %s\n", cls.servername ); + Com_Printf( "state: %i\n", clc.state ); + Com_Printf( "Server: %s\n", clc.servername ); Com_Printf ("User info settings:\n"); Info_Print( Cvar_InfoString( CVAR_USERINFO ) ); Com_Printf( "--------------------------------------\n" ); @@ -1898,14 +1935,14 @@ void CL_DownloadsComplete( void ) { } // let the client game init and load data - cls.state = CA_LOADING; + clc.state = CA_LOADING; // Pump the loop, this may change gamestate! Com_EventLoop(); // if the gamestate was changed by calling Com_EventLoop // then we loaded everything already and we don't want to do it again. - if ( cls.state != CA_LOADING ) { + if ( clc.state != CA_LOADING ) { return; } @@ -2091,7 +2128,7 @@ void CL_InitDownloads(void) { if ( *clc.downloadList ) { // if autodownloading is not enabled on the server - cls.state = CA_CONNECTED; + clc.state = CA_CONNECTED; *clc.downloadTempName = *clc.downloadName = 0; Cvar_Set( "cl_downloadName", "" ); @@ -2123,7 +2160,7 @@ void CL_CheckForResend( void ) { } // resend if we haven't gotten a reply yet - if ( cls.state != CA_CONNECTING && cls.state != CA_CHALLENGING ) { + if ( clc.state != CA_CONNECTING && clc.state != CA_CHALLENGING ) { return; } @@ -2135,7 +2172,7 @@ void CL_CheckForResend( void ) { clc.connectPacketCount++; - switch ( cls.state ) { + switch ( clc.state ) { case CA_CONNECTING: // requesting a challenge .. IPv6 users always get in as authorize server supports no ipv6. #ifndef STANDALONE @@ -2177,7 +2214,7 @@ void CL_CheckForResend( void ) { break; default: - Com_Error( ERR_FATAL, "CL_CheckForResend: bad cls.state" ); + Com_Error( ERR_FATAL, "CL_CheckForResend: bad clc.state" ); } } @@ -2192,7 +2229,7 @@ to the client so it doesn't have to wait for the full timeout period. =================== */ void CL_DisconnectPacket( netadr_t from ) { - if ( cls.state < CA_AUTHORIZING ) { + if ( clc.state < CA_AUTHORIZING ) { return; } @@ -2410,7 +2447,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { // challenge from the server we are connecting to if (!Q_stricmp(c, "challengeResponse")) { - if (cls.state != CA_CONNECTING) + if (clc.state != CA_CONNECTING) { Com_DPrintf("Unwanted challenge response received. Ignored.\n"); return; @@ -2433,7 +2470,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { // start sending challenge response instead of challenge request packets clc.challenge = atoi(Cmd_Argv(1)); - cls.state = CA_CHALLENGING; + clc.state = CA_CHALLENGING; clc.connectPacketCount = 0; clc.connectTime = -99999; @@ -2446,11 +2483,11 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { // server connection if ( !Q_stricmp(c, "connectResponse") ) { - if ( cls.state >= CA_CONNECTED ) { + if ( clc.state >= CA_CONNECTED ) { Com_Printf ("Dup connect received. Ignored.\n"); return; } - if ( cls.state != CA_CHALLENGING ) { + if ( clc.state != CA_CHALLENGING ) { Com_Printf ("connectResponse packet while not connecting. Ignored.\n"); return; } @@ -2459,7 +2496,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { return; } Netchan_Setup (NS_CLIENT, &clc.netchan, from, Cvar_VariableValue( "net_qport" ) ); - cls.state = CA_CONNECTED; + clc.state = CA_CONNECTED; clc.lastPacketSentTime = -9999; // send first packet immediately return; } @@ -2542,7 +2579,7 @@ void CL_PacketEvent( netadr_t from, msg_t *msg ) { return; } - if ( cls.state < CA_CONNECTED ) { + if ( clc.state < CA_CONNECTED ) { return; // can't be a valid sequenced packet } @@ -2596,7 +2633,7 @@ void CL_CheckTimeout( void ) { // check timeout // if ( ( !CL_CheckPaused() || !sv_paused->integer ) - && cls.state >= CA_CONNECTED && cls.state != CA_CINEMATIC + && clc.state >= CA_CONNECTED && clc.state != CA_CINEMATIC && cls.realtime - clc.lastPacketTime > cl_timeout->value*1000) { if (++cl.timeoutcount > 5) { // timeoutcount saves debugger Com_Printf ("\nServer connection timed out.\n"); @@ -2635,7 +2672,7 @@ CL_CheckUserinfo */ void CL_CheckUserinfo( void ) { // don't add reliable commands when not yet connected - if(cls.state < CA_CONNECTED) + if(clc.state < CA_CONNECTED) return; // don't overflow the reliable command buffer when paused @@ -2666,7 +2703,7 @@ void CL_Frame ( int msec ) { if(clc.downloadCURLM) { CL_cURL_PerformDownload(); // we can't process frames normally when in disconnected - // download mode since the ui vm expects cls.state to be + // download mode since the ui vm expects clc.state to be // CA_CONNECTED if(clc.cURLDisconnected) { cls.realFrametime = msec; @@ -2685,7 +2722,7 @@ void CL_Frame ( int msec ) { // bring up the cd error dialog if needed cls.cddialog = qfalse; VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_NEED_CD ); - } else if ( cls.state == CA_DISCONNECTED && !( Key_GetCatcher( ) & KEYCATCH_UI ) + } else if ( clc.state == CA_DISCONNECTED && !( Key_GetCatcher( ) & KEYCATCH_UI ) && !com_sv_running->integer && uivm ) { // if disconnected, bring up the menu S_StopAllSounds(); @@ -2695,7 +2732,7 @@ void CL_Frame ( int msec ) { // if recording an avi, lock to a fixed fps if ( CL_VideoRecording( ) && cl_aviFrameRate->integer && msec) { // save the current screen - if ( cls.state == CA_ACTIVE || cl_forceavidemo->integer) { + if ( clc.state == CA_ACTIVE || cl_forceavidemo->integer) { CL_TakeVideoFrame( ); // fixed time for next frame' @@ -2707,7 +2744,7 @@ void CL_Frame ( int msec ) { } if( cl_autoRecordDemo->integer ) { - if( cls.state == CA_ACTIVE && !clc.demorecording && !clc.demoplaying ) { + if( clc.state == CA_ACTIVE && !clc.demorecording && !clc.demoplaying ) { // If not recording a demo, and we should be, start one qtime_t now; char *nowString; @@ -2724,7 +2761,7 @@ void CL_Frame ( int msec ) { now.tm_min, now.tm_sec ); - Q_strncpyz( serverName, cls.servername, MAX_OSPATH ); + Q_strncpyz( serverName, clc.servername, MAX_OSPATH ); // Replace the ":" in the address as it is not a valid // file name character p = strstr( serverName, ":" ); @@ -2738,7 +2775,7 @@ void CL_Frame ( int msec ) { Cbuf_ExecuteText( EXEC_NOW, va( "record %s-%s-%s", nowString, serverName, mapName ) ); } - else if( cls.state != CA_ACTIVE && clc.demorecording ) { + else if( clc.state != CA_ACTIVE && clc.demorecording ) { // Recording, but not CA_ACTIVE, so stop recording CL_StopRecord_f( ); } @@ -3119,9 +3156,11 @@ void CL_Init( void ) { Con_Init (); - CL_ClearState (); - - cls.state = CA_DISCONNECTED; // no longer CA_UNINITIALIZED + if(!com_fullyInitialized) + { + CL_ClearState(); + clc.state = CA_DISCONNECTED; // no longer CA_UNINITIALIZED + } cls.realtime = 0; @@ -3334,7 +3373,8 @@ CL_Shutdown =============== */ -void CL_Shutdown( char *finalmsg ) { +void CL_Shutdown(char *finalmsg, qboolean disconnect) +{ static qboolean recursive = qfalse; // check whether the client is running at all. @@ -3349,16 +3389,15 @@ void CL_Shutdown( char *finalmsg ) { } recursive = qtrue; - CL_Disconnect( qtrue ); - - CL_Snd_Shutdown(); - CL_ShutdownRef(); + if(disconnect) + CL_Disconnect(qtrue); - CL_ShutdownUI(); + CL_Snd_Shutdown(); + CL_ClearMemory(qtrue); Cmd_RemoveCommand ("cmd"); Cmd_RemoveCommand ("configstrings"); - Cmd_RemoveCommand ("userinfo"); + Cmd_RemoveCommand ("clientinfo"); Cmd_RemoveCommand ("snd_restart"); Cmd_RemoveCommand ("vid_restart"); Cmd_RemoveCommand ("disconnect"); @@ -3367,15 +3406,22 @@ void CL_Shutdown( char *finalmsg ) { Cmd_RemoveCommand ("cinematic"); Cmd_RemoveCommand ("stoprecord"); Cmd_RemoveCommand ("connect"); + Cmd_RemoveCommand ("reconnect"); Cmd_RemoveCommand ("localservers"); Cmd_RemoveCommand ("globalservers"); Cmd_RemoveCommand ("rcon"); Cmd_RemoveCommand ("ping"); Cmd_RemoveCommand ("serverstatus"); Cmd_RemoveCommand ("showip"); + Cmd_RemoveCommand ("fs_openedList"); + Cmd_RemoveCommand ("fs_referencedList"); Cmd_RemoveCommand ("model"); Cmd_RemoveCommand ("video"); Cmd_RemoveCommand ("stopvideo"); + Cmd_RemoveCommand ("minimize"); + + CL_ShutdownInput(); + Con_Shutdown(); Cvar_Set( "cl_running", "0" ); @@ -4168,7 +4214,7 @@ void CL_ServerStatus_f(void) { if ( argc != 2 && argc != 3 ) { - if (cls.state != CA_ACTIVE || clc.demoplaying) + if (clc.state != CA_ACTIVE || clc.demoplaying) { Com_Printf ("Not connected to a server.\n"); Com_Printf( "usage: serverstatus [-4|-6] server\n"); diff --git a/code/client/cl_parse.c b/code/client/cl_parse.c index 1796afbe..315aa943 100644 --- a/code/client/cl_parse.c +++ b/code/client/cl_parse.c @@ -463,6 +463,7 @@ void CL_ParseGamestate( msg_t *msg ) { entityState_t nullstate; int cmd; char *s; + char oldGame[MAX_QPATH]; Con_Close(); @@ -518,6 +519,9 @@ void CL_ParseGamestate( msg_t *msg ) { // read the checksum feed clc.checksumFeed = MSG_ReadLong( msg ); + // save old gamedir + Cvar_VariableStringBuffer("fs_game", oldGame, sizeof(oldGame)); + // parse useful values out of CS_SERVERINFO CL_ParseServerInfo(); @@ -529,7 +533,8 @@ void CL_ParseGamestate( msg_t *msg ) { CL_StopRecord_f(); // reinitialize the filesystem if the game directory has changed - FS_ConditionalRestart( clc.checksumFeed ); + if(FS_ConditionalRestart(clc.checksumFeed, qfalse) && !cls.oldGame[0]) + Q_strncpyz(cls.oldGame, oldGame, sizeof(cls.oldGame)); // This used to call CL_StartHunkUsers, but now we enter the download state before loading the // cgame diff --git a/code/client/cl_scrn.c b/code/client/cl_scrn.c index 6e160c42..3929d9c4 100644 --- a/code/client/cl_scrn.c +++ b/code/client/cl_scrn.c @@ -360,7 +360,7 @@ void SCR_DrawVoipMeter( void ) { return; // player doesn't want to show meter at all. else if (!cl_voipSend->integer) return; // not recording at the moment. - else if (cls.state != CA_ACTIVE) + else if (clc.state != CA_ACTIVE) return; // not connected to a server. else if (!cl_connectedToVoipServer) return; // server doesn't support VoIP. @@ -488,7 +488,7 @@ void SCR_DrawScreenField( stereoFrame_t stereoFrame ) { // wide aspect ratio screens need to have the sides cleared // unless they are displaying game renderings - if ( uiFullscreen || (cls.state != CA_ACTIVE && cls.state != CA_CINEMATIC) ) { + if ( uiFullscreen || (clc.state != CA_ACTIVE && clc.state != CA_CINEMATIC) ) { if ( cls.glconfig.vidWidth * 480 > cls.glconfig.vidHeight * 640 ) { re.SetColor( g_color_table[0] ); re.DrawStretchPic( 0, 0, cls.glconfig.vidWidth, cls.glconfig.vidHeight, 0, 0, 0, 0, cls.whiteShader ); @@ -499,9 +499,9 @@ void SCR_DrawScreenField( stereoFrame_t stereoFrame ) { // if the menu is going to cover the entire screen, we // don't need to render anything under it if ( uivm && !uiFullscreen ) { - switch( cls.state ) { + switch( clc.state ) { default: - Com_Error( ERR_FATAL, "SCR_DrawScreenField: bad cls.state" ); + Com_Error( ERR_FATAL, "SCR_DrawScreenField: bad clc.state" ); break; case CA_CINEMATIC: SCR_DrawCinematic(); diff --git a/code/client/cl_ui.c b/code/client/cl_ui.c index b8d13c51..e65977bd 100644 --- a/code/client/cl_ui.c +++ b/code/client/cl_ui.c @@ -35,8 +35,8 @@ GetClientState */ static void GetClientState( uiClientState_t *state ) { state->connectPacketCount = clc.connectPacketCount; - state->connState = cls.state; - Q_strncpyz( state->servername, cls.servername, sizeof( state->servername ) ); + state->connState = clc.state; + Q_strncpyz( state->servername, clc.servername, sizeof( state->servername ) ); Q_strncpyz( state->updateInfoString, cls.updateInfoString, sizeof( state->updateInfoString ) ); Q_strncpyz( state->messageString, clc.serverMessage, sizeof( state->messageString ) ); state->clientNum = cl.snap.ps.clientNum; @@ -1115,7 +1115,7 @@ void CL_InitUI( void ) { if (v == UI_OLD_API_VERSION) { // Com_Printf(S_COLOR_YELLOW "WARNING: loading old Quake III Arena User Interface version %d\n", v ); // init for this gamestate - VM_Call( uivm, UI_INIT, (cls.state >= CA_AUTHORIZING && cls.state < CA_ACTIVE)); + VM_Call( uivm, UI_INIT, (clc.state >= CA_AUTHORIZING && clc.state < CA_ACTIVE)); } else if (v != UI_API_VERSION) { Com_Error( ERR_DROP, "User Interface is version %d, expected %d", v, UI_API_VERSION ); @@ -1123,7 +1123,7 @@ void CL_InitUI( void ) { } else { // init for this gamestate - VM_Call( uivm, UI_INIT, (cls.state >= CA_AUTHORIZING && cls.state < CA_ACTIVE) ); + VM_Call( uivm, UI_INIT, (clc.state >= CA_AUTHORIZING && clc.state < CA_ACTIVE) ); } } diff --git a/code/client/client.h b/code/client/client.h index ac9f3aa5..53a5bb5b 100644 --- a/code/client/client.h +++ b/code/client/client.h @@ -162,10 +162,13 @@ demo through a file. typedef struct { + connstate_t state; // connection status + int clientNum; int lastPacketSentTime; // for retransmits during connection int lastPacketTime; // for timeouts + char servername[MAX_OSPATH]; // name of server from original connect (used by reconnect) netadr_t serverAddress; int connectTime; // for connection retransmits int connectPacketCount; // for display on connection dialog @@ -301,12 +304,8 @@ typedef struct { } serverInfo_t; typedef struct { - connstate_t state; // connection status - qboolean cddialog; // bring up the cd needed dialog next frame - char servername[MAX_OSPATH]; // name of server from original connect (used by reconnect) - // when the server clears the hunk, all of these must be restarted qboolean rendererStarted; qboolean soundStarted; @@ -333,6 +332,8 @@ typedef struct { serverInfo_t favoriteServers[MAX_OTHER_SERVERS]; int pingUpdateSource; // source currently pinging or updating + + char oldGame[MAX_QPATH]; // update server info netadr_t updateServer; @@ -442,8 +443,6 @@ extern cvar_t *cl_voip; // void CL_Init (void); -void CL_FlushMemory(void); -void CL_ShutdownAll(void); void CL_AddReliableCommand(const char *cmd, qboolean isDisconnectCmd); void CL_StartHunkUsers( qboolean rendererOnly ); @@ -491,7 +490,8 @@ extern kbutton_t in_speed; extern kbutton_t in_voiprecord; #endif -void CL_InitInput (void); +void CL_InitInput(void); +void CL_ShutdownInput(void); void CL_SendCmd (void); void CL_ClearState (void); void CL_ReadPackets (void); @@ -535,7 +535,8 @@ qboolean CL_UpdateVisiblePings_f( int source ); void Con_DrawCharacter (int cx, int line, int num); void Con_CheckResize (void); -void Con_Init (void); +void Con_Init(void); +void Con_Shutdown(void); void Con_Clear_f (void); void Con_ToggleConsole_f (void); void Con_DrawNotify (void); diff --git a/code/null/null_client.c b/code/null/null_client.c index 1e852482..386cf076 100644 --- a/code/null/null_client.c +++ b/code/null/null_client.c @@ -25,7 +25,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA cvar_t *cl_shownet; -void CL_Shutdown( char *finalmsg ) { +void CL_Shutdown(char *finalmsg, qboolean disconnect) +{ } void CL_Init( void ) { @@ -79,16 +80,23 @@ void CL_InitKeyCommands( void ) { void CL_CDDialog( void ) { } -void CL_FlushMemory( void ) { +void CL_FlushMemory(void) +{ +} + +void CL_ShutdownAll(qboolean shutdownRef) +{ } void CL_StartHunkUsers( qboolean rendererOnly ) { } +void CL_InitRef(void) +{ +} + void CL_Snd_Shutdown(void) { } -void CL_ShutdownAll(void) {} - qboolean CL_CDKeyValidate( const char *key, const char *checksum ) { return qtrue; } diff --git a/code/qcommon/common.c b/code/qcommon/common.c index 804f9499..68189a81 100644 --- a/code/qcommon/common.c +++ b/code/qcommon/common.c @@ -338,7 +338,7 @@ void QDECL Com_Error( int code, const char *fmt, ... ) { longjmp (abortframe, -1); } else { VM_Forced_Unload_Start(); - CL_Shutdown (va("Client fatal crashed: %s", com_errorMessage)); + CL_Shutdown (va("Client fatal crashed: %s", com_errorMessage), qtrue); SV_Shutdown (va("Server fatal crashed: %s", com_errorMessage)); VM_Forced_Unload_Done(); } @@ -363,7 +363,7 @@ void Com_Quit_f( void ) { char *p = Cmd_Args( ); if ( !com_errorEntered ) { SV_Shutdown (p[0] ? p : "Server quit"); - CL_Shutdown (p[0] ? p : "Client quit"); + CL_Shutdown (p[0] ? p : "Client quit", qtrue); Com_Shutdown (); FS_Shutdown(qtrue); } @@ -2386,34 +2386,46 @@ Change to a new mod properly with cleaning up cvars before switching. ================== */ -void Com_GameRestart(int checksumFeed, qboolean clientRestart) +void Com_GameRestart(int checksumFeed, qboolean disconnect) { // make sure no recursion can be triggered if(!com_gameRestarting && com_fullyInitialized) { + int clWasRunning = com_cl_running->integer; + com_gameRestarting = qtrue; - if(clientRestart) - { - CL_Disconnect(qfalse); - CL_ShutdownAll(); - } - // Kill server if we have one if(com_sv_running->integer) SV_Shutdown("Game directory changed"); + if(clWasRunning) + { + if(disconnect) + CL_Disconnect(qfalse); + + CL_Shutdown("Game directory changed", disconnect); + } + FS_Restart(checksumFeed); // Clean out any user and VM created cvars Cvar_Restart(qtrue); Com_ExecuteCfg(); - // shut down sound system before restart - CL_Snd_Shutdown(); - - if(clientRestart) + if(disconnect) + { + // We don't want to change any network settings if gamedir + // change was triggered by a connect to server because the + // new network settings might make the connection fail. + NET_Restart_f(); + } + + if(clWasRunning) + { + CL_Init(); CL_StartHunkUsers(qfalse); + } com_gameRestarting = qfalse; } @@ -2761,6 +2773,7 @@ void Com_Init( char *commandLine ) { com_maxfpsMinimized = Cvar_Get( "com_maxfpsMinimized", "0", CVAR_ARCHIVE ); com_abnormalExit = Cvar_Get( "com_abnormalExit", "0", CVAR_ROM ); com_busyWait = Cvar_Get("com_busyWait", "0", CVAR_ARCHIVE); + Cvar_Get("com_errorMessage", "", CVAR_ROM | CVAR_NORESTART); com_introPlayed = Cvar_Get( "com_introplayed", "0", CVAR_ARCHIVE); diff --git a/code/qcommon/files.c b/code/qcommon/files.c index 767a1024..af031422 100644 --- a/code/qcommon/files.c +++ b/code/qcommon/files.c @@ -3875,19 +3875,16 @@ FS_ConditionalRestart restart if necessary ================= */ -qboolean FS_ConditionalRestart(int checksumFeed) +qboolean FS_ConditionalRestart(int checksumFeed, qboolean disconnect) { if(fs_gamedirvar->modified) { - Com_GameRestart(checksumFeed, qfalse); + Com_GameRestart(checksumFeed, disconnect); return qtrue; } else if(checksumFeed != fs_checksumFeed) - { FS_Restart(checksumFeed); - return qtrue; - } return qfalse; } diff --git a/code/qcommon/qcommon.h b/code/qcommon/qcommon.h index 2f1c9172..c80209d3 100644 --- a/code/qcommon/qcommon.h +++ b/code/qcommon/qcommon.h @@ -597,7 +597,7 @@ qboolean FS_Initialized( void ); void FS_InitFilesystem ( void ); void FS_Shutdown( qboolean closemfp ); -qboolean FS_ConditionalRestart( int checksumFeed ); +qboolean FS_ConditionalRestart(int checksumFeed, qboolean disconnect); void FS_Restart( int checksumFeed ); // shutdown and restart the filesystem so changes to fs_gamedir can take effect @@ -813,7 +813,7 @@ void QDECL Com_Printf( const char *fmt, ... ) __attribute__ ((format (printf, void QDECL Com_DPrintf( const char *fmt, ... ) __attribute__ ((format (printf, 1, 2))); void QDECL Com_Error( int code, const char *fmt, ... ) __attribute__ ((format (printf, 2, 3))); void Com_Quit_f( void ); -void Com_GameRestart(int checksumFeed, qboolean clientRestart); +void Com_GameRestart(int checksumFeed, qboolean disconnect); int Com_Milliseconds( void ); // will be journaled properly unsigned Com_BlockChecksum( const void *buffer, int length ); @@ -868,6 +868,7 @@ extern int time_backend; // renderer backend time extern int com_frameTime; extern qboolean com_errorEntered; +extern qboolean com_fullyInitialized; extern fileHandle_t com_journalFile; extern fileHandle_t com_journalDataFile; @@ -957,7 +958,7 @@ void CL_InitKeyCommands( void ); void CL_Init( void ); void CL_Disconnect( qboolean showMainMenu ); -void CL_Shutdown( char *finalmsg ); +void CL_Shutdown(char *finalmsg, qboolean disconnect); void CL_Frame( int msec ); qboolean CL_GameCommand( void ); void CL_KeyEvent (int key, qboolean down, unsigned time); @@ -987,12 +988,15 @@ void CL_ForwardCommandToServer( const char *string ); void CL_CDDialog( void ); // bring up the "need a cd to play" dialog -void CL_ShutdownAll( void ); -// shutdown all the client stuff - void CL_FlushMemory( void ); // dump all memory on an error +void CL_ShutdownAll(qboolean shutdownRef); +// shutdown client + +void CL_InitRef(void); +// initialize renderer interface + void CL_StartHunkUsers( qboolean rendererOnly ); // start all the client stuff using the hunk diff --git a/code/sdl/sdl_input.c b/code/sdl/sdl_input.c index 26b78fa8..e89a9b31 100644 --- a/code/sdl/sdl_input.c +++ b/code/sdl/sdl_input.c @@ -973,7 +973,7 @@ void IN_Frame( void ) IN_ProcessEvents( ); // If not DISCONNECTED (main menu) or ACTIVE (in game), we're loading - loading = !!( cls.state != CA_DISCONNECTED && cls.state != CA_ACTIVE ); + loading = !!( clc.state != CA_DISCONNECTED && clc.state != CA_ACTIVE ); if( !r_fullscreen->integer && ( Key_GetCatcher( ) & KEYCATCH_CONSOLE ) ) { diff --git a/code/server/sv_init.c b/code/server/sv_init.c index 32905015..14f4dac6 100644 --- a/code/server/sv_init.c +++ b/code/server/sv_init.c @@ -417,7 +417,7 @@ void SV_SpawnServer( char *server, qboolean killBots ) { CL_MapLoading(); // make sure all the client stuff is unloaded - CL_ShutdownAll(); + CL_ShutdownAll(qfalse); // clear the whole hunk because we're (re)loading the server Hunk_Clear(); diff --git a/code/sys/sys_main.c b/code/sys/sys_main.c index 7ca851f1..1cced2ac 100644 --- a/code/sys/sys_main.c +++ b/code/sys/sys_main.c @@ -351,7 +351,7 @@ void Sys_Error( const char *error, ... ) Q_vsnprintf (string, sizeof(string), error, argptr); va_end (argptr); - CL_Shutdown( string ); + CL_Shutdown(string, qtrue); Sys_ErrorDialog( string ); Sys_Exit( 3 ); @@ -498,9 +498,9 @@ void Sys_SigHandler( int signal ) { signalcaught = qtrue; #ifndef DEDICATED - CL_Shutdown( va( "Received signal %d", signal ) ); + CL_Shutdown(va("Received signal %d", signal), qtrue); #endif - SV_Shutdown( va( "Received signal %d", signal ) ); + SV_Shutdown(va("Received signal %d", signal) ); } if( signal == SIGTERM || signal == SIGINT )