/* * SV_Demo_Stop */ static void SV_Demo_Stop( bool cancel, bool silent ) { if( !svs.demo.file ) { if( !silent ) { Com_Printf( "No server demo recording in progress\n" ); } return; } if( cancel ) { Com_Printf( "Canceled server demo recording: %s\n", svs.demo.filename ); } else { SNAP_StopDemoRecording( svs.demo.file ); Com_Printf( "Stopped server demo recording: %s\n", svs.demo.filename ); } FS_FCloseFile( svs.demo.file ); svs.demo.file = 0; if( cancel ) { if( !FS_RemoveFile( svs.demo.tempname ) ) Com_Printf( "Error: Failed to delete the temporary server demo file\n" ); } else { // write some meta information about the match/demo SV_SetDemoMetaKeyValue( "hostname", sv.configstrings[CS_HOSTNAME] ); SV_SetDemoMetaKeyValue( "localtime", va( "%u", svs.demo.localtime ) ); SV_SetDemoMetaKeyValue( "multipov", "1" ); SV_SetDemoMetaKeyValue( "duration", va( "%u", (int)ceil( svs.demo.duration/1000.0f ) ) ); SV_SetDemoMetaKeyValue( "mapname", sv.configstrings[CS_MAPNAME] ); SV_SetDemoMetaKeyValue( "gametype", sv.configstrings[CS_GAMETYPENAME] ); SV_SetDemoMetaKeyValue( "levelname", sv.configstrings[CS_MESSAGE] ); SV_SetDemoMetaKeyValue( "matchname", sv.configstrings[CS_MATCHNAME] ); SV_SetDemoMetaKeyValue( "matchscore", sv.configstrings[CS_MATCHSCORE] ); SV_SetDemoMetaKeyValue( "matchuuid", sv.configstrings[CS_MATCHUUID] ); SNAP_WriteDemoMetaData( svs.demo.tempname, svs.demo.meta_data, svs.demo.meta_data_realsize ); if( !FS_MoveFile( svs.demo.tempname, svs.demo.filename ) ) Com_Printf( "Error: Failed to rename the server demo file\n" ); } svs.demo.localtime = 0; svs.demo.basetime = svs.demo.duration = 0; SNAP_FreeClientFrames( &svs.demo.client ); Mem_ZoneFree( svs.demo.filename ); svs.demo.filename = NULL; Mem_ZoneFree( svs.demo.tempname ); svs.demo.tempname = NULL; }
/* * SV_DropClient * * Called when the player is totally leaving the server, either willingly * or unwillingly. This is NOT called if the entire server is quiting * or crashing. */ void SV_DropClient( client_t *drop, int type, const char *format, ... ) { va_list argptr; char *reason; char string[1024]; if( format ) { va_start( argptr, format ); Q_vsnprintfz( string, sizeof( string ), format, argptr ); va_end( argptr ); reason = string; } else { Q_strncpyz( string, "User disconnected", sizeof( string ) ); reason = NULL; } // remove the rating of the client if( drop->edict ) ge->RemoveRating( drop->edict ); // add the disconnect if( drop->edict && ( drop->edict->r.svflags & SVF_FAKECLIENT ) ) { ge->ClientDisconnect( drop->edict, reason ); SV_ClientResetCommandBuffers( drop ); // make sure everything is clean } else { SV_InitClientMessage( drop, &tmpMessage, NULL, 0 ); SV_SendServerCommand( drop, "disconnect %i \"%s\"", type, string ); SV_AddReliableCommandsToMessage( drop, &tmpMessage ); SV_SendMessageToClient( drop, &tmpMessage ); Netchan_PushAllFragments( &drop->netchan ); if( drop->state >= CS_CONNECTED ) { // call the prog function for removing a client // this will remove the body, among other things ge->ClientDisconnect( drop->edict, reason ); } else if( drop->name[0] ) { Com_Printf( "Connecting client %s%s disconnected (%s%s)\n", drop->name, S_COLOR_WHITE, reason, S_COLOR_WHITE ); } } SV_MM_ClientDisconnect( drop ); SNAP_FreeClientFrames( drop ); if( drop->download.name ) { if( drop->download.data ) { FS_FreeBaseFile( drop->download.data ); drop->download.data = NULL; } Mem_ZoneFree( drop->download.name ); drop->download.name = NULL; drop->download.size = 0; drop->download.timeout = 0; } if( drop->individual_socket ) NET_CloseSocket( &drop->socket ); if( drop->mv ) { sv.num_mv_clients--; drop->mv = qfalse; } drop->tvclient = qfalse; drop->state = CS_ZOMBIE; // become free in a few seconds drop->name[0] = 0; }
/* * TV_Downstream_DropClient */ void TV_Downstream_DropClient( client_t *drop, int type, const char *format, ... ) { va_list argptr; char string[1024]; msg_t Message; qbyte MessageData[MAX_MSGLEN]; va_start( argptr, format ); Q_vsnprintfz( string, sizeof( string ), format, argptr ); va_end( argptr ); Com_Printf( "%s" S_COLOR_WHITE " dropped: %s\n", drop->name, string ); TV_Downstream_InitClientMessage( drop, &Message, MessageData, sizeof( MessageData ) ); TV_Downstream_SendServerCommand( drop, "disconnect %i \"%s\"", type, string ); TV_Downstream_AddReliableCommandsToMessage( drop, &Message ); TV_Downstream_SendMessageToClient( drop, &Message ); Netchan_PushAllFragments( &drop->netchan ); if( drop->relay && /*drop->relay->state == CA_ACTIVE && */drop->state >= CS_CONNECTING ) TV_Relay_ClientDisconnect( drop->relay, drop ); // make sure everything is clean TV_Downstream_ClientResetCommandBuffers( drop, qtrue ); SNAP_FreeClientFrames( drop ); if( drop->download.name ) { if( drop->download.data ) { FS_FreeBaseFile( drop->download.data ); drop->download.data = NULL; } Mem_ZoneFree( drop->download.name ); drop->download.name = NULL; drop->download.size = 0; drop->download.timeout = 0; } if( drop->individual_socket ) NET_CloseSocket( &drop->socket ); if( drop->mv ) { tvs.nummvclients--; drop->mv = qfalse; } memset( &drop->flood, 0, sizeof( drop->flood ) ); drop->edict = NULL; drop->relay = NULL; drop->tv = qfalse; drop->state = CS_ZOMBIE; // become free in a few seconds drop->name[0] = 0; }