void CL_ReadPackets( void ) { CL_ReadNetMessage(); cl.lerpFrac = CL_LerpPoint(); cl.thirdperson = clgame.dllFuncs.CL_IsThirdPerson(); #if 0 // keep cheat cvars are unchanged if( cl.maxclients > 1 && cls.state == ca_active && host.developer <= 1 ) Cvar_SetCheatState(); #endif // singleplayer never has connection timeout if( NET_IsLocalAddress( cls.netchan.remote_address )) return; // check timeout if( cls.state >= ca_connected && !cls.demoplayback && cls.state != ca_cinematic ) { if( host.realtime - cls.netchan.last_received > cl_timeout->value ) { if( ++cl.timeoutcount > 5 ) // timeoutcount saves debugger { Msg( "\nServer connection timed out.\n" ); CL_Disconnect(); CL_ClearEdicts(); return; } } } else cl.timeoutcount = 0; }
/* ================ Host_EndGame ================ */ void Host_EndGame( const char *message, ... ) { va_list argptr; static char string[MAX_SYSPATH]; va_start( argptr, message ); Q_vsprintf( string, message, argptr ); va_end( argptr ); MsgDev( D_INFO, "Host_EndGame: %s\n", string ); if( SV_Active()) { Q_snprintf( host.finalmsg, sizeof( host.finalmsg ), "Host_EndGame: %s", string ); SV_Shutdown( false ); return; } if( host.type == HOST_DEDICATED ) Sys_Break( "Host_EndGame: %s\n", string ); // dedicated servers exit SV_Shutdown( false ); CL_Disconnect(); // recreate world if needs CL_ClearEdicts (); // release all models Mod_ClearAll( true ); Host_AbortCurrentFrame (); }
/* ================ CL_Drop Called after an Host_Error was thrown ================ */ void CL_Drop( void ) { if( cls.state == ca_uninitialized ) return; CL_Disconnect(); // This fixes crash in menu_playersetup after disconnecting from server CL_ClearEdicts(); }
/* ================= CL_ConnectionlessPacket Responses to broadcasts, etc ================= */ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) { char *args; char *c, buf[MAX_SYSPATH]; int len = sizeof( buf ), i = 0; netadr_t servadr; BF_Clear( msg ); BF_ReadLong( msg ); // skip the -1 args = BF_ReadStringLine( msg ); Cmd_TokenizeString( args ); c = Cmd_Argv( 0 ); MsgDev( D_NOTE, "CL_ConnectionlessPacket: %s : %s\n", NET_AdrToString( from ), c ); // server connection if( !Q_strcmp( c, "client_connect" )) { if( cls.state == ca_connected ) { MsgDev( D_INFO, "Dup connect received. Ignored.\n"); return; } Netchan_Setup( NS_CLIENT, &cls.netchan, from, net_qport->integer); BF_WriteByte( &cls.netchan.message, clc_stringcmd ); BF_WriteString( &cls.netchan.message, "new" ); cls.state = ca_connected; cl.validsequence = 0; // haven't gotten a valid frame update yet cl.delta_sequence = -1; // we'll request a full delta from the baseline cls.lastoutgoingcommand = -1; // we don't have a backed up cmd history yet cls.nextcmdtime = host.realtime; // we can send a cmd right away CL_StartupDemoHeader (); } else if( !Q_strcmp( c, "info" )) { // server responding to a status broadcast CL_ParseStatusMessage( from, msg ); } else if( !Q_strcmp( c, "netinfo" )) { // server responding to a status broadcast CL_ParseNETInfoMessage( from, msg ); } else if( !Q_strcmp( c, "cmd" )) { // remote command from gui front end if( !NET_IsLocalAddress( from )) { Msg( "Command packet from remote host. Ignored.\n" ); return; } #ifdef XASH_SDL SDL_RestoreWindow( host.hWnd ); #endif args = BF_ReadString( msg ); Cbuf_AddText( args ); Cbuf_AddText( "\n" ); } else if( !Q_strcmp( c, "print" )) { // print command from somewhere Msg("remote: %s\n", BF_ReadString( msg ) ); } else if( !Q_strcmp( c, "ping" )) { // ping from somewhere Netchan_OutOfBandPrint( NS_CLIENT, from, "ack" ); } else if( !Q_strcmp( c, "challenge" )) { // challenge from the server we are connecting to cls.challenge = Q_atoi( Cmd_Argv( 1 )); CL_SendConnectPacket(); return; } else if( !Q_strcmp( c, "echo" )) { // echo request from server Netchan_OutOfBandPrint( NS_CLIENT, from, "%s", Cmd_Argv( 1 )); } else if( !Q_strcmp( c, "disconnect" )) { // a disconnect message from the server, which will happen if the server // dropped the connection but it is still getting packets from us CL_Disconnect(); CL_ClearEdicts(); } else if( !Q_strcmp( c, "f") ) { // serverlist got from masterserver while( !msg->bOverflow ) { servadr.type = NA_IP; // 4 bytes for IP BF_ReadBytes( msg, servadr.ip, sizeof( servadr.ip )); // 2 bytes for Port servadr.port = BF_ReadShort( msg ); if( !servadr.port ) break; MsgDev( D_INFO, "Found server: %s\n", NET_AdrToString( servadr )); NET_Config( true ); // allow remote Netchan_OutOfBandPrint( NS_CLIENT, servadr, "info %i", PROTOCOL_VERSION ); } // execute at next frame preventing relation on fps Cbuf_AddText("menu_resetping\n"); } else if( clgame.dllFuncs.pfnConnectionlessPacket( &from, args, buf, &len )) { // user out of band message (must be handled in CL_ConnectionlessPacket) if( len > 0 ) Netchan_OutOfBand( NS_SERVER, from, len, (byte *)buf ); } else MsgDev( D_ERROR, "Bad connectionless packet from %s:\n%s\n", NET_AdrToString( from ), args ); }
/* ================= Host_Error ================= */ void Host_Error( const char *error, ... ) { static char hosterror1[MAX_SYSPATH]; static char hosterror2[MAX_SYSPATH]; static qboolean recursive = false; va_list argptr; if( host.mouse_visible && !CL_IsInMenu( )) { // hide VGUI mouse #ifdef XASH_SDL SDL_ShowCursor( false ); #endif host.mouse_visible = false; } va_start( argptr, error ); Q_vsprintf( hosterror1, error, argptr ); va_end( argptr ); CL_WriteMessageHistory (); // before Q_error call if( host.framecount < 3 ) { Sys_Error( "Host_InitError: %s", hosterror1 ); } else if( host.framecount == host.errorframe ) { Sys_Error( "Host_MultiError: %s", hosterror2 ); return; } else { if( host.developer > 0 ) { UI_SetActiveMenu( false ); Key_SetKeyDest( key_console ); Msg( "^1Host_Error: ^7%s", hosterror1 ); } else MSGBOX2( hosterror1 ); } // host is shutting down. don't invoke infinite loop if( host.state == HOST_SHUTDOWN ) return; if( recursive ) { Msg( "Host_RecursiveError: %s", hosterror2 ); Sys_Error( hosterror1 ); return; // don't multiple executes } recursive = true; Q_strncpy( hosterror2, hosterror1, MAX_SYSPATH ); host.errorframe = host.framecount; // to avoid multple calls per frame Q_sprintf( host.finalmsg, "Server crashed: %s", hosterror1 ); // clear cmd buffer to prevent execution of any commands Cbuf_Clear(); SV_Shutdown( false ); CL_Drop(); // drop clients // recreate world if required CL_ClearEdicts (); // release all models Mod_ClearAll( false ); recursive = false; Host_AbortCurrentFrame(); }