/* ================ SV_Shutdown Called when each game quits, before Sys_Quit or Sys_Error ================ */ void SV_Shutdown( char *finalmsg ) { if ( !com_sv_running || !com_sv_running->integer ) { return; } Com_Printf( "----- Server Shutdown -----\n" ); if ( svs.clients && !com_errorEntered ) { SV_FinalMessage( finalmsg ); } SV_RemoveOperatorCommands(); SV_MasterShutdown(); SV_ShutdownGameProgs(); // free current level SV_ClearServer(); // free server static data if ( svs.clients ) { //Z_Free( svs.clients ); free( svs.clients ); // RF, avoid trying to allocate large chunk on a fragmented zone } memset( &svs, 0, sizeof( svs ) ); Cvar_Set( "sv_running", "0" ); Com_Printf( "---------------------------\n" ); // disconnect any local clients CL_Disconnect( qfalse ); }
static void testVisFlags (void) { const char *mapName = "test_game"; if (FS_CheckFile("maps/%s.bsp", mapName) != -1) { edict_t *ent; int num; /* the other tests didn't call the server shutdown function to clean up */ OBJZERO(*sv); SV_Map(true, mapName, NULL); num = 0; ent = NULL; while ((ent = G_EdictsGetNextLivingActorOfTeam(ent, TEAM_ALIEN))) { const teammask_t teamMask = G_TeamToVisMask(ent->team); const bool visible = ent->visflags & teamMask; char *visFlagsBuf = Mem_StrDup(Com_UnsignedIntToBinary(ent->visflags)); char *teamMaskBuf = Mem_StrDup(Com_UnsignedIntToBinary(teamMask)); CU_ASSERT_EQUAL(ent->team, TEAM_ALIEN); UFO_CU_ASSERT_TRUE_MSG(visible, va("visflags: %s, teamMask: %s", visFlagsBuf, teamMaskBuf)); Mem_Free(visFlagsBuf); Mem_Free(teamMaskBuf); num++; } SV_ShutdownGameProgs(); CU_ASSERT_TRUE(num > 0); } else { UFO_CU_FAIL_MSG(va("Map resource '%s.bsp' for test is missing.", mapName)); } }
/* ================ SV_Shutdown Called when each game quits, before Sys_Quit or Sys_Error ================ */ void SV_Shutdown( char *finalmsg ) { if ( !com_sv_running || !com_sv_running->integer ) return; Com_Printf( "----- Server Shutdown -----\n" ); if( theSVS.svClients_.size() && !com_errorEntered ) { SV_FinalMessage( finalmsg ); } //SV_RemoveOperatorCommands(); //SV_MasterShutdown(); SV_ShutdownGameProgs(); // free current level SV_ClearServer(); // free server static data // if( theSVS.clients_ ) // Z_Free( theSVS.clients_ ); // theSVS.clearClients();// done in theSVS.clear() /// Com_Memset( &svs, 0, sizeof( svs ) ); theSVS.clear(); Cvar_Set( "sv_running", "0" ); Cvar_Set("ui_singlePlayerActive", "0"); Com_Printf( "---------------------------\n" ); // disconnect any local clients CL_Disconnect( false ); }
static void testSpawnAndConnect (void) { char userinfo[MAX_INFO_STRING]; player_t *player; const char *name = "name"; bool day = true; byte *buf; /* this entity string may not contain any inline models, we don't have the bsp tree loaded here */ const int size = FS_LoadFile("game/entity.txt", &buf); edict_t *e = NULL; int cnt = 0; CU_ASSERT_NOT_EQUAL_FATAL(size, -1); CU_ASSERT_FATAL(size > 0); SV_InitGameProgs(); /* otherwise we can't link the entities */ SV_ClearWorld(); player = G_PlayerGetNextHuman(0); svs.ge->SpawnEntities(name, day, (const char *)buf); CU_ASSERT_TRUE(svs.ge->ClientConnect(player, userinfo, sizeof(userinfo))); CU_ASSERT_FALSE(svs.ge->RunFrame()); while ((e = G_EdictsGetNextInUse(e))) { Com_Printf("entity %i: %s\n", cnt, e->classname); cnt++; } CU_ASSERT_EQUAL(cnt, 45); SV_ShutdownGameProgs(); FS_FreeFile(buf); }
/* * ================ * SV_Shutdown * * Called when each game quits, * before Sys_Quit or Sys_Error * ================ */ void SV_Shutdown(char *finalmsg, qboolean reconnect) { if (svs.clients) { SV_FinalMessage(finalmsg, reconnect); } Master_Shutdown(); SV_ShutdownGameProgs(); // free current level if (sv.demofile) { FS_FCloseFile(sv.demofile); } memset(&sv, 0, sizeof(sv)); Com_SetServerState(sv.state); // free server static data if (svs.clients) { Z_Free(svs.clients); } if (svs.client_entities) { Z_Free(svs.client_entities); } if (svs.demofile) { fclose(svs.demofile); } memset(&svs, 0, sizeof(svs)); }
void Hunk_Clear( void ) { #ifndef DEDICATED CL_ShutdownCGame(); CL_ShutdownUI(); #endif SV_ShutdownGameProgs(); #ifndef DEDICATED CIN_CloseAllVideos(); #endif hunk_tag = TAG_HUNK_MARK1; Z_TagFree(TAG_HUNK_MARK1); Z_TagFree(TAG_HUNK_MARK2); if ( re.HunkClearCrap ) { re.HunkClearCrap(); } // Com_Printf( "Hunk_Clear: reset the hunk ok\n" ); VM_Clear(); //See if any ghoul2 stuff was leaked, at this point it should be all cleaned up. #ifdef _FULL_G2_LEAK_CHECKING assert(g_Ghoul2Allocations == 0 && g_G2ClientAlloc == 0 && g_G2ServerAlloc == 0); if (g_Ghoul2Allocations) { Com_Printf("%i bytes leaked by ghoul2 routines (%i client, %i server)\n", g_Ghoul2Allocations, g_G2ClientAlloc, g_G2ServerAlloc); G2_DEBUG_ReportLeaks(); } #endif }
/* ================ SV_Shutdown Called when each game quits, before Sys_Quit or Sys_Error ================ */ void SV_Shutdown( char *finalmsg ) { if ( !com_sv_running || !com_sv_running->integer ) { return; } Com_Printf( "----- Server Shutdown -----\n" ); if ( svs.clients && !com_errorEntered ) { SV_FinalMessage( finalmsg ); } SV_RemoveOperatorCommands(); SV_MasterShutdown(); SV_ShutdownGameProgs(); // free current level SV_ClearServer(); // free server static data if ( svs.clients ) { Z_Free( svs.clients ); } Com_Memset( &svs, 0, sizeof( svs ) ); Cvar_Set( "sv_running", "0" ); Cvar_Set("ui_singlePlayerActive", "0"); Com_Printf( "---------------------------\n" ); // disconnect any local clients CL_Disconnect( qfalse ); }
/* ================ SV_Shutdown Called when each game quits, before Sys_Quit or Sys_Error ================ */ void SV_Shutdown( char *finalmsg ) { if ( !com_sv_running || !com_sv_running->integer ) { return; } Com_Printf( "----- Server Shutdown (%s) -----\n", finalmsg ); NET_LeaveMulticast6(); if ( svs.clients && !com_errorEntered ) { SV_FinalMessage( finalmsg ); } SV_RemoveOperatorCommands(); SV_MasterShutdown(); SV_ShutdownGameProgs(); #ifdef DEDICATED Com_ShutdownRef(); #endif MSG_ShutdownNetFields(); // free current level SV_ClearServer(); // free server static data if(svs.players) { int index; for(index = 0; index < sv_maxclients->integer; index++) SV_FreePlayer(&svs.players[index]); Z_Free(svs.players); } if(svs.clients) { int index; for(index = 0; index < sv_maxclients->integer; index++) SV_FreeClient(&svs.clients[index]); Z_Free(svs.clients); } Com_Memset( &svs, 0, sizeof( svs ) ); Cvar_Set( "sv_running", "0" ); Cvar_Set("ui_singlePlayerActive", "0"); Cvar_Set("sv_public", "0"); Com_Printf( "---------------------------\n" ); // disconnect any local clients if( sv_killserver->integer != 2 ) CL_Disconnect( qfalse ); }
/* ================ SV_Shutdown Called when each game quits, before Sys_Quit or Sys_Error ================ */ void SV_Shutdown( char *finalmsg ) { if ( !com_sv_running || !com_sv_running->integer ) { return; } Com_Printf( "----- Server Shutdown -----\n" ); if ( svs.clients && !com_errorEntered ) { SV_FinalMessage( finalmsg ); } SV_RemoveOperatorCommands(); SV_MasterShutdown(); SV_ShutdownGameProgs(); /* Ghoul2 Insert Start */ // de allocate the snapshot entities if (svs.snapshotEntities) { delete[] svs.snapshotEntities; svs.snapshotEntities = NULL; } #ifdef G2_COLLISION_ENABLED if ( com_dedicated->integer && G2VertSpaceServer) { delete G2VertSpaceServer; G2VertSpaceServer = 0; } #endif // free current level SV_ClearServer(); // free server static data if ( svs.clients ) { Z_Free( svs.clients ); } Com_Memset( &svs, 0, sizeof( svs ) ); Cvar_Set( "sv_running", "0" ); Cvar_Set("ui_singlePlayerActive", "0"); Com_Printf( "---------------------------\n" ); // disconnect any local clients CL_Disconnect( qfalse ); // shutdown webserver if (mgsrv) { SV_MV_Websrv_Shutdown(); } }
/** * @brief Called when each game quits, before Sys_Quit or Sys_Error */ void SV_Shutdown(char *finalmsg) { // close attack log SV_CloseAttackLog(); if (!com_sv_running || !com_sv_running->integer) { return; } Com_Printf("----- Server Shutdown -----\n"); if (svs.clients && !com_errorEntered) { SV_FinalCommand(va("print \"%s\"", finalmsg), qtrue); } SV_RemoveOperatorCommands(); SV_MasterShutdown(); SV_ShutdownGameProgs(); // stop any demos if (sv.demoState == DS_RECORDING) { SV_DemoStopRecord(); } else if (sv.demoState == DS_PLAYBACK) { SV_DemoStopPlayback(); } // free current level SV_ClearServer(); // free server static data if (svs.clients) { //Z_Free( svs.clients ); free(svs.clients); // avoid trying to allocate large chunk on a fragmented zone } memset(&svs, 0, sizeof(svs)); svs.serverLoad = -1; Cvar_Set("sv_running", "0"); Com_Printf("---------------------------\n"); // disconnect any local clients CL_Disconnect(qfalse); #ifdef FEATURE_TRACKER Tracker_ServerStop(); #endif }
/** * @brief Called when each game quits, before Sys_Quit or Sys_Error */ void SV_Shutdown(char *finalmsg) { // close attack log SV_CloseAttackLog(); if (!com_sv_running || !com_sv_running->integer) { return; } Com_Printf("----- Server Shutdown -----\n"); if (svs.clients && !com_errorEntered) { SV_FinalCommand(va("print \"%s\"", finalmsg), qtrue); } SV_RemoveOperatorCommands(); SV_MasterShutdown(); SV_ShutdownGameProgs(); SV_DemoStopAll(); // free current level SV_ClearServer(); // free server static data if (svs.clients) { int index; for (index = 0; index < sv_maxclients->integer; index++) { SV_Netchan_ClearQueue(&svs.clients[index]); } //Z_Free( svs.clients ); free(svs.clients); // avoid trying to allocate large chunk on a fragmented zone } memset(&svs, 0, sizeof(svs)); svs.serverLoad = -1; Cvar_Set("sv_running", "0"); Com_Printf("---------------------------\n"); // disconnect any local clients CL_Disconnect(qfalse); #ifdef FEATURE_TRACKER Tracker_ServerStop(); #endif }
/* ================ SV_Shutdown Called when each game quits, before Sys_Quit or Sys_Error ================ */ void SV_Shutdown( const char *finalmsg ) { if ( !com_sv_running || !com_sv_running->integer ) { return; } PrintBanner(_( "Server Shutdown" )) NET_LeaveMulticast6(); if ( svs.clients && !com_errorEntered ) { SV_FinalCommand( va( "print %s", Cmd_QuoteString( finalmsg ) ), qtrue ); } SV_RemoveOperatorCommands(); SV_MasterShutdown(); SV_ShutdownGameProgs(); // free current level SV_ClearServer(); // free server static data if ( svs.clients ) { int index; for ( index = 0; index < sv_maxclients->integer; index++ ) { SV_FreeClient( &svs.clients[ index ] ); } //Z_Free( svs.clients ); free( svs.clients ); // RF, avoid trying to allocate large chunk on a fragmented zone } memset( &svs, 0, sizeof( svs ) ); svs.serverLoad = -1; Cvar_Set( "sv_running", "0" ); #ifndef DEDICATED NET_Config( qtrue ); #endif Com_Printf( "---------------------------\n" ); // disconnect any local clients CL_Disconnect( qfalse ); }
/* ================ SV_Shutdown Called when each game quits, before Sys_Quit or Sys_Error ================ */ void SV_Shutdown( const char *finalmsg ) { if ( !com_sv_running || !com_sv_running->integer ) { return; } PrintBanner( "Server Shutdown" ) NET_LeaveMulticast6(); if ( svs.clients ) { SV_FinalCommand( va( "print %s", Cmd_QuoteString( finalmsg ) ), true ); } SV_RemoveOperatorCommands(); SV_MasterShutdown(); SV_ShutdownGameProgs(); // free current level SV_ClearServer(); // free server static data if ( svs.clients ) { int index; for ( index = 0; index < sv_maxclients->integer; index++ ) { SV_FreeClient( &svs.clients[ index ] ); } free( svs.clients ); } memset( &svs, 0, sizeof( svs ) ); svs.serverLoad = -1; Cvar_Set( "sv_running", "0" ); #ifndef BUILD_SERVER NET_Config( true ); #endif Com_Printf( "---------------------------\n" ); // disconnect any local clients CL_Disconnect( false ); }
static void testShooting (void) { const char *mapName = "test_game"; if (FS_CheckFile("maps/%s.bsp", mapName) != -1) { /* the other tests didn't call the server shutdown function to clean up */ OBJZERO(*sv); SV_Map(true, mapName, NULL); /** @todo equip the soldier */ /** @todo set the input variables -- gi.ReadFormat(format, &pos, &i, &firemode, &from); */ /** @todo do the shot -- G_ClientShoot(player, ent, pos, i, firemode, &mock, true, from); */ /** @todo implement the test here - e.g. extend shot_mock_t */ SV_ShutdownGameProgs(); } else { UFO_CU_FAIL_MSG(va("Map resource '%s.bsp' for test is missing.", mapName)); } }
/* ================ SV_Shutdown Called when each game quits, before Sys_Quit or Sys_Error ================ */ void SV_Shutdown( char *finalmsg ) { if ( !com_sv_running || !com_sv_running->integer ) { return; } Com_Printf( "----- Server Shutdown (%s) -----\n", finalmsg ); NET_LeaveMulticast6(); if ( svs.clients && !com_errorEntered ) { SV_FinalMessage( finalmsg ); } SV_RemoveOperatorCommands(); SV_MasterShutdown(); SV_ShutdownGameProgs(); // free current level SV_ClearServer(); // free siege static data since this is cross level or shutdown, not map restart if(svs.siege) { Z_Free(svs.siege); } // free server static data if(svs.clients) { int index; for(index = 0; index < sv_maxclients->integer; index++) SV_FreeClient(&svs.clients[index]); Z_Free(svs.clients); } Com_Memset( &svs, 0, sizeof( svs ) ); Cvar_Set( "sv_running", "0" ); Cvar_Set("ui_singlePlayerActive", "0"); Com_Printf( "---------------------------\n" ); // disconnect any local clients if( sv_killserver->integer != 2 ) CL_Disconnect( qfalse ); }
/* ================ SV_Shutdown Called when each game quits, before Sys_Quit or Sys_Error ================ */ void SV_Shutdown( char *finalmsg ) { if ( !com_sv_running || !com_sv_running->integer ) { return; } // Com_Printf( "----- Server Shutdown -----\n" ); if ( svs.clients && !com_errorEntered ) { SV_FinalMessage( finalmsg ); } SV_RemoveOperatorCommands(); SV_MasterShutdown(); SV_ShutdownGameProgs(); svs.gameStarted = qfalse; /* Ghoul2 Insert Start */ // de allocate the snapshot entities if (svs.snapshotEntities) { delete[] svs.snapshotEntities; svs.snapshotEntities = NULL; } // free current level SV_ClearServer(); CM_ClearMap();//jfm: add a clear here since it's commented out in clearServer. This prevents crashing cmShaderTable on exit. // free server static data if ( svs.clients ) { Z_Free( svs.clients ); } Com_Memset( &svs, 0, sizeof( svs ) ); Cvar_Set( "sv_running", "0" ); Cvar_Set("ui_singlePlayerActive", "0"); // Com_Printf( "---------------------------\n" ); // disconnect any local clients if( sv_killserver->integer != 2 ) CL_Disconnect( qfalse ); }
/* ================ SV_Shutdown Called when each game quits, before Sys_Quit or Sys_Error ================ */ void SV_Shutdown( char *finalmsg ) { int i; if ( !com_sv_running || !com_sv_running->integer ) { return; } //Com_Printf( "----- Server Shutdown -----\n" ); if ( svs.clients && !com_errorEntered ) { SV_FinalMessage( finalmsg ); } SV_RemoveOperatorCommands(); SV_ShutdownGameProgs(qfalse); if (svs.snapshotEntities) { Z_Free(svs.snapshotEntities); svs.snapshotEntities = NULL; } for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) { if ( sv.configstrings[i] ) { Z_Free( sv.configstrings[i] ); } } // free current level memset( &sv, 0, sizeof( sv ) ); // free server static data if ( svs.clients ) { SV_FreeClient(svs.clients); Z_Free( svs.clients ); } memset( &svs, 0, sizeof( svs ) ); // Ensure we free any memory used by the leaf cache. CM_CleanLeafCache(); Cvar_Set( "sv_running", "0" ); //Com_Printf( "---------------------------\n" ); }
static void testInventoryTempContainerLinks (void) { const char *mapName = "test_game"; if (FS_CheckFile("maps/%s.bsp", mapName) != -1) { edict_t *ent; int nr; containerIndex_t container; const invList_t *ic; /* the other tests didn't call the server shutdown function to clean up */ OBJZERO(*sv); SV_Map(true, mapName, NULL); level.activeTeam = TEAM_ALIEN; /* first alien that should die and drop its inventory */ ent = G_EdictsGetNextLivingActorOfTeam(NULL, TEAM_ALIEN); nr = 0; for (container = 0; container < CID_MAX; container++) { if (container == CID_ARMOUR || container == CID_FLOOR) continue; for (ic = ent->getContainer(container); ic; ic = ic->getNext()) nr++; } CU_ASSERT_TRUE(nr > 0); CU_ASSERT_PTR_NULL(ent->getFloor()); G_InventoryToFloor(ent); CU_ASSERT_PTR_NOT_NULL(ent->getFloor()); CU_ASSERT_PTR_EQUAL(G_GetFloorItemFromPos(ent->pos)->getFloor(), ent->getFloor()); nr = 0; for (container = 0; container < CID_MAX; container++) { if (container == CID_ARMOUR || container == CID_FLOOR) continue; for (ic = ent->getContainer(container); ic; ic = ic->getNext()) nr++; } CU_ASSERT_EQUAL(nr, 0); SV_ShutdownGameProgs(); } else { UFO_CU_FAIL_MSG(va("Map resource '%s.bsp' for test is missing.", mapName)); } }
/** * @brief Called when each game quits, before Sys_Quit or Sys_Error * @param[in] finalmsg The message all clients get as server shutdown message * @param[in] reconnect True if this is only a restart (new map or map restart), * false if the server shutdown completely and you also want to disconnect all clients */ void SV_Shutdown (const char *finalmsg, qboolean reconnect) { unsigned int i; if (!svs.initialized) return; if (svs.clients) SV_FinalMessage(finalmsg, reconnect); Com_Printf("Shutdown server: %s\n", finalmsg); Master_Shutdown(); SV_ShutdownGameProgs(); NET_DatagramSocketClose(svs.netDatagramSocket); SV_Stop(); for (i = 0; i < sv->numSVModels; i++) { sv_model_t *model = &sv->svModels[i]; if (model->name) Mem_Free(model->name); } /* free current level */ OBJZERO(*sv); /* free server static data */ if (svs.clients) Mem_Free(svs.clients); if (svs.serverMutex != NULL) TH_MutexDestroy(svs.serverMutex); OBJZERO(svs); /* maybe we shut down before we init - e.g. in case of an error */ if (sv_maxclients) sv_maxclients->flags &= ~CVAR_LATCH; if (sv_mapname) sv_mapname->flags &= ~CVAR_NOSET; }
/* ================ SV_Shutdown Called when each game quits, before Sys_Quit or Sys_Error ================ */ void SV_Shutdown( char *finalmsg ) { if ( !com_sv_running || !com_sv_running->integer ) { return; } Com_Printf( "----- Server Shutdown (%s) -----\n", finalmsg ); // stop server-side demos (if any) Cbuf_ExecuteText(EXEC_NOW, "stopserverdemo all"); if ( svs.clients && !com_errorEntered ) { SV_FinalMessage( finalmsg ); } SV_RemoveOperatorCommands(); SV_MasterShutdown(); SV_ShutdownGameProgs(); // free current level SV_ClearServer(); #ifdef USE_SQLITE_BANS #ifdef DEDICATED SV_BansShutdown(); #endif #endif // free server static data if ( svs.clients ) { Z_Free( svs.clients ); } Com_Memset( &svs, 0, sizeof( svs ) ); Cvar_Set( "sv_running", "0" ); Cvar_Set("ui_singlePlayerActive", "0"); Com_Printf( "---------------------------\n" ); // disconnect any local clients if( sv_killserver->integer != 2 ) CL_Disconnect( qfalse ); }
// Called when each game quits, before Sys_Quit or Sys_Error void SV_Shutdown( const char *finalmsg ) { if ( !com_sv_running || !com_sv_running->integer ) { return; } Com_Printf( "----- Server Shutdown (%s) -----\n", finalmsg ); NET_LeaveMulticast6(); if ( svs.clients && !com_errorEntered ) { SV_FinalMessage( finalmsg ); } SV_RemoveOperatorCommands(); SV_MasterShutdown(); SV_ShutdownGameProgs(); svs.gameStarted = qfalse; // free current level SV_ClearServer(); // free server static data if(svs.clients) { int index; for(index = 0; index < sv_maxclients->integer; index++) SV_FreeClient(&svs.clients[index]); Z_Free(svs.clients); } memset( &svs, 0, sizeof( svs ) ); Cvar_Set( "sv_running", "0" ); Com_Printf( "---------------------------\n" ); // disconnect any local clients if( sv_killserver->integer != 2 ) CL_Disconnect( qfalse, "Server shutdown" ); }
/* ================ SV_Shutdown Called when each game quits, before Sys_Quit or Sys_Error ================ */ void SV_Shutdown( char *finalmsg ) { if ( !com_sv_running || !com_sv_running->integer ) { return; } Com_Printf( "----- Server Shutdown (%s) -----\n", finalmsg ); NET_LeaveMulticast6(); if ( svs.clients && !com_errorEntered ) { SV_FinalMessage( finalmsg ); } SV_MasterShutdown(); SV_ShutdownGameProgs(); // stop any demos if (sv.demoState == DS_RECORDING) SV_DemoStopRecord(); if (sv.demoState == DS_PLAYBACK) SV_DemoStopPlayback(); // free current level SV_ClearServer(); // free server static data if ( svs.clients ) { Z_Free( svs.clients ); } Com_Memset( &svs, 0, sizeof( svs ) ); Cvar_Set( "sv_running", "0" ); Cvar_Set("ui_singlePlayerActive", "0"); Com_Printf( "---------------------------\n" ); // disconnect any local clients if( sv_killserver->integer != 2 ) CL_Disconnect( qfalse ); }
/* ================ SV_Shutdown Called when each game quits, before Sys_Quit or Sys_Error ================ */ void SV_Shutdown( char *finalmsg ) { if ( !com_sv_running || !com_sv_running->integer ) { return; } Com_Printf( "----- Server Shutdown -----\n" ); if ( svs.clients && !com_errorEntered ) { SV_FinalMessage( finalmsg ); } SV_RemoveOperatorCommands(); SV_ShutdownGameProgs(); if (svs.snapshotEntities) { Z_Free(svs.snapshotEntities); svs.snapshotEntities = NULL; } // remove allocated space for ghoul2 game side model transforms delete G2VertSpaceServer; G2VertSpaceServer = NULL; // free current level memset( &sv, 0, sizeof( sv ) ); // free server static data if ( svs.clients ) { Z_Free( svs.clients ); } memset( &svs, 0, sizeof( svs ) ); // Ensure we free any memory used by the leaf cache. CM_CleanLeafCache(); Cvar_Set( "sv_running", "0" ); Com_Printf( "---------------------------\n" ); }
static void testDoorTrigger (void) { const char *mapName = "test_game"; if (FS_CheckFile("maps/%s.bsp", mapName) != -1) { edict_t *e = NULL; int cnt = 0; int doors = 0; /* the other tests didn't call the server shutdown function to clean up */ OBJZERO(*sv); SV_Map(true, mapName, NULL); while ((e = G_EdictsGetNextInUse(e))) { cnt++; if (e->type == ET_DOOR) { if (Q_streq(e->targetname, "left-0")) { /* this one is triggered by an actor standing inside of a trigger_touch */ CU_ASSERT_TRUE(e->doorState); } else if (Q_streq(e->targetname, "right-0")) { /* this one has a trigger_touch, too - but nobody is touching that trigger yet */ CU_ASSERT_FALSE(e->doorState); } else { /* both of the used doors have a targetname set */ CU_ASSERT(false); } doors++; } } SV_ShutdownGameProgs(); CU_ASSERT_TRUE(cnt > 0); CU_ASSERT_TRUE(doors == 2); } else { UFO_CU_FAIL_MSG(va("Map resource '%s.bsp' for test is missing.", mapName)); } }
/* ================ SV_SpawnServer Change the server to a new map, taking all connected clients along with it. This is NOT called for map_restart ================ */ void SV_SpawnServer( char *server, qboolean killBots ) { int i; int checksum; qboolean isBot; char systemInfo[16384]; const char *p; // shut down the existing game if it is running SV_ShutdownGameProgs(); Com_Printf ("------ Server Initialization ------\n"); Com_Printf ("Server: %s\n",server); // if not running a dedicated server CL_MapLoading will connect the client to the server // also print some status stuff CL_MapLoading(); // make sure all the client stuff is unloaded CL_ShutdownAll(); // clear the whole hunk because we're (re)loading the server Hunk_Clear(); // clear collision map data CM_ClearMap(); // init client structures and svs.numSnapshotEntities if ( !Cvar_VariableValue("sv_running") ) { SV_Startup(); } else { // check for maxclients change if ( sv_maxclients->modified ) { SV_ChangeMaxClients(); } } // clear pak references FS_ClearPakReferences(0); // allocate the snapshot entities on the hunk svs.snapshotEntities = Hunk_Alloc( sizeof(entityState_t)*svs.numSnapshotEntities, h_high ); svs.nextSnapshotEntities = 0; // toggle the server bit so clients can detect that a // server has changed svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT; // set nextmap to the same map, but it may be overriden // by the game startup or another console command Cvar_Set( "nextmap", "map_restart 0"); // Cvar_Set( "nextmap", va("map %s", server) ); // wipe the entire per-level structure SV_ClearServer(); for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) { sv.configstrings[i] = CopyString(""); } // make sure we are not paused Cvar_Set("cl_paused", "0"); // get a new checksum feed and restart the file system srand(Com_Milliseconds()); sv.checksumFeed = ( ((int) rand() << 16) ^ rand() ) ^ Com_Milliseconds(); FS_Restart( sv.checksumFeed ); CM_LoadMap( va("maps/%s.bsp", server), qfalse, &checksum ); // set serverinfo visible name Cvar_Set( "mapname", server ); Cvar_Set( "sv_mapChecksum", va("%i",checksum) ); // serverid should be different each time sv.serverId = com_frameTime; sv.restartedServerId = sv.serverId; // I suppose the init here is just to be safe sv.checksumFeedServerId = sv.serverId; Cvar_Set( "sv_serverid", va("%i", sv.serverId ) ); // clear physics interaction links SV_ClearWorld (); // media configstring setting should be done during // the loading stage, so connected clients don't have // to load during actual gameplay sv.state = SS_LOADING; // load and spawn all other entities SV_InitGameProgs(); // don't allow a map_restart if game is modified sv_gametype->modified = qfalse; // run a few frames to allow everything to settle for ( i = 0 ; i < 3 ; i++ ) { VM_Call( gvm, GAME_RUN_FRAME, svs.time ); SV_BotFrame( svs.time ); svs.time += 100; } // create a baseline for more efficient communications SV_CreateBaseline (); for (i=0 ; i<sv_maxclients->integer ; i++) { // send the new gamestate to all connected clients if (svs.clients[i].state >= CS_CONNECTED) { char *denied; if ( svs.clients[i].netchan.remoteAddress.type == NA_BOT ) { if ( killBots ) { SV_DropClient( &svs.clients[i], "" ); continue; } isBot = qtrue; } else { isBot = qfalse; } // connect the client again denied = VM_ExplicitArgPtr( gvm, VM_Call( gvm, GAME_CLIENT_CONNECT, i, qfalse, isBot ) ); // firstTime = qfalse if ( denied ) { // this generally shouldn't happen, because the client // was connected before the level change SV_DropClient( &svs.clients[i], denied ); } else { if( !isBot ) { // when we get the next packet from a connected client, // the new gamestate will be sent svs.clients[i].state = CS_CONNECTED; } else { client_t *client; sharedEntity_t *ent; client = &svs.clients[i]; client->state = CS_ACTIVE; ent = SV_GentityNum( i ); ent->s.number = i; client->gentity = ent; client->deltaMessage = -1; client->nextSnapshotTime = svs.time; // generate a snapshot immediately VM_Call( gvm, GAME_CLIENT_BEGIN, i ); } } } } // run another frame to allow things to look at all the players VM_Call( gvm, GAME_RUN_FRAME, svs.time ); SV_BotFrame( svs.time ); svs.time += 100; if ( sv_pure->integer ) { // the server sends these to the clients so they will only // load pk3s also loaded at the server p = FS_LoadedPakChecksums(); Cvar_Set( "sv_paks", p ); if (strlen(p) == 0) { Com_Printf( "WARNING: sv_pure set but no PK3 files loaded\n" ); } p = FS_LoadedPakNames(); Cvar_Set( "sv_pakNames", p ); // if a dedicated pure server we need to touch the cgame because it could be in a // seperate pk3 file and the client will need to load the latest cgame.qvm if ( com_dedicated->integer ) { SV_TouchCGame(); } } else { Cvar_Set( "sv_paks", "" ); Cvar_Set( "sv_pakNames", "" ); } // the server sends these to the clients so they can figure // out which pk3s should be auto-downloaded p = FS_ReferencedPakChecksums(); Cvar_Set( "sv_referencedPaks", p ); p = FS_ReferencedPakNames(); Cvar_Set( "sv_referencedPakNames", p ); // save systeminfo and serverinfo strings Q_strncpyz( systemInfo, Cvar_InfoString_Big( CVAR_SYSTEMINFO ), sizeof( systemInfo ) ); cvar_modifiedFlags &= ~CVAR_SYSTEMINFO; SV_SetConfigstring( CS_SYSTEMINFO, systemInfo ); SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) ); cvar_modifiedFlags &= ~CVAR_SERVERINFO; // any media configstring setting now should issue a warning // and any configstring changes should be reliably transmitted // to all clients sv.state = SS_GAME; // send a heartbeat now so the master will get up to date info SV_Heartbeat_f(); Hunk_SetMark(); Com_Printf ("-----------------------------------\n"); }
static void testMoveEntities (void) { pos3_t pos; vec3_t vec; pathing_t* path = Mem_AllocType(pathing_t); forbiddenList_t forbiddenList; const byte crouchingState = 0; const int maxTUs = MAX_ROUTE_TUS; forbiddenList.reset(); SV_Map(true, mapName, nullptr); /* starting point */ VectorSet(vec, 240, -144, 32); VecToPos(vec, pos); G_CompleteRecalcRouting(); { Edict* ent = nullptr; while ((ent = G_EdictsGetNextInUse(ent))) { /* Dead 2x2 unit will stop walking, too. */ if (ent->type == ET_SOLID) { int j; for (j = 0; j < ent->forbiddenListSize; j++) { forbiddenList.add(ent->forbiddenListPos[j], (byte*) &ent->fieldSize); } } } } { int lengthStored; pos3_t to; Grid_CalcPathing(sv->mapData.routing, ACTOR_SIZE_NORMAL, path, pos, maxTUs, &forbiddenList); Grid_MoveStore(path); /* walk onto the func_breakable */ { VectorSet(vec, 112, -144, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, 4 * TU_MOVE_STRAIGHT); } /* walk over the func_breakable */ { VectorSet(vec, 80, -144, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, 5 * TU_MOVE_STRAIGHT); } /* walk over the func_breakable */ { VectorSet(vec, 16, -144, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, 7 * TU_MOVE_STRAIGHT); } } /* starting point */ VectorSet(vec, 144, 144, 32); VecToPos(vec, pos); { int lengthStored; pos3_t to; Grid_CalcPathing(sv->mapData.routing, ACTOR_SIZE_NORMAL, path, pos, maxTUs, &forbiddenList); Grid_MoveStore(path); /* walk through the opened door */ { VectorSet(vec, 112, 144, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, TU_MOVE_STRAIGHT); } /* walk around the opened door */ { VectorSet(vec, 144, 208, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, 2 * TU_MOVE_STRAIGHT + TU_MOVE_DIAGONAL); } } SV_ShutdownGameProgs(); }
/* ================ SV_SpawnServer Change the server to a new map, taking all connected clients along with it. This is NOT called for map_restart ================ */ void SV_SpawnServer( char *server, qboolean killBots ) { int i; int checksum; qboolean isBot; const char *p; // shut down the existing game if it is running SV_ShutdownGameProgs(); Com_Printf( "------ Server Initialization ------\n" ); Com_Printf( "Server: %s\n", server ); // if not running a dedicated server CL_MapLoading will connect the client to the server // also print some status stuff CL_MapLoading(); // make sure all the client stuff is unloaded CL_ShutdownAll(); // clear the whole hunk because we're (re)loading the server Hunk_Clear(); // clear collision map data // (SA) NOTE: TODO: used in missionpack CM_ClearMap(); // wipe the entire per-level structure SV_ClearServer(); // MrE: main zone should be pretty much emtpy at this point // except for file system data and cached renderer data Z_LogHeap(); // allocate empty config strings for ( i = 0; i < MAX_CONFIGSTRINGS; i++ ) { sv.configstrings[ i ] = CopyString( "" ); sv.configstringsmodified[ i ] = qfalse; } // init client structures and svs.numSnapshotEntities if ( !Cvar_VariableValue( "sv_running" ) ) { SV_Startup(); } else { // check for maxclients change if ( sv_maxclients->modified ) { SV_ChangeMaxClients(); } #ifdef USE_HUB_SERVER // if sv_owHubHost was changed, resolve the address again if ( sv_owHubHost->modified ) { sv_owHubHost->modified = qfalse; SV_ResolveowHubHost(); } #endif } // clear pak references FS_ClearPakReferences( 0 ); // allocate the snapshot entities on the hunk svs.snapshotEntities = Hunk_Alloc( sizeof( entityState_t ) * svs.numSnapshotEntities, h_high ); svs.nextSnapshotEntities = 0; // toggle the server bit so clients can detect that a // server has changed svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT; // set nextmap to the same map, but it may be overriden // by the game startup or another console command Cvar_Set( "nextmap", "map_restart 0" ); // Cvar_Set( "nextmap", va("map %s", server) ); // Ridah // DHM - Nerve :: We want to use the completion bar in multiplayer as well // Arnout: just always use it // if( !SV_GameIsSinglePlayer() ) { SV_SetExpectedHunkUsage( va( "maps/%s.bsp", server ) ); // } else { // just set it to a negative number,so the cgame knows not to draw the percent bar // Cvar_Set( "com_expectedhunkusage", "-1" ); // } // make sure we are not paused Cvar_Set( "cl_paused", "0" ); #if !defined( DO_LIGHT_DEDICATED ) // get a new checksum feed and restart the file system srand( Sys_Milliseconds() ); sv.checksumFeed = ( ( ( int ) rand() << 16 ) ^ rand() ) ^ Sys_Milliseconds(); // DO_LIGHT_DEDICATED // only comment out when you need a new pure checksum string and it's associated random feed //Com_DPrintf("SV_SpawnServer checksum feed: %p\n", sv.checksumFeed); #else // DO_LIGHT_DEDICATED implementation below // we are not able to randomize the checksum feed since the feed is used as key for pure_checksum computations // files.c 1776 : pack->pure_checksum = Com_BlockChecksumKey( fs_headerLongs, 4 * fs_numHeaderLongs, LittleLong(fs_checksumFeed) ); // we request a fake randomized feed, files.c knows the answer srand( Sys_Milliseconds() ); sv.checksumFeed = FS_RandChecksumFeed(); #endif FS_Restart( sv.checksumFeed ); CM_LoadMap( va( "maps/%s.bsp", server ), qfalse, &checksum ); // set serverinfo visible name Cvar_Set( "mapname", server ); Cvar_Set( "sv_mapChecksum", va( "%i", checksum ) ); sv_newGameShlib = Cvar_Get( "sv_newGameShlib", "", CVAR_TEMP ); // serverid should be different each time sv.serverId = com_frameTime; sv.restartedServerId = sv.serverId; sv.checksumFeedServerId = sv.serverId; Cvar_Set( "sv_serverid", va( "%i", sv.serverId ) ); // clear physics interaction links SV_ClearWorld(); // media configstring setting should be done during // the loading stage, so connected clients don't have // to load during actual gameplay sv.state = SS_LOADING; Cvar_Set( "sv_serverRestarting", "1" ); // load and spawn all other entities SV_InitGameProgs(); // don't allow a map_restart if game is modified // Arnout: there isn't any check done against this, obsolete // sv_gametype->modified = qfalse; // run a few frames to allow everything to settle for ( i = 0; i < GAME_INIT_FRAMES; i++ ) { VM_Call( gvm, GAME_RUN_FRAME, svs.time ); SV_BotFrame( svs.time ); svs.time += FRAMETIME; } // create a baseline for more efficient communications SV_CreateBaseline(); for ( i = 0; i < sv_maxclients->integer; i++ ) { // send the new gamestate to all connected clients if ( svs.clients[ i ].state >= CS_CONNECTED ) { char *denied; if ( svs.clients[ i ].netchan.remoteAddress.type == NA_BOT ) { if ( killBots || SV_GameIsSinglePlayer() || SV_GameIsCoop() ) { SV_DropClient( &svs.clients[ i ], "" ); continue; } isBot = qtrue; } else { isBot = qfalse; } // connect the client again denied = VM_ExplicitArgPtr( gvm, VM_Call( gvm, GAME_CLIENT_CONNECT, i, qfalse, isBot ) ); // firstTime = qfalse if ( denied ) { // this generally shouldn't happen, because the client // was connected before the level change SV_DropClient( &svs.clients[ i ], denied ); } else { if ( !isBot ) { // when we get the next packet from a connected client, // the new gamestate will be sent svs.clients[ i ].state = CS_CONNECTED; } else { client_t *client; sharedEntity_t *ent; client = &svs.clients[ i ]; client->state = CS_ACTIVE; ent = SV_GentityNum( i ); ent->s.number = i; client->gentity = ent; client->deltaMessage = -1; client->nextSnapshotTime = svs.time; // generate a snapshot immediately VM_Call( gvm, GAME_CLIENT_BEGIN, i ); } } } } // run another frame to allow things to look at all the players VM_Call( gvm, GAME_RUN_FRAME, svs.time ); SV_BotFrame( svs.time ); svs.time += FRAMETIME; if ( sv_pure->integer ) { // the server sends these to the clients so they will only // load pk3s also loaded at the server p = FS_LoadedPakChecksums(); Cvar_Set( "sv_paks", p ); if ( strlen( p ) == 0 ) { Com_Printf( "WARNING: sv_pure set but no PK3 files loaded\n" ); } p = FS_LoadedPakNames(); Cvar_Set( "sv_pakNames", p ); // if a dedicated pure server we need to touch the cgame because it could be in a // seperate pk3 file and the client will need to load the latest cgame.qvm if ( com_dedicated->integer ) { SV_TouchCGame(); } } else { Cvar_Set( "sv_paks", "" ); Cvar_Set( "sv_pakNames", "" ); } // the server sends these to the clients so they can figure // out which pk3s should be auto-downloaded // NOTE: we consider the referencedPaks as 'required for operation' // we want the server to reference the mp_bin pk3 that the client is expected to load from SV_TouchCGameDLL(); p = FS_ReferencedPakChecksums(); Cvar_Set( "sv_referencedPaks", p ); p = FS_ReferencedPakNames(); Cvar_Set( "sv_referencedPakNames", p ); // save systeminfo and serverinfo strings cvar_modifiedFlags &= ~CVAR_SYSTEMINFO; SV_SetConfigstring( CS_SYSTEMINFO, Cvar_InfoString_Big( CVAR_SYSTEMINFO ) ); SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO | CVAR_SERVERINFO_NOUPDATE ) ); cvar_modifiedFlags &= ~CVAR_SERVERINFO; // any media configstring setting now should issue a warning // and any configstring changes should be reliably transmitted // to all clients sv.state = SS_GAME; // send a heartbeat now so the master will get up to date info SV_Heartbeat_f(); Hunk_SetMark(); SV_UpdateConfigStrings(); Cvar_Set( "sv_serverRestarting", "0" ); Com_Printf( "-----------------------------------\n" ); }
void TearDown() { SV_ShutdownGameProgs(); }
void GameTest::testCountSpawnpointsForMapInSingleplayerMode(bool verbose, const mapDef_t *md, const char *asmName, const char *aircraft, const char *ufo) { if (verbose) { std::cout << "[ ] adding test parameter: gamemode singleplayer" << std::endl; Com_Printf("CountSpawnpoints - adding test parameter: gamemode singleplayer\n"); } /* Set initial values. */ /* load singleplayer map */ Cvar_Set("sv_maxclients", "1"); /* It seems, because of reaction-fire limitations we cannot spawn more than 128 actors total. */ Cvar_Set("sv_maxsoldiersperteam", "12"); Cvar_Set("ai_singleplayeraliens", "64"); Cvar_Set("ai_numcivilians", "16"); Com_Printf("CountSpawnpoints - loading map: mode singleplayer mapdef %s map %s assembly %s dropship %s ufo %s\n", md->id, md->mapTheme, asmName, aircraft, ufo); long time = Sys_Milliseconds(); try { SV_Map(true, md->mapTheme, asmName, true); } catch (comDrop_t&) { ADD_FAILURE() << "Error: Failed to load assembly " << asmName << " from mapdef " << md->id << ", map " << md->mapTheme << " aircraft: " << aircraft << ", ufo: " << ufo << " => singleplayer mode."; Com_Printf("CountSpawnpoints - error: Failed to load map.\n"); SV_ShutdownGameProgs(); return; } time = Sys_Milliseconds() - time; Com_Printf("CountSpawnpoints - result: %li ms\n", time); mapCount++; /* This is the max number of aliens the UFO can bring to the battlefield. */ const int numteamUFO = testCountSpawnpointsGetNumteamValueForUFO(ufo); /* The number of human spawnpoints required on the map depends on the 'numteam' value of the used dropship, if any. */ const int minHumans = testCountSpawnpointsGetNumteamValueForAircraft(aircraft); /* The number of spawnpoints for 2x2 units required on the map depends on the number of UGVs the aircraft can transport. */ const int minHuman2x2 = testCountSpawnpointsGetNum2x2ValueForAircraft(aircraft); /* How many aliens do we need to have on the map, at least? The mapdef defines the map to support up to 'maxaliens' aliens, so the map should have at least this number of spawnpoints available. However, this number must not be higher than the 'numteam' value of the used UFO, if any. */ const int minAliens = std::min(md->maxAliens, numteamUFO); /* Count the spawnpoints available on the map. */ const int spawnCivs = static_cast<int>(level.num_spawnpoints[TEAM_CIVILIAN]); const int spawnHumans = static_cast<int>(level.num_spawnpoints[TEAM_PHALANX]); const int spawnAliens = static_cast<int>(level.num_spawnpoints[TEAM_ALIEN]); const int spawnHuman2x2 = static_cast<int>(level.num_2x2spawnpoints[TEAM_PHALANX]); /* Make gtest report back in case there are not enough human spawnpoints. */ EXPECT_GE(spawnHumans, minHumans) << "Error: Assembly " << asmName << " in mapdef " << md->id << " from map " << md->mapTheme << " in singleplayer mode (aircraft: " << aircraft << " ufo: " << ufo << "): Only " << spawnHumans << " human spawnpoints but " << minHumans << " expected."; /* Make gtest report back in case there are not enough alien spawnpoints. */ EXPECT_GE(spawnAliens, minAliens) << "Error: Assembly " << asmName << " in mapdef " << md->id << " from map " << md->mapTheme << " in singleplayer mode (aircraft: " << aircraft << " ufo: " << ufo << "): Only " << spawnAliens << " alien spawnpoints but " << minAliens << " expected."; /* Make gtest report back in case there are not enough human 2x2 spawnpoints. */ EXPECT_GE(spawnHuman2x2, minHuman2x2) << "Error: Assembly " << asmName << " in mapdef " << md->id << " from map " << md->mapTheme << " in singleplayer mode (aircraft: " << aircraft << " ufo: " << ufo << "): Only " << spawnHuman2x2 << " human 2x2 spawnpoints but " << minHuman2x2 << " expected."; /* Make gtest report back if the number of aliens allowed on the map is smaller than the crew number of the used UFO, if any. */ if (ufo) EXPECT_GE(md->maxAliens, numteamUFO) << "Error: Assembly " << asmName << " in mapdef " << md->id << " from map " << md->mapTheme << " in singleplayer mode (aircraft: " << aircraft << " ufo: " << ufo << "): The number of aliens allowed on the map is smaller than expected."; /* Print report to log. */ Com_Printf("CountSpawnpoints - map: mode singleplayer\n"); Com_Printf("CountSpawnpoints - map: mapdef %s\n", md->id); Com_Printf("CountSpawnpoints - map: map %s\n", md->mapTheme); Com_Printf("CountSpawnpoints - map: assembly %s\n", asmName); Com_Printf("CountSpawnpoints - map: aircraft %s \n", aircraft); Com_Printf("CountSpawnpoints - map: ufo %s\n", ufo); Com_Printf("CountSpawnpoints - count spawnpoints: civilian %i\n", spawnCivs); Com_Printf("CountSpawnpoints - count spawnpoints: singleplayer needs/found %i/%i\n", minHumans, spawnHumans); Com_Printf("CountSpawnpoints - count spawnpoints: singleplayer_2x2 needs/found %i/%i\n", minHuman2x2, spawnHuman2x2); Com_Printf("CountSpawnpoints - count spawnpoints: alien needs/found %i/%i\n", minAliens, spawnAliens); if (spawnHumans < minHumans) Com_Printf("CountSpawnpoints - error: missing spawnpoints - singleplayer needs/found %i/%i\n", minHumans, spawnHumans); if (spawnHuman2x2 < minHuman2x2) Com_Printf("CountSpawnpoints - error: missing spawnpoints - singleplayer_2x2 needs/found %i/%i\n", minHuman2x2, spawnHuman2x2); if (spawnAliens < minAliens) Com_Printf("CountSpawnpoints - error: missing spawnpoints - alien needs/found %i/%i\n", minAliens, spawnAliens); if (ufo) { if (md->maxAliens < numteamUFO) { Com_Printf("CountSpawnpoints - error: mapdef parameter - maxaliens needs/found %i/%i\n", numteamUFO, md->maxAliens); } } SV_ShutdownGameProgs(); }
void GameTest::testCountSpawnpointsForMapInMultiplayerMode(bool verbose, const mapDef_t *md, const char *asmName, const char *aircraft, const char *ufo) { if (verbose) { std::cout << "[ ] adding test parameter: gamemode multiplayer" << std::endl; Com_Printf("CountSpawnpoints - adding test parameter: gamemode multiplayer\n"); } if (LIST_IsEmpty(md->gameTypes)) { ADD_FAILURE() << "Error: Multiplayer enabled, but no gametypes defined in mapdef " << md->id; Com_Printf("CountSpawnpoints - error: Multiplayer enabled, but no gametypes defined in mapdef.\n"); return; } if (md->teams < 1) { ADD_FAILURE() << "Error: Multiplayer enabled, but number of teams is " << md->teams; Com_Printf("CountSpawnpoints - error: Multiplayer enabled, but number of teams is %i.\n", md->teams); return; } /* Set initial values. */ /* Load map in multiplayer mode. */ Cvar_Set("sv_maxclients", DOUBLEQUOTE(MAX_CLIENTS)); /* It seems, because of reaction-fire limitations we cannot spawn more than 128 actors total. */ Cvar_Set("sv_maxsoldiersperteam", "12"); Cvar_Set("ai_multiplayeraliens", "64"); Cvar_Set("ai_numcivilians", "16"); Com_Printf("CountSpawnpoints - loading map: mode multiplayer mapdef %s map %s assembly %s dropship %s ufo %s\n", md->id, md->mapTheme, asmName, aircraft, ufo); long time = Sys_Milliseconds(); try { SV_Map(true, md->mapTheme, asmName, true); } catch (comDrop_t&) { ADD_FAILURE() << "Error: Failed to load assembly " << asmName << " from mapdef " << md->id << ", map " << md->mapTheme << " aircraft: " << aircraft << ", ufo: " << ufo << " => multiplayer mode."; Com_Printf("CountSpawnpoints - error: Multiplayer enabled, but no gametypes defined in mapdef.\n"); Com_Printf("CountSpawnpoints - error: Failed to load map.\n"); SV_ShutdownGameProgs(); return; } time = Sys_Milliseconds() - time; Com_Printf("CountSpawnpoints - result: %li ms\n", time); SV_ShutdownGameProgs(); mapCount++; /* Print report to log. */ Com_Printf("CountSpawnpoints - map: mode multiplayer\n"); Com_Printf("CountSpawnpoints - map: mapdef %s\n", md->id); Com_Printf("CountSpawnpoints - map: map %s\n", md->mapTheme); Com_Printf("CountSpawnpoints - map: assembly %s\n", asmName); Com_Printf("CountSpawnpoints - map: aircraft %s \n", aircraft); Com_Printf("CountSpawnpoints - map: ufo %s\n", ufo); /* Check if one of the gametypes available in the mapdef defines a coop mode, in which case we will need aliens on the map. */ int coop = 0; /* The number of alien spawnpoints required on the map. In PvP gamemodes this is zero, while in coop games we check for the number given as 'maxaliens' in the mapdef. */ int minAliens = 0; /* The number of player spawnpoints required for each team is determined by the value of sv_maxsoldiersperteam given in the gametype def. */ int minMP = 0; /* Count spawnpoints for TEAM_CIVILIAN. */ const int spawnCivs = static_cast<int>(level.num_spawnpoints[TEAM_CIVILIAN]); Com_Printf("CountSpawnpoints - count spawnpoints: civilian %i\n", spawnCivs); /* Find the highest numbers for alien and player spawnpoints needed in the map. */ LIST_Foreach(md->gameTypes, const char, gameType) { for (int i = 0; i < csi.numGTs; i++) { const gametype_t* gt = &csi.gts[i]; if (!Q_streq(gt->id, gameType)) continue; const cvarlist_t* list = gt->cvars; for (int j = 0; j < gt->num_cvars; j++, list++) { if (Q_streq(list->name, "ai_multiplayeraliens")) { coop = std::max(coop, atoi(list->value)); } else if (Q_streq(list->name, "sv_maxsoldiersperteam")) { minMP = std::max(minMP, atoi(list->value)); } } } } /* If the mapdef does not define a coop mode, we do not need aliens. */ if (coop) minAliens = std::min(md->maxAliens, testCountSpawnpointsGetNumteamValueForUFO(ufo)); const int startTeam = TEAM_CIVILIAN + 1; /* For every single mp team defined in the mapdef - check if there are enough spawnpoints available. */ for (int currTeamNum = startTeam; currTeamNum < startTeam + md->teams; ++currTeamNum) { if (currTeamNum > TEAM_MAX_HUMAN) { ADD_FAILURE() << "Error: Mapdef " << md->id << " has too many teams set."; Com_Printf("CountSpawnpoints - error: Too many teams set.\n"); break; } const int spawnTeam = static_cast<int>(level.num_spawnpoints[currTeamNum]); /* Make gtest report back in case there are not enough spawnpoints available for the team. */ EXPECT_GE(spawnTeam, minMP) << "Error: Assembly " << asmName << " from mapdef " << md->id << ", map " << md->mapTheme << "(aircraft: " << aircraft << ", ufo: " << ufo << ") in multiplayer mode: Only " << spawnTeam << " spawnpoints for team " << currTeamNum << " but " << minMP << " expected."; /* Log the result. */ Com_Printf("CountSpawnpoints - count spawnpoints: player team/needs/found %i/%i/%i\n", currTeamNum, minMP, spawnTeam); if (spawnTeam < minMP) Com_Printf("CountSpawnpoints - error: missing spawnpoints - player team/needs/found %i/%i/%i\n", currTeamNum, minMP, spawnTeam); } if (minAliens) { const int spawnAliens = static_cast<int>(level.num_spawnpoints[TEAM_ALIEN]); /* Make gtest report back in case there are not enough alien spawnpoints available. */ EXPECT_GE(spawnAliens, minAliens) << "Assembly " << asmName << " from mapdef " << md->id << ", map " << md->mapTheme << "(aircraft: " << aircraft << ", ufo: " << ufo << ") in multiplayer mode defines at least one coop game mode," << " but does not have enough alien spawn positions for that. We expect at least " << minAliens << " spawn positions for aliens, the map provides " << spawnAliens << "."; /* Log the result. */ Com_Printf("CountSpawnpoints - count spawnpoints: alien needs/found %i/%i\n", minAliens, spawnAliens); if (spawnAliens < minAliens) Com_Printf("CountSpawnpoints - error: missing spawnpoints - alien needs/found %i/%i\n", minAliens, spawnAliens); } SV_ShutdownGameProgs(); }