/* * SV_Demo_WriteSnap */ void SV_Demo_WriteSnap( void ) { int i; msg_t msg; uint8_t msg_buffer[MAX_MSGLEN]; if( !svs.demo.file ) return; for( i = 0; i < sv_maxclients->integer; i++ ) { if( svs.clients[i].state >= CS_SPAWNED && svs.clients[i].edict && !( svs.clients[i].edict->r.svflags & SVF_NOCLIENT ) ) break; } if( i == sv_maxclients->integer ) { // FIXME Com_Printf( "No players left, stopping server side demo recording\n" ); SV_Demo_Stop_f(); return; } MSG_Init( &msg, msg_buffer, sizeof( msg_buffer ) ); SV_BuildClientFrameSnap( &svs.demo.client ); SV_WriteFrameSnapToClient( &svs.demo.client, &msg ); SV_AddReliableCommandsToMessage( &svs.demo.client, &msg ); SV_Demo_WriteMessage( &msg ); svs.demo.duration = svs.gametime - svs.demo.basetime; svs.demo.client.lastframe = sv.framenum; // FIXME: is this needed? }
/* * SV_Map * command from the console or progs. */ void SV_Map( const char *level, qboolean devmap ) { client_t *cl; int i; if( svs.demo.file ) SV_Demo_Stop_f(); // skip the end-of-unit flag if necessary if( level[0] == '*' ) level++; if( sv.state == ss_dead ) SV_InitGame(); // the game is just starting // remove all bots before changing map for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ ) { if( cl->state && cl->edict && ( cl->edict->r.svflags & SVF_FAKECLIENT ) ) { SV_DropClient( cl, DROP_TYPE_GENERAL, NULL ); } } // wsw : Medar : this used to be at SV_SpawnServer, but we need to do it before sending changing // so we don't send frames after sending changing command // leave slots at start for clients only for( i = 0; i < sv_maxclients->integer; i++ ) { // needs to reconnect if( svs.clients[i].state > CS_CONNECTING ) { svs.clients[i].state = CS_CONNECTING; } // limit number of connected multiview clients if( svs.clients[i].mv ) { if( sv.num_mv_clients < sv_maxmvclients->integer ) sv.num_mv_clients++; else svs.clients[i].mv = qfalse; } svs.clients[i].lastframe = -1; memset( svs.clients[i].gameCommands, 0, sizeof( svs.clients[i].gameCommands ) ); } SV_MOTD_Update(); SCR_BeginLoadingPlaque(); // for local system SV_BroadcastCommand( "changing\n" ); SV_SendClientMessages(); SV_SpawnServer( level, devmap ); SV_BroadcastCommand( "reconnect\n" ); }
/* * SV_ShutdownGame * * Called when each game quits */ void SV_ShutdownGame( const char *finalmsg, qboolean reconnect ) { if( !svs.initialized ) return; if( svs.demo.file ) SV_Demo_Stop_f(); if( svs.clients ) SV_FinalMessage( finalmsg, reconnect ); SV_ShutdownGameProgs(); // SV_MM_Shutdown(); NET_CloseSocket( &svs.socket_loopback ); NET_CloseSocket( &svs.socket_udp ); NET_CloseSocket( &svs.socket_udp6 ); #ifdef TCP_ALLOW_CONNECT if( sv_tcp->integer ) NET_CloseSocket( &svs.socket_tcp ); #endif // get any latched variable changes (sv_maxclients, etc) Cvar_GetLatchedVars( CVAR_LATCH ); if( svs.clients ) { Mem_Free( svs.clients ); svs.clients = NULL; } if( svs.client_entities.entities ) { Mem_Free( svs.client_entities.entities ); memset( &svs.client_entities, 0, sizeof( svs.client_entities ) ); } if( svs.cms ) { CM_Free( svs.cms ); svs.cms = NULL; } memset( &sv, 0, sizeof( sv ) ); Com_SetServerState( sv.state ); Com_FreePureList( &svs.purelist ); if( svs.motd ) { Mem_Free( svs.motd ); svs.motd = NULL; } if( sv_mempool ) Mem_EmptyPool( sv_mempool ); memset( &svs, 0, sizeof( svs ) ); svs.initialized = qfalse; }
/* * SV_ShutdownGame * * Called when each game quits */ void SV_ShutdownGame( const char *finalmsg, bool reconnect ) { if( !svs.initialized ) { return; } if( svs.demo.file ) { SV_Demo_Stop_f(); } if( svs.clients ) { SV_FinalMessage( finalmsg, reconnect ); } SV_ShutdownGameProgs(); // SV_MM_Shutdown(); SV_MasterSendQuit(); NET_CloseSocket( &svs.socket_loopback ); NET_CloseSocket( &svs.socket_udp ); NET_CloseSocket( &svs.socket_udp6 ); #ifdef TCP_ALLOW_CONNECT if( sv_tcp->integer ) { NET_CloseSocket( &svs.socket_tcp ); NET_CloseSocket( &svs.socket_tcp6 ); } #endif // get any latched variable changes (sv_maxclients, etc) Cvar_GetLatchedVars( CVAR_LATCH ); if( svs.clients ) { Mem_Free( svs.clients ); svs.clients = NULL; } if( svs.client_entities.entities ) { Mem_Free( svs.client_entities.entities ); memset( &svs.client_entities, 0, sizeof( svs.client_entities ) ); } if( svs.cms ) { // CM_ReleaseReference will take care of freeing up the memory // if there are no other modules referencing the collision model CM_ReleaseReference( svs.cms ); svs.cms = NULL; } Com_SetServerCM( NULL, 0 ); memset( &sv, 0, sizeof( sv ) ); Com_SetServerState( sv.state ); Com_FreePureList( &svs.purelist ); if( svs.motd ) { Mem_Free( svs.motd ); svs.motd = NULL; } if( sv_mempool ) { Mem_EmptyPool( sv_mempool ); } if( svs.wakelock ) { Sys_ReleaseWakeLock( svs.wakelock ); svs.wakelock = NULL; } memset( &svs, 0, sizeof( svs ) ); svs.initialized = false; }