UFO: Alien Invasion
Loading...
Searching...
No Matches
test_game.cpp
Go to the documentation of this file.
1
5
6/*
7Copyright (C) 2002-2025 UFO: Alien Invasion.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24*/
25
26#include "test_shared.h"
27#include "../shared/ufotypes.h"
28#include "../game/g_local.h"
29#include "../game/g_actor.h"
30#include "../game/g_client.h"
31#include "../game/g_edicts.h"
32#include "../game/g_inventory.h"
33#include "../game/g_move.h"
34#include "../server/server.h"
36
37static int mapCount = 0;
38
39class GameTest: public ::testing::Test {
40protected:
41 static void SetUpTestCase() {
42 TEST_Init();
43 /* we need the teamdefs for spawning ai actors */
44 Com_ParseScripts(true);
45 Cvar_Set("sv_threads", "0");
46 sv_maxclients = Cvar_Get("sv_maxclients", "1", CVAR_SERVERINFO, "Max. connected clients for test");
48 masterserver_url = Cvar_Get("masterserver_url", MASTER_SERVER, CVAR_ARCHIVE, "URL of UFO:AI masterserver");
49
50 sv_genericPool = Mem_CreatePool("server-gametest");
51 com_networkPool = Mem_CreatePool("server-gametest-network");
52 r_state.active_texunit = &r_state.texunits[0];
53 }
54
55 static void TearDownTestCase() {
57 }
58
59 void testCountSpawnpointsForMap(bool verbose, const mapDef_t *md);
60 void testCountSpawnpointsForMapWithAssembly(bool verbose, const mapDef_t *md, const char *asmName);
61 void testCountSpawnpointsForMapWithAssemblyAndAircraft(bool verbose, const mapDef_t *md, const char *asmName, const char *aircraft);
62 void testCountSpawnpointsForMapWithAssemblyAndAircraftAndUfo(bool verbose, const mapDef_t *md, const char *asmName, const char *aircraft, const char *ufo);
63 void testCountSpawnpointsForMapInSingleplayerMode(bool verbose, const mapDef_t *md, const char *asmName, const char *aircraft, const char *ufo);
64 void testCountSpawnpointsForMapInMultiplayerMode(bool verbose, const mapDef_t *md, const char *asmName, const char *aircraft, const char *ufo);
65 int testCountSpawnpointsGetNumteamValueForAircraft(const char *aircraft);
67 int testCountSpawnpointsGetNum2x2ValueForAircraft(const char *aircraft);
68
69 void SetUp() {
70 OBJZERO(*sv);
71 }
72
73 void TearDown() {
75 }
76};
77
78TEST_F(GameTest, SpawnAndConnect)
79{
80 char userinfo[MAX_INFO_STRING];
81 player_t* player;
82 const char* name = "name";
83 bool day = true;
84 byte* buf;
85 /* this entity string may not contain any inline models, we don't have the bsp tree loaded here */
86 const int size = FS_LoadFile("game/entity.txt", &buf);
87 Edict* e = nullptr;
88 int cnt = 0;
89
90 ASSERT_NE(size, -1) << "could not load game/entity.txt.";
91 ASSERT_TRUE(size > 0) << "game/entity.txt is empty.";
92
94 /* otherwise we can't link the entities */
96
97 player = G_PlayerGetNextHuman(0);
98 svs.ge->SpawnEntities(name, day, (const char*)buf);
99 ASSERT_TRUE(svs.ge->ClientConnect(player, userinfo, sizeof(userinfo))) << "Failed to connect the client";
100 ASSERT_FALSE(svs.ge->RunFrame()) << "Failed to run the server logic frame tick";
101
102 while ((e = G_EdictsGetNextInUse(e))) {
103 Com_Printf("entity %i: %s\n", cnt, e->classname);
104 cnt++;
105 }
106
107 ASSERT_EQ(cnt, 43);
108
110}
111
113{
114 /* Right now, 2x2 units are not yet implemented. But if we start to, it will probably
115 be humans bringing UGVs into battle. So we should make sure there are at least some
116 2x2 spawnpoints for TEAM_HUMAN on each map.
117 The values are arbitrary, as they are not defined within the scripts yet. */
118
119 if (Q_strnull(aircraft)) {
120 /* Could be any, so we return the max supported number. */
121 return 3;
122 } else if (Q_streq(aircraft, "craft_drop_firebird")) {
123 return 3;
124 } else if (Q_streq(aircraft, "craft_drop_raptor")) {
125 return 3;
126 } else if (Q_streq(aircraft, "craft_drop_herakles")) {
127 return 3;
128 } else {
129 ADD_FAILURE() << "Error: Mapdef defines unknown aircraft: " << aircraft;
130 return 0;
131 }
132}
133
135{
136 // TODO: somehow fix these magic values here
137 if (Q_strnull(aircraft)) {
138 /* Could be any, so we return the max supported number. */
139 return 12;
140 } else if (Q_streq(aircraft, "craft_drop_firebird")) {
141 return 8;
142 } else if (Q_streq(aircraft, "craft_drop_raptor")) {
143 return 10;
144 } else if (Q_streq(aircraft, "craft_drop_herakles")) {
145 return 12;
146 } else {
147 ADD_FAILURE() << "Error: Mapdef defines unknown aircraft: " << aircraft;
148 return 0;
149 }
150}
151
153{
154 // TODO: somehow fix these magic values here
155 if (Q_strnull(ufo)) {
156 /* Could be any, or none (ground based mission), so we return the max supported number. */
157 return 30;
158 } else if (Q_streq(ufo, "craft_ufo_scout") || Q_streq(ufo, "craft_crash_scout")) {
159 return 4;
160 } else if (Q_streq(ufo, "craft_ufo_fighter") || Q_streq(ufo, "craft_crash_fighter")) {
161 return 6;
162 } else if (Q_streq(ufo, "craft_ufo_harvester") || Q_streq(ufo, "craft_crash_harvester")) {
163 return 8;
164 } else if (Q_streq(ufo, "craft_ufo_corrupter") || Q_streq(ufo, "craft_crash_corrupter")) {
165 return 10;
166 } else if (Q_streq(ufo, "craft_ufo_supply") || Q_streq(ufo, "craft_crash_supply")) {
167 return 12;
168 } else if (Q_streq(ufo, "craft_ufo_gunboat") || Q_streq(ufo, "craft_crash_gunboat")) {
169 return 12;
170 } else if (Q_streq(ufo, "craft_ufo_bomber") || Q_streq(ufo, "craft_crash_bomber")) {
171 return 18;
172 } else if (Q_streq(ufo, "craft_ufo_ripper") || Q_streq(ufo, "craft_crash_ripper")) {
173 return 14;
174 } else {
175 ADD_FAILURE() << "Error: Mapdef defines unknown UFO: " << ufo;
176 return 0;
177 }
178}
179
180void GameTest::testCountSpawnpointsForMapInMultiplayerMode(bool verbose, const mapDef_t *md, const char *asmName, const char *aircraft, const char *ufo)
181{
182 if (verbose) {
183 std::cout << "[ ] adding test parameter: gamemode multiplayer" << std::endl;
184 Com_Printf("CountSpawnpoints - adding test parameter: gamemode multiplayer\n");
185 }
186
187 if (LIST_IsEmpty(md->gameTypes)) {
188 ADD_FAILURE() << "Error: Multiplayer enabled, but no gametypes defined in mapdef " << md->id;
189 Com_Printf("CountSpawnpoints - error: Multiplayer enabled, but no gametypes defined in mapdef.\n");
190 return;
191 }
192
193 if (md->teams < 1) {
194 ADD_FAILURE() << "Error: Multiplayer enabled, but number of teams is " << md->teams;
195 Com_Printf("CountSpawnpoints - error: Multiplayer enabled, but number of teams is %i.\n", md->teams);
196 return;
197 }
198
199 /* Set initial values. */
200 /* Load map in multiplayer mode. */
201 Cvar_Set("sv_maxclients", DOUBLEQUOTE(MAX_CLIENTS));
202 /* It seems, because of reaction-fire limitations we cannot spawn more than 128 actors total. */
203 Cvar_Set("sv_maxsoldiersperteam", "12");
204 Cvar_Set("ai_multiplayeraliens", "64");
205 Cvar_Set("ai_numcivilians", "16");
206
207 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);
208 long time = Sys_Milliseconds();
209
210 try {
211 SV_Map(true, md->mapTheme, asmName, true);
212 } catch (comDrop_t&) {
213 ADD_FAILURE() << "Error: Failed to load assembly " << asmName << " from mapdef " << md->id << ", map "
214 << md->mapTheme << " aircraft: " << aircraft << ", ufo: " << ufo << " => multiplayer mode.";
215 Com_Printf("CountSpawnpoints - error: Multiplayer enabled, but no gametypes defined in mapdef.\n");
216 Com_Printf("CountSpawnpoints - error: Failed to load map.\n");
218 return;
219 }
220
221 time = Sys_Milliseconds() - time;
222 Com_Printf("CountSpawnpoints - result: %li ms\n", time);
224 mapCount++;
225
226 /* Print report to log. */
227 Com_Printf("CountSpawnpoints - map: mode multiplayer\n");
228 Com_Printf("CountSpawnpoints - map: mapdef %s\n", md->id);
229 Com_Printf("CountSpawnpoints - map: map %s\n", md->mapTheme);
230 Com_Printf("CountSpawnpoints - map: assembly %s\n", asmName);
231 Com_Printf("CountSpawnpoints - map: aircraft %s \n", aircraft);
232 Com_Printf("CountSpawnpoints - map: ufo %s\n", ufo);
233
234 /* Check if one of the gametypes available in the mapdef defines a coop mode,
235 in which case we will need aliens on the map. */
236 int coop = 0;
237 /* The number of alien spawnpoints required on the map. In PvP gamemodes this is zero,
238 while in coop games we check for the number given as 'maxaliens' in the mapdef. */
239 int minAliens = 0;
240 /* The number of player spawnpoints required for each team is determined
241 by the value of sv_maxsoldiersperteam given in the gametype def. */
242 int minMP = 0;
243
244 /* Count spawnpoints for TEAM_CIVILIAN. */
245 const int spawnCivs = static_cast<int>(level.num_spawnpoints[TEAM_CIVILIAN]);
246 Com_Printf("CountSpawnpoints - count spawnpoints: civilian %i\n", spawnCivs);
247
248 /* Find the highest numbers for alien and player spawnpoints needed in the map. */
249 LIST_Foreach(md->gameTypes, const char, gameType) {
250 for (int i = 0; i < csi.numGTs; i++) {
251 const gametype_t* gt = &csi.gts[i];
252 if (!Q_streq(gt->id, gameType))
253 continue;
254 const cvarlist_t* list = gt->cvars;
255 for (int j = 0; j < gt->num_cvars; j++, list++) {
256 if (Q_streq(list->name, "ai_multiplayeraliens")) {
257 coop = std::max(coop, atoi(list->value));
258 } else if (Q_streq(list->name, "sv_maxsoldiersperteam")) {
259 minMP = std::max(minMP, atoi(list->value));
260 }
261 }
262 }
263 }
264
265 /* If the mapdef does not define a coop mode, we do not need aliens. */
266 if (coop)
267 minAliens = std::min(md->maxAliens, testCountSpawnpointsGetNumteamValueForUFO(ufo));
268
269 const int startTeam = TEAM_CIVILIAN + 1;
270 /* For every single mp team defined in the mapdef - check if there are enough spawnpoints available. */
271 for (int currTeamNum = startTeam; currTeamNum < startTeam + md->teams; ++currTeamNum) {
272 if (currTeamNum > TEAM_MAX_HUMAN) {
273 ADD_FAILURE() << "Error: Mapdef " << md->id << " has too many teams set.";
274 Com_Printf("CountSpawnpoints - error: Too many teams set.\n");
275 break;
276 }
277 const int spawnTeam = static_cast<int>(level.num_spawnpoints[currTeamNum]);
278 /* Make gtest report back in case there are not enough spawnpoints available for the team. */
279 EXPECT_GE(spawnTeam, minMP) << "Error: Assembly " << asmName << " from mapdef " << md->id << ", map " << md->mapTheme
280 << "(aircraft: " << aircraft << ", ufo: " << ufo << ") in multiplayer mode: Only " << spawnTeam
281 << " spawnpoints for team " << currTeamNum << " but " << minMP << " expected.";
282 /* Log the result. */
283 Com_Printf("CountSpawnpoints - count spawnpoints: player team/needs/found %i/%i/%i\n", currTeamNum, minMP, spawnTeam);
284 if (spawnTeam < minMP)
285 Com_Printf("CountSpawnpoints - error: missing spawnpoints - player team/needs/found %i/%i/%i\n", currTeamNum, minMP, spawnTeam);
286
287 }
288 if (minAliens) {
289 const int spawnAliens = static_cast<int>(level.num_spawnpoints[TEAM_ALIEN]);
290 /* Make gtest report back in case there are not enough alien spawnpoints available. */
291 EXPECT_GE(spawnAliens, minAliens) << "Assembly " << asmName << " from mapdef " << md->id << ", map " << md->mapTheme
292 << "(aircraft: " << aircraft << ", ufo: " << ufo << ") in multiplayer mode defines at least one coop game mode,"
293 << " but does not have enough alien spawn positions for that. We expect at least " << minAliens
294 << " spawn positions for aliens, the map provides " << spawnAliens << ".";
295 /* Log the result. */
296 Com_Printf("CountSpawnpoints - count spawnpoints: alien needs/found %i/%i\n", minAliens, spawnAliens);
297 if (spawnAliens < minAliens)
298 Com_Printf("CountSpawnpoints - error: missing spawnpoints - alien needs/found %i/%i\n", minAliens, spawnAliens);
299 }
300
302}
303
304void GameTest::testCountSpawnpointsForMapInSingleplayerMode(bool verbose, const mapDef_t *md, const char *asmName, const char *aircraft, const char *ufo)
305{
306 if (verbose) {
307 std::cout << "[ ] adding test parameter: gamemode singleplayer" << std::endl;
308 Com_Printf("CountSpawnpoints - adding test parameter: gamemode singleplayer\n");
309 }
310
311 /* Set initial values. */
312 /* load singleplayer map */
313 Cvar_Set("sv_maxclients", "1");
314 /* It seems, because of reaction-fire limitations we cannot spawn more than 128 actors total. */
315 Cvar_Set("sv_maxsoldiersperteam", "12");
316 Cvar_Set("ai_singleplayeraliens", "64");
317 Cvar_Set("ai_numcivilians", "16");
318
319 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);
320 long time = Sys_Milliseconds();
321
322 try {
323 SV_Map(true, md->mapTheme, asmName, true);
324 } catch (comDrop_t&) {
325 ADD_FAILURE() << "Error: Failed to load assembly " << asmName << " from mapdef " << md->id << ", map "
326 << md->mapTheme << " aircraft: " << aircraft << ", ufo: " << ufo << " => singleplayer mode.";
327 Com_Printf("CountSpawnpoints - error: Failed to load map.\n");
329 return;
330 }
331 time = Sys_Milliseconds() - time;
332 Com_Printf("CountSpawnpoints - result: %li ms\n", time);
333 mapCount++;
334
335 /* This is the max number of aliens the UFO can bring to the battlefield. */
336 const int numteamUFO = testCountSpawnpointsGetNumteamValueForUFO(ufo);
337
338 /* The number of human spawnpoints required on the map depends on the 'numteam' value
339 of the used dropship, if any. */
340 const int minHumans = testCountSpawnpointsGetNumteamValueForAircraft(aircraft);
341
342 /* The number of spawnpoints for 2x2 units required on the map depends on the number
343 of UGVs the aircraft can transport. */
344 const int minHuman2x2 = testCountSpawnpointsGetNum2x2ValueForAircraft(aircraft);
345
346 /* How many aliens do we need to have on the map, at least?
347 The mapdef defines the map to support up to 'maxaliens' aliens, so the map should have
348 at least this number of spawnpoints available.
349 However, this number must not be higher than the 'numteam' value of the used UFO, if any. */
350 const int minAliens = std::min(md->maxAliens, numteamUFO);
351
352 /* Count the spawnpoints available on the map. */
353 const int spawnCivs = static_cast<int>(level.num_spawnpoints[TEAM_CIVILIAN]);
354 const int spawnHumans = static_cast<int>(level.num_spawnpoints[TEAM_PHALANX]);
355 const int spawnAliens = static_cast<int>(level.num_spawnpoints[TEAM_ALIEN]);
356 const int spawnHuman2x2 = static_cast<int>(level.num_2x2spawnpoints[TEAM_PHALANX]);
357
358 /* Make gtest report back in case there are not enough human spawnpoints. */
359 EXPECT_GE(spawnHumans, minHumans) << "Error: Assembly " << asmName << " in mapdef " << md->id
360 << " from map " << md->mapTheme << " in singleplayer mode (aircraft: " << aircraft
361 << " ufo: " << ufo << "): Only " << spawnHumans << " human spawnpoints but " << minHumans
362 << " expected.";
363 /* Make gtest report back in case there are not enough alien spawnpoints. */
364 EXPECT_GE(spawnAliens, minAliens) << "Error: Assembly " << asmName << " in mapdef " << md->id
365 << " from map " << md->mapTheme << " in singleplayer mode (aircraft: " << aircraft
366 << " ufo: " << ufo << "): Only " << spawnAliens << " alien spawnpoints but " << minAliens
367 << " expected.";
368 /* Make gtest report back in case there are not enough human 2x2 spawnpoints. */
369 EXPECT_GE(spawnHuman2x2, minHuman2x2) << "Error: Assembly " << asmName << " in mapdef " << md->id
370 << " from map " << md->mapTheme << " in singleplayer mode (aircraft: " << aircraft
371 << " ufo: " << ufo << "): Only " << spawnHuman2x2 << " human 2x2 spawnpoints but " << minHuman2x2
372 << " expected.";
373 /* 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. */
374 if (ufo) {
375 EXPECT_GE(md->maxAliens, numteamUFO) << "Error: Assembly " << asmName << " in mapdef " << md->id
376 << " from map " << md->mapTheme << " in singleplayer mode (aircraft: " << aircraft
377 << " ufo: " << ufo << "): The number of aliens allowed on the map is smaller than expected.";
378 }
379
380 /* Print report to log. */
381 Com_Printf("CountSpawnpoints - map: mode singleplayer\n");
382 Com_Printf("CountSpawnpoints - map: mapdef %s\n", md->id);
383 Com_Printf("CountSpawnpoints - map: map %s\n", md->mapTheme);
384 Com_Printf("CountSpawnpoints - map: assembly %s\n", asmName);
385 Com_Printf("CountSpawnpoints - map: aircraft %s \n", aircraft);
386 Com_Printf("CountSpawnpoints - map: ufo %s\n", ufo);
387 Com_Printf("CountSpawnpoints - count spawnpoints: civilian %i\n", spawnCivs);
388 Com_Printf("CountSpawnpoints - count spawnpoints: singleplayer needs/found %i/%i\n", minHumans, spawnHumans);
389 Com_Printf("CountSpawnpoints - count spawnpoints: singleplayer_2x2 needs/found %i/%i\n", minHuman2x2, spawnHuman2x2);
390 Com_Printf("CountSpawnpoints - count spawnpoints: alien needs/found %i/%i\n", minAliens, spawnAliens);
391 if (spawnHumans < minHumans)
392 Com_Printf("CountSpawnpoints - error: missing spawnpoints - singleplayer needs/found %i/%i\n", minHumans, spawnHumans);
393 if (spawnHuman2x2 < minHuman2x2)
394 Com_Printf("CountSpawnpoints - error: missing spawnpoints - singleplayer_2x2 needs/found %i/%i\n", minHuman2x2, spawnHuman2x2);
395 if (spawnAliens < minAliens)
396 Com_Printf("CountSpawnpoints - error: missing spawnpoints - alien needs/found %i/%i\n", minAliens, spawnAliens);
397 if (ufo) {
398 if (md->maxAliens < numteamUFO) {
399 Com_Printf("CountSpawnpoints - error: mapdef parameter - maxaliens needs/found %i/%i\n", numteamUFO, md->maxAliens);
400 }
401 }
402
404}
405
406void GameTest::testCountSpawnpointsForMapWithAssemblyAndAircraftAndUfo(bool verbose, const mapDef_t *md, const char *asmName, const char *aircraft, const char *ufo)
407{
408 if (verbose && ufo) {
409 std::cout << "[ ] adding test parameter: ufo " << ufo << std::endl;
410 Com_Printf("CountSpawnpoints - adding test parameter: ufo %s\n", ufo);
411 }
412
413 /* The ufocrash map is a special one. The mapdef should not define single- nor
414 multiplayer mode. It uses one assembly for each ufo defined in the mapdef,
415 where the assembly name is equal the name of the UFO. */
416 if (Q_streq(md->id, "ufocrash")) {
417 testCountSpawnpointsForMapInSingleplayerMode(verbose, md, ufo, aircraft, ufo);
418 return;
419 }
420
421 /* Check if we are manually testing a certain gamemode. */
422 if (TEST_ExistsProperty("mode")) {
423 const char *mode = TEST_GetStringProperty("mode");
424 if (Q_streq(mode, "sp")) {
425 if (md->singleplayer || md->campaign) {
426 testCountSpawnpointsForMapInSingleplayerMode(verbose, md, asmName, aircraft, ufo);
427 } else {
428 Com_Printf("CountSpawnpoints - error: Gamemode not defined in mapdef: %s\n", mode);
429 ADD_FAILURE() << "Error: Gamemode not defined in mapdef: " << mode;
430 }
431 } else if (Q_streq(mode, "mp")) {
432 if (md->multiplayer) {
433 testCountSpawnpointsForMapInMultiplayerMode(verbose, md, asmName, aircraft, ufo);
434 } else {
435 Com_Printf("CountSpawnpoints - error: Gamemode not defined in mapdef: %s\n", mode);
436 ADD_FAILURE() << "Error: Gamemode not defined in mapdef: " << mode;
437 }
438 } else {
439 Com_Printf("CountSpawnpoints - error: Not a valid gamemode: %s\n", mode);
440 ADD_FAILURE() << "Error: Not a valid gamemode: " << mode;
441 }
442 } else {
443 /* Test every gamemode defined in the mapdef. */
444 if (md->singleplayer || md->campaign) {
445 testCountSpawnpointsForMapInSingleplayerMode(verbose, md, asmName, aircraft, ufo);
446 }
447 if (md->multiplayer) {
448 testCountSpawnpointsForMapInMultiplayerMode(verbose, md, asmName, aircraft, ufo);
449 }
450 }
451}
452
453void GameTest::testCountSpawnpointsForMapWithAssemblyAndAircraft(bool verbose, const mapDef_t *md, const char *asmName, const char *aircraft)
454{
455 if (verbose && aircraft) {
456 std::cout << "[ ] adding test parameter: aircraft " << aircraft << std::endl;
457 Com_Printf("CountSpawnpoints - adding test parameter: aircraft %s\n", aircraft);
458 }
459
460 /* Check if we are manually testing a certain UFO type. */
461 if (TEST_ExistsProperty("ufo")) {
462 const char *ufo = TEST_GetStringProperty("ufo");
463 int tested = 0;
464 LIST_Foreach(md->ufos, const char, s) {
465 if (Q_streq(ufo, s)) {
467 testCountSpawnpointsForMapWithAssemblyAndAircraftAndUfo(verbose, md, asmName, aircraft, ufo);
468 tested += 1;
469 }
470 }
471 if (tested < 1) {
472 Com_Printf("CountSpawnpoints - error: Not a valid UFO id: %s\n", ufo);
473 ADD_FAILURE() << "Error: Not a valid ufo id: " << ufo;
474 }
475 } else if (LIST_IsEmpty(md->ufos)) {
476 /* The mapdef defines no UFOs. */
477 Cvar_Set("rm_ufo", "");
478 testCountSpawnpointsForMapWithAssemblyAndAircraftAndUfo(verbose, md, asmName, aircraft, nullptr);
479 } else {
480 /* Test every UFO defined in the mapdef. */
481 LIST_Foreach(md->ufos, const char, ufo) {
483 testCountSpawnpointsForMapWithAssemblyAndAircraftAndUfo(verbose, md, asmName, aircraft, ufo);
484 }
485 }
486}
487
488void GameTest::testCountSpawnpointsForMapWithAssembly(bool verbose, const mapDef_t *md, const char *asmName)
489{
490 if (asmName) {
491 std::cout << "[ ] testing mapdef: " << md->id << " assembly: " << asmName << std::endl;
492 Com_Printf("CountSpawnpoints - adding test parameter: assembly %s\n", asmName);
493 } else {
494 std::cout << "[ ] testing mapdef: " << md->id << std::endl;
495 }
496
497 /* Check if we are manually testing a certain aircraft. */
498 if (TEST_ExistsProperty("aircraft")) {
499 const char *aircraft = TEST_GetStringProperty("aircraft");
500 int tested = 0;
501 LIST_Foreach(md->aircraft, const char, s) {
502 if (Q_streq(aircraft, s)) {
503 Cvar_Set("rm_drop", "%s", Com_GetRandomMapAssemblyNameForCraft(aircraft));
504 testCountSpawnpointsForMapWithAssemblyAndAircraft(verbose, md, asmName, aircraft);
505 tested += 1;
506 }
507 }
508 if (tested < 1) {
509 Com_Printf("CountSpawnpoints - error: Not a valid aircraft id: %s\n", aircraft);
510 ADD_FAILURE() << "Error: Not a valid aircraft id: " << aircraft;
511 }
512 } else if (LIST_IsEmpty(md->aircraft)) {
513 /* There is no aircraft defined in the mapdef. */
514 Cvar_Set("rm_drop", "");
515 testCountSpawnpointsForMapWithAssemblyAndAircraft(verbose, md, asmName, nullptr);
516 } else {
517 /* Testing every aircraft defined in the mapdef. */
518 LIST_Foreach(md->aircraft, const char, aircraft) {
519 Cvar_Set("rm_drop", "%s", Com_GetRandomMapAssemblyNameForCraft(aircraft));
520 testCountSpawnpointsForMapWithAssemblyAndAircraft(verbose, md, asmName, aircraft);
521 }
522 }
523}
524
526{
527 Com_Printf("CountSpawnpoints - test start: mapdef %s\n", md->id);
528
529 /* Check if we are manually testing a certain assembly. */
530 if (TEST_ExistsProperty("assembly")) {
531 const char *asmName = TEST_GetStringProperty("assembly");
532 int tested = 0;
533 LIST_Foreach(md->params, const char, s) {
534 if (Q_streq(asmName, s)) {
535 testCountSpawnpointsForMapWithAssembly(verbose, md, asmName);
536 tested += 1;
537 }
538 }
539 if (tested < 1) {
540 Com_Printf("CountSpawnpoints - error: Not a valid assembly: %s\n", asmName);
541 ADD_FAILURE() << "Error: Not a valid assembly: " << asmName;
542 }
543 } else if (LIST_IsEmpty(md->params)) {
544 /* This is for static maps. */
545 std::cout << "[ ] testing mapdef: " << md->id << std::endl;
546 testCountSpawnpointsForMapWithAssembly(verbose, md, nullptr);
547 } else {
548 /* This is for RMA. */
549 LIST_Foreach(md->params, const char, asmName) {
550 testCountSpawnpointsForMapWithAssembly(verbose, md, asmName);
551 }
552 }
553}
554
555TEST_F(GameTest, CountSpawnpointsStatic)
556{
557 bool verbose = false;
558 if (TEST_ExistsProperty("verbose"))
559 verbose = true;
560
561 mapCount = 0;
562 const mapDef_t* md;
563 MapDef_Foreach(md) {
564 /* Exlude RMA maps. */
565 if (md->mapTheme[0] == '+')
566 continue;
567 /* Exclude .baseattack. */
568 if (md->mapTheme[0] == '.')
569 return;
570 testCountSpawnpointsForMap(verbose, md);
571 }
572 std::cout << "[ ] Static maps tested: " << mapCount << std::endl;
573 Com_Printf("CountSpawnpoints - static maps tested: %i\n", mapCount);
574}
575
576TEST_F(GameTest, CountSpawnpointsRMA)
577{
578 bool verbose = false;
579 if (TEST_ExistsProperty("verbose"))
580 verbose = true;
581
582 mapCount = 0;
583 const mapDef_t* md;
584
585 /* Check if we are manually testing a certain mapdef. */
586 if (TEST_ExistsProperty("mapdef-id")) {
587 const char* mapdefId = TEST_GetStringProperty("mapdef-id");
588 int tested = 0;
589 MapDef_Foreach(md) {
590 if (Q_streq(md->id, mapdefId)) {
591 testCountSpawnpointsForMap(verbose, md);
592 tested += 1;
593 }
594 }
595 if (tested < 1) {
596 Com_Printf("CountSpawnpoints - error: Not a valid mapdef: %s\n", mapdefId);
597 ADD_FAILURE() << "Error: Not a valid mapdef: " << mapdefId;
598 }
599 } else {
600 MapDef_Foreach(md) {
601 /* Exlude static maps. */
602 if (md->mapTheme[0] != '+')
603 continue;
604 /* Exclude .baseattack. */
605 if (md->mapTheme[0] == '.')
606 return;
607
608 testCountSpawnpointsForMap(verbose, md);
609 }
610 }
611 Com_Printf("CountSpawnpoints - RMA combinations tested: RMA %i\n", mapCount);
612 std::cout << "[ ] RMA combinations tested: " << mapCount << std::endl;
614}
615
616TEST_F(GameTest, DoorTrigger)
617{
618 const char* mapName = "test_game";
619 ASSERT_NE(-1, FS_CheckFile("maps/%s.bsp", mapName)) << "Map resource '" << mapName << ".bsp' for test is missing.";
620 Edict* e = nullptr;
621 int cnt = 0;
622 int doors = 0;
623
624 SV_Map(true, mapName, nullptr);
625 while ((e = G_EdictsGetNextInUse(e))) {
626 cnt++;
627 if (e->type != ET_DOOR)
628 continue;
629 if (Q_streq(e->targetname, "left-0")) {
630 ASSERT_TRUE(e->doorState) << "this one is triggered by an actor standing inside of a trigger_touch";
631 } else if (Q_streq(e->targetname, "right-0")) {
632 ASSERT_FALSE(e->doorState) << "this one has a trigger_touch, too - but nobody is touching that trigger yet";
633 } else {
634 ASSERT_TRUE(false) << "both of the used doors have a targetname set";
635 }
636 doors++;
637 }
638
639 ASSERT_TRUE(cnt > 0);
640 ASSERT_TRUE(doors == 2);
641}
642
643TEST_F(GameTest, Shooting)
644{
645 const char* mapName = "test_game";
646 ASSERT_NE(-1, FS_CheckFile("maps/%s.bsp", mapName)) << "Map resource '" << mapName << ".bsp' for test is missing.";
647 SV_Map(true, mapName, nullptr);
652}
653
654static int GAMETEST_GetItemCount (const Edict* ent, containerIndex_t container)
655{
656 const Item* invlist = ent->getContainer(container);
657 int count = 0;
658 while (invlist != nullptr) {
659 count += invlist->getAmount();
660 invlist = invlist->getNext();
661 }
662
663 return count;
664}
665
666TEST_F(GameTest, VisFlags)
667{
668 const char* mapName = "test_game";
669 ASSERT_NE(-1, FS_CheckFile("maps/%s.bsp", mapName)) << "Map resource '" << mapName << ".bsp' for test is missing.";
670 int num;
671
672 SV_Map(true, mapName, nullptr);
673
674 num = 0;
675 Actor* actor = nullptr;
676 while ((actor = G_EdictsGetNextLivingActorOfTeam(actor, TEAM_ALIEN))) {
677 const teammask_t teamMask = G_TeamToVisMask(actor->getTeam());
678 const bool visible = actor->visflags & teamMask;
679 char* visFlagsBuf = Mem_StrDup(Com_UnsignedIntToBinary(actor->visflags));
680 char* teamMaskBuf = Mem_StrDup(Com_UnsignedIntToBinary(teamMask));
681 ASSERT_EQ(actor->getTeam(), TEAM_ALIEN);
682 ASSERT_TRUE(visible) << "visflags: " << visFlagsBuf << ", teamMask: " << teamMaskBuf;
683 Mem_Free(visFlagsBuf);
684 Mem_Free(teamMaskBuf);
685 num++;
686 }
687
688 ASSERT_TRUE(num > 0) << "No alien actors found";
689}
690
691TEST_F(GameTest, InventoryForDiedAlien)
692{
693 const char* mapName = "test_game";
694 ASSERT_NE(-1, FS_CheckFile("maps/%s.bsp", mapName)) << "Map resource '" << mapName << ".bsp' for test is missing.";
695 Actor* diedEnt;
696 Actor* actor;
697 Edict* floorItems;
698 Item* invlist;
699 int count;
700 SV_Map(true, mapName, nullptr);
701 level.activeTeam = TEAM_ALIEN;
702
703 /* first alien that should die and drop its inventory */
705 ASSERT_TRUE(nullptr != diedEnt);
706 diedEnt->HP = 0;
707 ASSERT_TRUE(G_ActorDieOrStun(diedEnt, nullptr));
708 ASSERT_TRUE(diedEnt->isDead());
709
710 /* now try to collect the inventory with a second alien */
712 ASSERT_TRUE(nullptr != actor);
713
714 /* move to the location of the first died alien to drop the inventory into the same floor container */
715 Player& player = actor->getPlayer();
716 ASSERT_TRUE(G_IsAIPlayer(&player));
717 G_ClientMove(player, 0, actor, diedEnt->pos);
718 ASSERT_TRUE(VectorCompare(actor->pos, diedEnt->pos));
719
720 floorItems = G_GetFloorItems(actor);
721 ASSERT_TRUE(nullptr != floorItems);
722 ASSERT_EQ(floorItems->getFloor(), actor->getFloor());
723
724 /* drop everything to floor to make sure we have space in the backpack */
725 G_InventoryToFloor(actor);
726 ASSERT_EQ(0, GAMETEST_GetItemCount(actor, CID_BACKPACK));
727
728 invlist = actor->getContainer(CID_BACKPACK);
729 ASSERT_TRUE(nullptr == invlist);
731 if (count > 0) {
732 Item* entryToMove = actor->getFloor();
733 int tx, ty;
734 actor->chr.inv.findSpace(INVDEF(CID_BACKPACK), entryToMove, &tx, &ty, entryToMove);
735 if (tx == NONE)
736 return;
737 Com_Printf("trying to move item %s from floor into backpack to pos %i:%i\n", entryToMove->def()->name, tx, ty);
738 ASSERT_TRUE(G_ActorInvMove(actor, INVDEF(CID_FLOOR), entryToMove, INVDEF(CID_BACKPACK), tx, ty, false));
739 ASSERT_EQ(count - 1, GAMETEST_GetItemCount(actor, CID_FLOOR)) << "item " << entryToMove->def()->name << " could not get moved successfully from floor into backpack";
740 Com_Printf("item %s was removed from floor\n", entryToMove->def()->name);
741 ASSERT_EQ(1, GAMETEST_GetItemCount(actor, CID_BACKPACK)) << "item " << entryToMove->def()->name << " could not get moved successfully from floor into backpack";
742 Com_Printf("item %s was moved successfully into the backpack\n", entryToMove->def()->name);
743 invlist = actor->getContainer(CID_BACKPACK);
744 ASSERT_TRUE(nullptr != invlist);
745 }
746}
747
748TEST_F(GameTest, InventoryWithTwoDiedAliensOnTheSameGridTile)
749{
750 const char* mapName = "test_game";
751 ASSERT_NE(-1, FS_CheckFile("maps/%s.bsp", mapName)) << "Map resource '" << mapName << ".bsp' for test is missing.";
752 Actor* diedEnt;
753 Actor* diedEnt2;
754 Actor* actor;
755 Edict* floorItems;
756 Item* invlist;
757 int count;
758 SV_Map(true, mapName, nullptr);
759 level.activeTeam = TEAM_ALIEN;
760
761 /* first alien that should die and drop its inventory */
763 ASSERT_TRUE(nullptr != diedEnt) << "No living actor in the alien team";
764 diedEnt->HP = 0;
765 G_ActorDieOrStun(diedEnt, nullptr);
766 ASSERT_TRUE(diedEnt->isDead()) << "Actor is not dead";
767
768 /* second alien that should die and drop its inventory */
769 diedEnt2 = G_EdictsGetNextLivingActorOfTeam(nullptr, TEAM_ALIEN);
770 ASSERT_TRUE(nullptr != diedEnt2) << "No living actor in the alien team";
771
772 /* move to the location of the first died alien to drop the inventory into the same floor container */
773 Player& player = diedEnt2->getPlayer();
774 ASSERT_TRUE(G_IsAIPlayer(&player));
775 G_ClientMove(player, 0, diedEnt2, diedEnt->pos);
776 ASSERT_TRUE(VectorCompare(diedEnt2->pos, diedEnt->pos));
777
778 diedEnt2->HP = 0;
779 G_ActorDieOrStun(diedEnt2, nullptr);
780 ASSERT_TRUE(diedEnt2->isDead()) << "Actor is not dead";
781
782 /* now try to collect the inventory with a third alien */
784 ASSERT_TRUE(nullptr != actor) << "No living actor in the alien team";
785
786 player = actor->getPlayer();
787 ASSERT_TRUE(G_IsAIPlayer(&player)) << "Player is not ai controlled";
788
789 G_ClientMove(player, 0, actor, diedEnt->pos);
790 ASSERT_TRUE(VectorCompare(actor->pos, diedEnt->pos)) << "Actor is not at the same position as the died entity";
791
792 floorItems = G_GetFloorItems(actor);
793 ASSERT_TRUE(nullptr != floorItems);
794 ASSERT_EQ(floorItems->getFloor(), actor->getFloor());
795
796 /* drop everything to floor to make sure we have space in the backpack */
797 G_InventoryToFloor(actor);
798 ASSERT_EQ(0, GAMETEST_GetItemCount(actor, CID_BACKPACK));
799
800 invlist = actor->getContainer(CID_BACKPACK);
801 ASSERT_TRUE(nullptr == invlist);
802
804 if (count > 0) {
805 Item* entryToMove = actor->getFloor();
806 int tx, ty;
807 actor->chr.inv.findSpace(INVDEF(CID_BACKPACK), entryToMove, &tx, &ty, entryToMove);
808 if (tx == NONE)
809 return;
810 Com_Printf("trying to move item %s from floor into backpack to pos %i:%i\n", entryToMove->def()->name, tx, ty);
811 ASSERT_TRUE(G_ActorInvMove(actor, INVDEF(CID_FLOOR), entryToMove, INVDEF(CID_BACKPACK), tx, ty, false));
812 ASSERT_EQ(GAMETEST_GetItemCount(actor, CID_FLOOR), count - 1) << "item " << entryToMove->def()->name << " could not get moved successfully from floor into backpack";
813 Com_Printf("item %s was removed from floor\n", entryToMove->def()->name);
814 ASSERT_EQ(GAMETEST_GetItemCount(actor, CID_BACKPACK), 1) << "item " << entryToMove->def()->name << " could not get moved successfully from floor into backpack";
815 Com_Printf("item %s was moved successfully into the backpack\n", entryToMove->def()->name);
816 invlist = actor->getContainer(CID_BACKPACK);
817 ASSERT_TRUE(nullptr != invlist);
818 }
819}
820
821TEST_F(GameTest, InventoryTempContainerLinks)
822{
823 const char* mapName = "test_game";
824 ASSERT_NE(-1, FS_CheckFile("maps/%s.bsp", mapName)) << "Map resource '" << mapName << ".bsp' for test is missing.";
825 SV_Map(true, mapName, nullptr);
826 level.activeTeam = TEAM_ALIEN;
827
828 /* first alien that should die and drop its inventory */
830 int nr = 0;
831 const Container* cont = nullptr;
832 while ((cont = actor->chr.inv.getNextCont(cont, true))) {
833 if (cont->id == CID_ARMOUR || cont->id == CID_FLOOR)
834 continue;
835 nr += cont->countItems();
836 }
837 ASSERT_TRUE(nr > 0) << "Could not find any items in the inventory of the actor";
838
839 ASSERT_TRUE(nullptr == actor->getFloor());
840 G_InventoryToFloor(actor);
841 ASSERT_TRUE(nullptr != actor->getFloor());
842 ASSERT_EQ(G_GetFloorItemFromPos(actor->pos)->getFloor(), actor->getFloor());
843
844 nr = 0;
845 cont = nullptr;
846 while ((cont = actor->chr.inv.getNextCont(cont, true))) {
847 if (cont->id == CID_ARMOUR || cont->id == CID_FLOOR)
848 continue;
849 nr += cont->countItems();
850 }
851 ASSERT_EQ(0, nr);
852}
#define INVDEF(containerID)
Definition cl_shared.h:48
An Edict of type Actor.
Definition g_edict.h:348
bool isDead() const
Definition g_edict.h:362
int countItems() const
Count the number of items in the Container.
teammask_t visflags
Definition g_edict.h:82
character_t chr
Definition g_edict.h:116
const char * classname
Definition g_edict.h:67
pos3_t pos
Definition g_edict.h:55
int HP
Definition g_edict.h:89
int doorState
Definition g_edict.h:158
int getTeam() const
Definition g_edict.h:269
Player & getPlayer() const
Definition g_edict.h:265
const char * targetname
Definition g_edict.h:126
entity_type_t type
Definition g_edict.h:81
Item * getContainer(const containerIndex_t idx) const
Definition g_edict.h:243
Item * getFloor() const
Definition g_edict.h:262
int testCountSpawnpointsGetNumteamValueForUFO(const char *ufo)
void testCountSpawnpointsForMapWithAssemblyAndAircraft(bool verbose, const mapDef_t *md, const char *asmName, const char *aircraft)
static void TearDownTestCase()
Definition test_game.cpp:55
void SetUp()
Definition test_game.cpp:69
static void SetUpTestCase()
Definition test_game.cpp:41
void testCountSpawnpointsForMapWithAssemblyAndAircraftAndUfo(bool verbose, const mapDef_t *md, const char *asmName, const char *aircraft, const char *ufo)
int testCountSpawnpointsGetNumteamValueForAircraft(const char *aircraft)
void testCountSpawnpointsForMapInSingleplayerMode(bool verbose, const mapDef_t *md, const char *asmName, const char *aircraft, const char *ufo)
int testCountSpawnpointsGetNum2x2ValueForAircraft(const char *aircraft)
void testCountSpawnpointsForMap(bool verbose, const mapDef_t *md)
void testCountSpawnpointsForMapInMultiplayerMode(bool verbose, const mapDef_t *md, const char *asmName, const char *aircraft, const char *ufo)
void TearDown()
Definition test_game.cpp:73
void testCountSpawnpointsForMapWithAssembly(bool verbose, const mapDef_t *md, const char *asmName)
void findSpace(const invDef_t *container, const Item *item, int *const px, int *const py, const Item *ignoredItem) const
Finds space for item in inv at container.
const Container * getNextCont(const Container *prev, bool inclTemp=false) const
item instance data, with linked list capability
Definition inv_shared.h:402
int getAmount() const
Definition inv_shared.h:463
const objDef_t * def(void) const
Definition inv_shared.h:469
Item * getNext() const
Definition inv_shared.h:451
csi_t csi
Definition common.cpp:39
cvar_t * port
Definition common.cpp:58
const char * Com_UnsignedIntToBinary(uint32_t x)
Definition common.cpp:1038
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
memPool_t * com_networkPool
Definition common.cpp:73
cvar_t * masterserver_url
Definition common.cpp:57
cvar_t * sv_maxclients
Definition g_main.cpp:43
#define PORT_SERVER
Definition common.h:137
#define MASTER_SERVER
Definition common.h:124
cvar_t * Cvar_Set(const char *varName, const char *value,...)
Sets a cvar value.
Definition cvar.cpp:615
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags, const char *desc)
Init or return a cvar.
Definition cvar.cpp:342
#define CVAR_SERVERINFO
Definition cvar.h:42
#define CVAR_ARCHIVE
Definition cvar.h:40
#define CVAR_NOSET
Definition cvar.h:43
#define NONE
Definition defines.h:68
int FS_CheckFile(const char *fmt,...)
Just returns the filelength and -1 if the file wasn't found.
Definition files.cpp:298
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
Definition files.cpp:384
void FS_FreeFile(void *buffer)
Definition files.cpp:411
bool G_ActorDieOrStun(Actor *actor, Edict *attacker)
Reports and handles death or stun of an actor. If the HP of an actor is zero the actor will die,...
Definition g_actor.cpp:435
bool G_ActorInvMove(Actor *actor, const invDef_t *fromContType, Item *fItem, const invDef_t *toContType, int tx, int ty, bool checkaction)
Moves an item inside an inventory. Floors are handled special.
Definition g_actor.cpp:506
Player * G_PlayerGetNextHuman(Player *lastPlayer)
Iterate through the list of players.
Definition g_client.cpp:58
Interface for g_client.cpp.
Actor * G_EdictsGetNextLivingActorOfTeam(Actor *lastEnt, const int team)
Iterate through the living actor entities of the given team.
Definition g_edicts.cpp:216
Edict * G_EdictsGetNextInUse(Edict *lastEnt)
Iterate through the entities that are in use.
Definition g_edicts.cpp:166
functions to handle the storage and lifecycle of all edicts in the game module.
void G_InventoryToFloor(Edict *ent)
Move items to adjacent locations if the containers on the current floor edict are full.
Edict * G_GetFloorItems(Edict *ent)
Prepares a list of items on the floor at given entity position.
Edict * G_GetFloorItemFromPos(const pos3_t pos)
Callback to G_GetEdictFromPos() for given position, used to get items from position.
Local definitions for game module.
level_locals_t level
Definition g_main.cpp:38
#define G_TeamToVisMask(team)
Definition g_local.h:143
#define G_IsAIPlayer(player)
Definition g_local.h:142
void G_ClientMove(const Player &player, int visTeam, Actor *actor, const pos3_t to)
Generates the client events that are send over the netchannel to move an actor.
Definition g_move.cpp:307
unsigned int teammask_t
Definition g_vis.h:30
SrvPlayer player_t
Definition game.h:72
#define MAX_INFO_STRING
Definition infostring.h:36
#define CID_BACKPACK
Definition inv_shared.h:51
#define CID_ARMOUR
Definition inv_shared.h:54
int32_t containerIndex_t
Definition inv_shared.h:46
#define CID_FLOOR
Definition inv_shared.h:55
voidpf void uLong size
Definition ioapi.h:42
voidpf void * buf
Definition ioapi.h:42
const char int mode
Definition ioapi.h:41
bool LIST_IsEmpty(const linkedList_t *list)
Checks whether the given list is empty.
Definition list.cpp:335
#define LIST_Foreach(list, type, var)
Iterates over a linked list, it's safe to delete the returned entry from the list while looping over ...
Definition list.h:41
#define Mem_Free(ptr)
Definition mem.h:35
#define Mem_CreatePool(name)
Definition mem.h:32
#define Mem_StrDup(in)
Definition mem.h:48
#define MAX_CLIENTS
Definition q_shared.h:299
#define TEAM_PHALANX
Definition q_shared.h:62
#define TEAM_ALIEN
Definition q_shared.h:63
#define MapDef_Foreach(var)
Definition q_shared.h:505
@ ET_DOOR
Definition q_shared.h:156
#define TEAM_MAX_HUMAN
Definition q_shared.h:64
#define TEAM_CIVILIAN
Definition q_shared.h:61
QGL_EXTERN GLuint count
Definition r_gl.h:99
QGL_EXTERN GLint i
Definition r_gl.h:113
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition r_gl.h:110
rstate_t r_state
Definition r_main.cpp:48
void Com_ParseScripts(bool onlyServer)
Definition scripts.cpp:3619
const char * Com_GetRandomMapAssemblyNameForCraft(const char *craftID)
Returns the name of an aircraft or an ufo that is used in the ump files for the random map assembly.
Definition scripts.cpp:3277
Main server include file.
memPool_t * sv_genericPool
Definition sv_main.cpp:55
void SV_ClearWorld(void)
Clear physics interaction links.
Definition sv_world.cpp:81
void SV_Map(bool day, const char *levelstring, const char *assembly, bool verbose=true)
Change the server to a new map, taking all connected clients along with it.
Definition sv_init.cpp:113
void SV_ShutdownGameProgs(void)
Called when either the entire server is being killed, or it is changing to a different game directory...
Definition sv_game.cpp:681
void SV_InitGameProgs(void)
Init the game subsystem for a new map.
Definition sv_game.cpp:747
serverInstanceGame_t * sv
Definition sv_init.cpp:36
serverInstanceStatic_t svs
Definition sv_init.cpp:35
#define Q_streq(a, b)
Definition shared.h:136
bool Q_strnull(const char *string)
Definition shared.h:138
#define DOUBLEQUOTE(x)
Definition shared.h:90
#define OBJZERO(obj)
Definition shared.h:178
Inventory inv
Definition chr_shared.h:411
char value[MAX_VAR]
Definition q_shared.h:338
char name[MAX_VAR]
Definition q_shared.h:337
cvarlist_t cvars[MAX_CVARLISTINGAMETYPE]
Definition q_shared.h:344
int num_cvars
Definition q_shared.h:345
char id[MAX_VAR]
Definition q_shared.h:342
linkedList_t * gameTypes
Definition q_shared.h:476
linkedList_t * aircraft
Definition q_shared.h:492
int teams
Definition q_shared.h:475
char * mapTheme
Definition q_shared.h:464
linkedList_t * ufos
Definition q_shared.h:491
char * id
Definition q_shared.h:463
int maxAliens
Definition q_shared.h:483
bool campaign
Definition q_shared.h:480
linkedList_t * params
Definition q_shared.h:465
bool multiplayer
Definition q_shared.h:474
bool singleplayer
Definition q_shared.h:481
const char * name
Definition inv_shared.h:267
int Sys_Milliseconds(void)
static int mapCount
Definition test_game.cpp:37
static int GAMETEST_GetItemCount(const Edict *ent, containerIndex_t container)
TEST_F(GameTest, SpawnAndConnect)
Definition test_game.cpp:78
static const char * mapName
void TEST_Shutdown(void)
bool TEST_ExistsProperty(const char *name)
const char * TEST_GetStringProperty(const char *name)
void TEST_Init(void)
Cross-platform type definitions.
#define VectorCompare(a, b)
Definition vector.h:63