/** * @sa CL_ServerInfoCallback */ static void CL_ServerInfo_f (void) { struct net_stream *s; const char *host; const char *port; switch (cgi->Cmd_Argc()) { case 2: host = cgi->Cmd_Argv(1); port = DOUBLEQUOTE(PORT_SERVER); break; case 3: host = cgi->Cmd_Argv(1); port = cgi->Cmd_Argv(2); break; default: if (selectedServer) { host = selectedServer->node; port = selectedServer->service; } else { host = cgi->Cvar_GetString("mn_server_ip"); port = DOUBLEQUOTE(PORT_SERVER); } break; } s = cgi->NET_Connect(host, port, NULL); if (s) { cgi->NET_OOB_Printf(s, "status %i", PROTOCOL_VERSION); cgi->NET_StreamSetCallback(s, &CL_ServerInfoCallback); } else cgi->Com_Printf("Could not connect to %s %s\n", host, port); }
/** * @brief Sends an rcon command to the gameserver that the user is currently connected to, * or if this is not the case, the gameserver that is specified in the cvar rcon_address. * @return @c true if the command was send, @c false otherwise. */ bool GAME_MP_Rcon (const char* password, const char* command) { if (Q_strnull(password)) { cgi->Com_Printf("You must set 'rcon_password' before issuing a rcon command.\n"); return false; } if (cgi->CL_GetClientState() >= ca_connected) { cgi->NET_OOB_Printf2(SV_CMD_RCON " %s %s", password, command); return true; } else if (rcon_address->string) { const char* port; if (strstr(rcon_address->string, ":")) port = strstr(rcon_address->string, ":") + 1; else port = DOUBLEQUOTE(PORT_SERVER); struct net_stream* s = cgi->NET_Connect(rcon_address->string, port, nullptr); if (s) { cgi->NET_OOB_Printf(s, SV_CMD_RCON " %s %s", password, command); cgi->NET_StreamSetCallback(s, &GAME_MP_RconCallback); return true; } } cgi->Com_Printf("You are not connected to any server\n"); return false; }
/** * @brief A brand new game has been started */ static void SV_InitGame (void) { /* allow next change after map change or restart */ sv_maxclients->flags |= CVAR_LATCH; /* get any latched variable changes (sv_maxclients, etc) */ Cvar_UpdateLatchedVars(); if (svs.serverMutex) Sys_Error("There is still a server running"); svs.clients = (client_t *)Mem_PoolAlloc(sizeof(client_t) * sv_maxclients->integer, sv_genericPool, 0); svs.serverMutex = TH_MutexCreate("server"); /* init network stuff */ if (sv_maxclients->integer > 1) { svs.initialized = SV_Start(NULL, port->string, &SV_ReadPacket); svs.netDatagramSocket = NET_DatagramSocketNew(NULL, Cvar_Get("port", DOUBLEQUOTE(PORT_SERVER), CVAR_NOSET, NULL)->string, &SV_DiscoveryCallback); } else svs.initialized = SV_Start(NULL, NULL, &SV_ReadPacket); SV_Heartbeat_f(); /* init game */ SV_InitGameProgs(); if (sv_maxclients->integer != 1 && (sv_dedicated->integer || sv_public->integer)) SV_SetMaster_f(); }
void R_InitPrograms (void) { if (!qglCreateProgram) { Com_Printf("not using GLSL shaders\n"); Cvar_Set("r_programs", "0"); r_programs->modified = false; return; } OBJZERO(r_state.shaders); OBJZERO(r_state.programs); /* Capable of running shaders, but have got them disabled, so do nothing */ if (!r_programs->integer) return; r_state.world_program = R_LoadProgram(shaderQualityLevelNames[r_programs->integer - 1][0], R_InitWorldProgram, R_UseWorldProgram); r_state.model_program = R_LoadProgram(shaderQualityLevelNames[r_programs->integer - 1][1], R_InitModelProgram, R_UseModelProgram); r_state.warp_program = R_LoadProgram("warp", R_InitWarpProgram, R_UseWarpProgram); r_state.geoscape_program = R_LoadProgram("geoscape", R_InitGeoscapeProgram, nullptr); r_state.combine2_program = R_LoadProgram("combine2", R_InitCombine2Program, nullptr); r_state.convolve_program = R_LoadProgram("convolve" DOUBLEQUOTE(FILTER_SIZE), R_InitConvolveProgram, R_UseConvolveProgram); r_state.atmosphere_program = R_LoadProgram("atmosphere", R_InitAtmosphereProgram, nullptr); r_state.simple_glow_program = R_LoadProgram("simple_glow", R_InitSimpleGlowProgram, nullptr); if (!(r_state.world_program && r_state.model_program && r_state.warp_program && r_state.geoscape_program && r_state.combine2_program && r_state.convolve_program && r_state.atmosphere_program && r_state.simple_glow_program)) { Com_Printf("disabled shaders because they failed to compile\n"); Cvar_Set("r_programs", "0"); r_programs->modified = false; } }
/** * @brief Only called once at startup, not for each game */ void SV_Init (void) { Com_Printf("\n------ server initialization -------\n"); sv_genericPool = Mem_CreatePool("Server: Generic"); OBJZERO(svs); sv = (serverInstanceGame_t *) Mem_PoolAlloc(sizeof(*sv), sv_genericPool, 0); SV_InitOperatorCommands(); rcon_password = Cvar_Get("rcon_password", "", 0, NULL); Cvar_Get("sv_cheats", "0", CVAR_SERVERINFO | CVAR_LATCH, NULL); Cvar_Get("sv_protocol", DOUBLEQUOTE(PROTOCOL_VERSION), CVAR_SERVERINFO | CVAR_NOSET, NULL); /* this cvar will become a latched cvar when you start the server */ sv_maxclients = Cvar_Get("sv_maxclients", "1", CVAR_SERVERINFO, "Max. connected clients"); sv_hostname = Cvar_Get("sv_hostname", "noname", CVAR_SERVERINFO | CVAR_ARCHIVE, "The name of the server that is displayed in the serverlist"); sv_http_downloadserver = Cvar_Get("sv_http_downloadserver", "", CVAR_ARCHIVE, "URL to a location where clients can download game content over HTTP"); sv_enablemorale = Cvar_Get("sv_enablemorale", "1", CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_LATCH, "Enable morale changes in multiplayer"); sv_maxsoldiersperteam = Cvar_Get("sv_maxsoldiersperteam", "4", CVAR_ARCHIVE | CVAR_SERVERINFO, "Max. amount of soldiers per team (see sv_maxsoldiersperplayer and sv_teamplay)"); sv_maxsoldiersperplayer = Cvar_Get("sv_maxsoldiersperplayer", "8", CVAR_ARCHIVE | CVAR_SERVERINFO, "Max. amount of soldiers each player can controll (see maxsoldiers and sv_teamplay)"); Cvar_SetCheckFunction("sv_maxsoldiersperplayer", SV_CheckMaxSoldiersPerPlayer); sv_dumpmapassembly = Cvar_Get("sv_dumpmapassembly", "0", CVAR_ARCHIVE, "Dump map assembly information to game console"); sv_threads = Cvar_Get("sv_threads", "1", CVAR_LATCH | CVAR_ARCHIVE, "Run the server threaded"); sv_public = Cvar_Get("sv_public", "1", 0, "Should heartbeats be send to the masterserver"); sv_reconnect_limit = Cvar_Get("sv_reconnect_limit", "3", CVAR_ARCHIVE, "Minimum seconds between connect messages"); SV_MapcycleInit(); }
void GAME_MP_CallbacksInit (const cgame_import_t* import) { cgi = import; rcon_client_password = cgi->Cvar_Get("rcon_password", "", 0, "Remote console password"); rcon_address = cgi->Cvar_Get("rcon_address", "", 0, "Address of the host you would like to control via rcon"); info_password = cgi->Cvar_Get("password", "", CVAR_USERINFO, nullptr); cl_maxsoldiersperteam = cgi->Cvar_Get("sv_maxsoldiersperteam", "4", CVAR_ARCHIVE | CVAR_SERVERINFO, "How many soldiers may one team have"); cl_maxsoldiersperplayer = cgi->Cvar_Get("sv_maxsoldiersperplayer", DOUBLEQUOTE(MAX_ACTIVETEAM), CVAR_ARCHIVE | CVAR_SERVERINFO, "How many soldiers one player is able to control in a given team"); cl_roundtimelimit = cgi->Cvar_Get("sv_roundtimelimit", "90", CVAR_ARCHIVE | CVAR_SERVERINFO, "Timelimit in seconds for multiplayer rounds"); cgi->Cmd_AddCommand("mp_selectteam_init", GAME_MP_SelectTeam_Init_f, "Function that gets all connected players and let you choose a free team"); cgi->Cmd_AddCommand("mp_init_ui", GAME_MP_InitUI_f, nullptr); cgi->Cmd_AddCommand("teamnum_dec", GAME_MP_TeamNum_f, "Decrease the preferred teamnum"); cgi->Cmd_AddCommand("teamnum_inc", GAME_MP_TeamNum_f, "Increase the preferred teamnum"); cgi->Cmd_AddCommand("pingservers", GAME_MP_PingServers_f, "Ping all servers in local network to get the serverlist"); cgi->Cmd_AddCommand("disconnect", GAME_MP_Disconnect_f, "Disconnect from the current server"); cgi->Cmd_AddCommand("connect", GAME_MP_Connect_f, "Connect to given ip"); cgi->Cmd_AddParamCompleteFunction("connect", GAME_MP_CompleteNetworkAddress); cgi->Cmd_AddCommand("reconnect", GAME_MP_Reconnect_f, "Reconnect to last server"); cgi->Cmd_AddCommand("rcon", GAME_MP_Rcon_f, "Execute a rcon command - see rcon_password"); cgi->Cmd_AddCommand("cl_startgame", GAME_MP_StartGame_f, "Forces a gamestart if you are the admin"); cgi->Cmd_AddParamCompleteFunction("rcon", GAME_MP_CompleteNetworkAddress); cl_maxsoldiersperteam->modified = false; cl_maxsoldiersperplayer->modified = false; }
static void SetUpTestCase() { TEST_Init(); /* we need the teamdefs for spawning ai actors */ Com_ParseScripts(true); Cvar_Set("sv_threads", "0"); sv_maxclients = Cvar_Get("sv_maxclients", "1", CVAR_SERVERINFO, "Max. connected clients for test"); port = Cvar_Get("port", DOUBLEQUOTE(PORT_SERVER), CVAR_NOSET); masterserver_url = Cvar_Get("masterserver_url", MASTER_SERVER, CVAR_ARCHIVE, "URL of UFO:AI masterserver"); sv_genericPool = Mem_CreatePool("server-gametest"); com_networkPool = Mem_CreatePool("server-gametest-network"); r_state.active_texunit = &r_state.texunits[0]; }
/** * @brief Adds a new entry into string with given value. * @note Removed any old version of the key * @param[in,out] s The target info string * @param[in] size The size of @c s * @param[in] key The key to set * @param[in] value The value to set for the given key * @sa Info_RemoveKey * @sa Info_SetValueForKeyAsInteger */ void Info_SetValueForKey (char* s, const size_t size, const char* key, const char* value) { char newi[MAX_INFO_STRING]; if (strstr(key, "\\") || strstr(value, "\\")) { Com_Printf("Can't use keys or values with a \\\n"); return; } if (strstr(key, ";")) { Com_Printf("Can't use keys or values with a semicolon\n"); return; } if (strstr(key, "\"") || strstr(value, "\"")) { Com_Printf("Can't use keys or values with a \"\n"); return; } if (strlen(key) > MAX_INFO_KEY - 1) { Com_Printf("Keys must be < " DOUBLEQUOTE(MAX_INFO_KEY) " characters.\n"); return; } if (strlen(key) > MAX_INFO_VALUE - 1) { Com_Printf("Values must be < " DOUBLEQUOTE(MAX_INFO_VALUE) " characters.\n"); return; } Info_RemoveKey(s, key); if (Q_strnull(value)) return; Com_sprintf(newi, sizeof(newi), "\\%s\\%s%s", key, value, s); Q_strncpyz(s, newi, size); }
/** * @brief The first function called when entering the multiplayer menu, then CL_Frame takes over * @sa CL_ParseServerInfoMessage * @note Use a parameter for pingservers to update the current serverlist */ void CL_PingServers_f (void) { selectedServer = NULL; /* refresh the list */ if (cgi->Cmd_Argc() == 2) { int i; /* reset current list */ serverText[0] = 0; serversAlreadyQueried = false; for (i = 0; i < serverListLength; i++) { cgi->Free(serverList[i].node); cgi->Free(serverList[i].service); } serverListPos = 0; serverListLength = 0; OBJZERO(serverList); } else { cgi->UI_RegisterText(TEXT_LIST, serverText); return; } if (!netDatagramSocket) netDatagramSocket = cgi->NET_DatagramSocketNew(NULL, DOUBLEQUOTE(PORT_CLIENT), &CL_ServerListDiscoveryCallback); /* broadcast search for all the servers int the local network */ if (netDatagramSocket) { const char buf[] = "discover"; cgi->NET_DatagramBroadcast(netDatagramSocket, buf, sizeof(buf), PORT_SERVER); } cgi->UI_RegisterText(TEXT_LIST, serverText); /* don't query the masterservers with every call */ if (serversAlreadyQueried) { if (lastServerQuery + SERVERQUERYTIMEOUT > cgi->CL_Milliseconds()) return; } else serversAlreadyQueried = true; lastServerQuery = cgi->CL_Milliseconds(); /* query master server? */ if (cgi->Cmd_Argc() == 2 && !Q_streq(cgi->Cmd_Argv(1), "local")) { cgi->Com_DPrintf(DEBUG_CLIENT, "Query masterserver\n"); cgi->CL_QueryMasterServer("query", CL_QueryMasterServerThread); } }
void GAME_MP_CallbacksInit (const cgame_import_t* import) { cgi = import; rcon_client_password = cgi->Cvar_Get("rcon_password", "", 0, "Remote console password"); rcon_address = cgi->Cvar_Get("rcon_address", "", 0, "Address of the host you would like to control via rcon"); info_password = cgi->Cvar_Get("password", "", CVAR_USERINFO, nullptr); cl_maxsoldiersperteam = cgi->Cvar_Get("sv_maxsoldiersperteam", "4", CVAR_ARCHIVE | CVAR_SERVERINFO, "How many soldiers may one team have"); cl_maxsoldiersperplayer = cgi->Cvar_Get("sv_maxsoldiersperplayer", DOUBLEQUOTE(MAX_ACTIVETEAM), CVAR_ARCHIVE | CVAR_SERVERINFO, "How many soldiers one player is able to control in a given team"); cl_roundtimelimit = cgi->Cvar_Get("sv_roundtimelimit", "90", CVAR_ARCHIVE | CVAR_SERVERINFO, "Timelimit in seconds for multiplayer rounds"); cgi->Cmd_TableAddList(mpCallbacks); cgi->Cmd_AddParamCompleteFunction("connect", GAME_MP_CompleteNetworkAddress); cgi->Cmd_AddParamCompleteFunction("rcon", GAME_MP_CompleteNetworkAddress); cl_maxsoldiersperteam->modified = false; cl_maxsoldiersperplayer->modified = false; }
/** * @brief Responds with short info for broadcast scans * @note The second parameter should be the current protocol version number. * @note Only a short server description - the user can determine whether he is * interested in a full status * @sa CL_ParseStatusMessage * @sa CL_ProcessPingReply */ static void SVC_Info (struct net_stream* s) { if (SVC_RateLimitAddress(*s)) { Com_DPrintf(DEBUG_SERVER, "SVC_Info: rate limit from %s exceeded, dropping request\n", NET_StreamToString(s)); return; } /* Allow getinfo to be DoSed relatively easily, but prevent excess outbound bandwidth usage when being flooded inbound */ if (SVC_RateLimit(&outboundLeakyBucket)) { Com_DPrintf(DEBUG_SERVER, "SVC_Info: rate limit exceeded, dropping request\n"); return; } if (sv_maxclients->integer == 1) { Com_DPrintf(DEBUG_SERVER, "Ignore info string in singleplayer mode\n"); return; /* ignore in single player */ } const int version = atoi(Cmd_Argv(1)); if (version != PROTOCOL_VERSION) { char string[MAX_VAR]; Com_sprintf(string, sizeof(string), "%s: wrong version (client: %i, host: %i)\n", sv_hostname->string, version, PROTOCOL_VERSION); NET_OOB_Printf(s, SV_CMD_PRINT "\n%s", string); return; } int count = 0; client_t* cl = nullptr; while ((cl = SV_GetNextClient(cl)) != nullptr) if (cl->state >= cs_spawning) count++; char infostring[MAX_INFO_STRING]; infostring[0] = '\0'; Info_SetValueForKey(infostring, sizeof(infostring), "sv_protocol", DOUBLEQUOTE(PROTOCOL_VERSION)); Info_SetValueForKey(infostring, sizeof(infostring), "sv_hostname", sv_hostname->string); Info_SetValueForKey(infostring, sizeof(infostring), "sv_dedicated", sv_dedicated->string); Info_SetValueForKey(infostring, sizeof(infostring), "sv_gametype", sv_gametype->string); Info_SetValueForKey(infostring, sizeof(infostring), "sv_mapname", sv->name); Info_SetValueForKeyAsInteger(infostring, sizeof(infostring), "clients", count); Info_SetValueForKey(infostring, sizeof(infostring), "sv_maxclients", sv_maxclients->string); Info_SetValueForKey(infostring, sizeof(infostring), "sv_version", UFO_VERSION); NET_OOB_Printf(s, SV_CMD_INFO "\n%s", infostring); }
static void CL_Connect_f (void) { char server[MAX_VAR]; char serverport[16]; if (!selectedServer && cgi->Cmd_Argc() != 2 && cgi->Cmd_Argc() != 3) { cgi->Com_Printf("Usage: %s <server> [<port>]\n", cgi->Cmd_Argv(0)); return; } if (cgi->Cmd_Argc() == 2) { Q_strncpyz(server, cgi->Cmd_Argv(1), sizeof(server)); Q_strncpyz(serverport, DOUBLEQUOTE(PORT_SERVER), sizeof(serverport)); } else if (cgi->Cmd_Argc() == 3) { Q_strncpyz(server, cgi->Cmd_Argv(1), sizeof(server)); Q_strncpyz(serverport, cgi->Cmd_Argv(2), sizeof(serverport)); } else { assert(selectedServer); Q_strncpyz(server, selectedServer->node, sizeof(server)); Q_strncpyz(serverport, selectedServer->service, sizeof(serverport)); } if (cgi->GAME_IsTeamEmpty() && !cgi->GAME_LoadDefaultTeam(qtrue)) { cgi->UI_Popup(_("Error"), "%s", _("Assemble a team first")); return; } if (cgi->Cvar_GetInteger("mn_server_need_password")) { cgi->UI_PushWindow("serverpassword", NULL, NULL); return; } /* if running a local server, kill it and reissue */ cgi->SV_Shutdown("Server quit.", qfalse); cgi->CL_Disconnect(); cgi->GAME_SetServerInfo(server, serverport); cgi->CL_SetClientState(ca_connecting); cgi->UI_InitStack(NULL, "multiplayerInGame", qfalse, qfalse); }
/** * @brief Responds with short info for broadcast scans * @note The second parameter should be the current protocol version number. * @note Only a short server description - the user can determine whether he is * interested in a full status * @sa CL_ParseStatusMessage * @sa CL_ProcessPingReply */ static void SVC_Info (struct net_stream *s) { int version; if (sv_maxclients->integer == 1) { Com_DPrintf(DEBUG_SERVER, "Ignore info string in singleplayer mode\n"); return; /* ignore in single player */ } version = atoi(Cmd_Argv(1)); if (version != PROTOCOL_VERSION) { char string[MAX_VAR]; Com_sprintf(string, sizeof(string), "%s: wrong version (client: %i, host: %i)\n", sv_hostname->string, version, PROTOCOL_VERSION); NET_OOB_Printf(s, "print\n%s", string); } else { client_t *cl; char infostring[MAX_INFO_STRING]; int count = 0; cl = NULL; while ((cl = SV_GetNextClient(cl)) != NULL) if (cl->state >= cs_spawning) count++; infostring[0] = '\0'; Info_SetValueForKey(infostring, sizeof(infostring), "sv_protocol", DOUBLEQUOTE(PROTOCOL_VERSION)); Info_SetValueForKey(infostring, sizeof(infostring), "sv_hostname", sv_hostname->string); Info_SetValueForKey(infostring, sizeof(infostring), "sv_dedicated", sv_dedicated->string); Info_SetValueForKey(infostring, sizeof(infostring), "sv_gametype", sv_gametype->string); Info_SetValueForKey(infostring, sizeof(infostring), "sv_mapname", sv->name); Info_SetValueForKeyAsInteger(infostring, sizeof(infostring), "clients", count); Info_SetValueForKey(infostring, sizeof(infostring), "sv_maxclients", sv_maxclients->string); Info_SetValueForKey(infostring, sizeof(infostring), "sv_version", UFO_VERSION); NET_OOB_Printf(s, "info\n%s", infostring); } }
/** * Send the rest of the command line over as * an unconnected command. */ static void CL_Rcon_f (void) { char message[MAX_STRING_CHARS]; if (cgi->Cmd_Argc() < 2) { cgi->Com_Printf("Usage: %s <command>\n", cgi->Cmd_Argv(0)); return; } if (!rcon_client_password->string) { cgi->Com_Printf("You must set 'rcon_password' before issuing an rcon command.\n"); return; } Com_sprintf(message, sizeof(message), "rcon %s %s", rcon_client_password->string, cgi->Cmd_Args()); if (cgi->CL_GetClientState() >= ca_connected) { cgi->NET_OOB_Printf2("%s", message); } else if (rcon_address->string) { const char *port; struct net_stream *s; if (strstr(rcon_address->string, ":")) port = strstr(rcon_address->string, ":") + 1; else port = DOUBLEQUOTE(PORT_SERVER); s = cgi->NET_Connect(rcon_address->string, port, NULL); if (s) { cgi->NET_OOB_Printf(s, "%s", message); cgi->NET_StreamSetCallback(s, &CL_RconCallback); } } else { cgi->Com_Printf("You are not connected to any server\n"); } }
bool Irc_Proto_Connect(const char *host, unsigned short port) { const bool status = Irc_Net_Connect(host, port, &irc_sock); if (!status) { if (!irc_messageBucketSize) { irc_messageBucketSize = IRC_IMPORT.Cvar_Get("irc_messageBucketSize", DOUBLEQUOTE(IRC_DEFAULT_MESSAGE_BUCKET_SIZE), CVAR_ARCHIVE); irc_messageBucketBurst = IRC_IMPORT.Cvar_Get("irc_messageBucketBurst", DOUBLEQUOTE(IRC_DEFAULT_MESSAGE_BUCKET_BURST), CVAR_ARCHIVE); irc_messageBucketRate = IRC_IMPORT.Cvar_Get("irc_messageBucketRate", DOUBLEQUOTE(IRC_DEFAULT_MESSAGE_BUCKET_RATE), CVAR_ARCHIVE); irc_characterBucketSize = IRC_IMPORT.Cvar_Get("irc_characterBucketSize", DOUBLEQUOTE(IRC_DEFAULT_CHARACTER_BUCKET_SIZE), CVAR_ARCHIVE); irc_characterBucketBurst = IRC_IMPORT.Cvar_Get("irc_characterBucketBurst", DOUBLEQUOTE(IRC_DEFAULT_CHARACTER_BUCKET_BURST), CVAR_ARCHIVE); irc_characterBucketRate = IRC_IMPORT.Cvar_Get("irc_characterBucketRate", DOUBLEQUOTE(IRC_DEFAULT_CHARACTER_BUCKET_RATE), CVAR_ARCHIVE); } irc_bucket.first_msg = NULL; irc_bucket.message_size = 0; irc_bucket.character_size = 0; irc_bucket.last_refill = IRC_IMPORT.Sys_Microseconds(); irc_bucket.message_token = Cvar_GetFloatValue(irc_messageBucketBurst); irc_bucket.character_token = Cvar_GetFloatValue(irc_characterBucketBurst); } return status; }
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(); }
/** * @brief Init function * @sa Com_ParseScripts * @sa Qcommon_Shutdown * @sa Sys_Init * @sa CL_Init */ void Qcommon_Init (int argc, char** argv) { logfile_active = nullptr; developer = nullptr; Sys_InitSignals(); /* random seed */ Com_SetRandomSeed(time(nullptr)); com_aliasSysPool = Mem_CreatePool("Common: Alias system for commands and enums"); com_cmdSysPool = Mem_CreatePool("Common: Command system"); com_cmodelSysPool = Mem_CreatePool("Common: Collision model"); com_cvarSysPool = Mem_CreatePool("Common: Cvar system"); com_fileSysPool = Mem_CreatePool("Common: File system"); com_genericPool = Mem_CreatePool("Generic"); com_networkPool = Mem_CreatePool("Network"); try { OBJZERO(csi); /* prepare enough of the subsystems to handle * cvar and command buffer management */ Com_InitArgv(argc, argv); Swap_Init(); Cbuf_Init(); Cmd_Init(); Cvar_Init(); uploadcrashdump = Cvar_Get("uploadcrashdump", "1", 0, "upload crashdumps to the developers"); Key_Init(); /* we need to add the early commands twice, because * a basedir needs to be set before executing * config files, but we want other parms to override * the settings of the config files */ Cbuf_AddEarlyCommands(false); Cbuf_Execute(); FS_InitFilesystem(true); Cbuf_AddText("exec default.cfg\n"); #ifdef DEDICATED_ONLY Cbuf_AddText("exec dedconfig.cfg\n"); #else Cbuf_AddText("exec config.cfg\n"); #endif Cbuf_AddEarlyCommands(true); Cbuf_Execute(); Com_SetRenderModified(false); Com_SetUserinfoModified(false); /* init commands and vars */ Cmd_AddCommand("saveconfig", Com_WriteConfig_f, "Write the configuration to file"); Cmd_AddCommand("gametypelist", Com_GameTypeList_f, "List all available multiplayer game types"); #ifdef DEBUG Cmd_AddCommand("debug_help", Com_DebugHelp_f, "Show some debugging help"); Cmd_AddCommand("debug_error", Com_DebugError_f, "Just throw a fatal error to test error shutdown procedures"); #endif Cmd_AddCommand("setdeveloper", Com_DeveloperSet_f, "Set the developer cvar to only get the debug output you want"); developer = Cvar_Get("developer", "0", 0, "Activate developer output to logfile and gameconsole"); #ifdef DEBUG logfile_active = Cvar_Get("logfile", "2", 0, "0 = deactivate logfile, 1 = write normal logfile, 2 = flush on every new line, 3 = always append to existing file"); #else logfile_active = Cvar_Get("logfile", "1", 0, "0 = deactivate logfile, 1 = write normal logfile, 2 = flush on every new line, 3 = always append to existing file"); #endif sv_gametype = Cvar_Get("sv_gametype", "fight1on1", CVAR_ARCHIVE | CVAR_SERVERINFO, "Sets the multiplayer gametype - see gametypelist command for a list of all gametypes"); http_proxy = Cvar_Get("http_proxy", "", CVAR_ARCHIVE, "Use this proxy for http transfers"); http_timeout = Cvar_Get("http_timeout", "3", CVAR_ARCHIVE, "Http connection and read timeout"); port = Cvar_Get("port", DOUBLEQUOTE(PORT_SERVER), CVAR_NOSET); masterserver_url = Cvar_Get("masterserver_url", MASTER_SERVER, CVAR_ARCHIVE, "URL of UFO:AI masterserver"); #ifdef DEDICATED_ONLY sv_dedicated = Cvar_Get("sv_dedicated", "1", CVAR_SERVERINFO | CVAR_NOSET, "Is this a dedicated server?"); /* don't allow to override this from commandline of config */ Cvar_ForceSet("sv_dedicated", "1"); #else sv_dedicated = Cvar_Get("sv_dedicated", "0", CVAR_SERVERINFO | CVAR_NOSET, "Is this a dedicated server?"); /* set this to false for client - otherwise Qcommon_Frame would set the initial values to multiplayer */ sv_gametype->modified = false; s_language = Cvar_Get("s_language", "", CVAR_ARCHIVE, "Game language - full language string e.g. en_EN.UTF-8"); s_language->modified = false; cl_maxfps = Cvar_Get("cl_maxfps", "50", CVAR_ARCHIVE); Cvar_SetCheckFunction("cl_maxfps", Com_CvarCheckMaxFPS); #endif // 5 is an i7 with a medium gfx-card // 3 dual core with 2 GB // 2 EeePc with 1 GB // 1 smartphone const char* hwclassVal = "5"; #ifdef __ANDROID__ /** get the hardware class of the machine we are running on. */ hwclassVal = "1"; #endif hwclass = Cvar_Get("hwclass", hwclassVal, 0, "Defines the hardware class of this machine. 1 is the lowest, 5 is the highest."); const char* s = va("UFO: Alien Invasion %s %s %s %s", UFO_VERSION, CPUSTRING, __DATE__, BUILDSTRING); Cvar_Get("version", s, CVAR_NOSET, "Full version string"); Cvar_Get("ver", UFO_VERSION, CVAR_SERVERINFO | CVAR_NOSET, "Version number"); if (sv_dedicated->integer) Cmd_AddCommand("quit", Com_Quit, "Quits the game"); Mem_Init(); Sys_Init(); NET_Init(); #ifndef NO_HTTP curl_global_init(CURL_GLOBAL_NOTHING); Com_Printf("%s initialized.\n", curl_version()); #endif SV_Init(); /* e.g. init the client hunk that is used in script parsing */ CL_Init(); Com_ParseScripts(sv_dedicated->integer); #ifndef DEDICATED_ONLY Cbuf_AddText("exec keys.cfg\n"); #endif if (!sv_dedicated->integer) Cbuf_AddText("init\n"); else Cbuf_AddText("dedicated_start\n"); Cbuf_Execute(); FS_ExecAutoexec(); /* add + commands from command line * if the user didn't give any commands, run default action */ if (Cbuf_AddLateCommands()) { /* the user asked for something explicit * so drop the loading plaque */ SCR_EndLoadingPlaque(); } const cvar_t* com_pipefile = Cvar_Get("com_pipefile", "", CVAR_ARCHIVE, "Filename of the pipe that is used to send commands to the game"); if (com_pipefile->string[0] != '\0') { FS_CreateOpenPipeFile(com_pipefile->string, &pipefile); } CL_InitAfter(); /* Check memory integrity */ Mem_CheckGlobalIntegrity(); #ifndef DEDICATED_ONLY if (!sv_dedicated->integer) { Schedule_Timer(cl_maxfps, &CL_Frame, nullptr, nullptr); Schedule_Timer(Cvar_Get("cl_slowfreq", "10", 0, nullptr), &CL_SlowFrame, nullptr, nullptr); /* now hide the console */ Sys_ShowConsole(false); } #endif Schedule_Timer(Cvar_Get("sv_freq", "10", CVAR_NOSET, nullptr), &SV_Frame, nullptr, nullptr); /** @todo This line wants to be removed */ Schedule_Timer(Cvar_Get("cbuf_freq", "10", 0, nullptr), &Cbuf_Execute_timer, nullptr, nullptr); Com_Printf("====== UFO Initialized ======\n"); Com_Printf("=============================\n"); } catch (comDrop_t const&) { Sys_Error("Error during initialization"); } }
/** * @brief This will be called when the game library is first loaded * @note only happens when a new game/map is started */ static void G_Init (void) { gi.DPrintf("==== InitGame ====\n"); /* noset vars */ sv_dedicated = gi.Cvar_Get("sv_dedicated", "0", CVAR_SERVERINFO | CVAR_NOSET, "Is this a dedicated server?"); /* latched vars */ sv_cheats = gi.Cvar_Get("sv_cheats", "0", CVAR_SERVERINFO | CVAR_LATCH, "Activate cheats"); gi.Cvar_Get("gamename", GAMEVERSION, CVAR_SERVERINFO | CVAR_LATCH, nullptr); gi.Cvar_Get("gamedate", __DATE__, CVAR_SERVERINFO | CVAR_LATCH, nullptr); developer = gi.Cvar_Get("developer", "0", 0, "Print out a lot of developer debug messages - useful to track down bugs"); logstats = gi.Cvar_Get("logstats", "1", CVAR_ARCHIVE, "Server logfile output for kills"); /* max. players per team (original quake) */ sv_maxplayersperteam = gi.Cvar_Get("sv_maxplayersperteam", "8", CVAR_SERVERINFO | CVAR_LATCH, "How many players (humans) may a team have"); /* max. soldiers per team */ sv_maxsoldiersperteam = gi.Cvar_Get("sv_maxsoldiersperteam", "4", CVAR_ARCHIVE | CVAR_SERVERINFO, "How many soldiers may one team have"); /* max soldiers per player */ sv_maxsoldiersperplayer = gi.Cvar_Get("sv_maxsoldiersperplayer", DOUBLEQUOTE(MAX_ACTIVETEAM), CVAR_ARCHIVE | CVAR_SERVERINFO, "How many soldiers one player is able to control in a given team"); /* enable moralestates in multiplayer */ sv_enablemorale = gi.Cvar_Get("sv_enablemorale", "1", CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_LATCH, "Enable morale behaviour for actors"); sv_roundtimelimit = gi.Cvar_Get("sv_roundtimelimit", "90", CVAR_ARCHIVE | CVAR_SERVERINFO, "Timelimit in seconds for multiplayer rounds"); sv_roundtimelimit->modified = false; sv_maxentities = gi.Cvar_Get("sv_maxentities", "1024", CVAR_LATCH, nullptr); sv_maxteams = gi.Cvar_Get("sv_maxteams", "2", CVAR_SERVERINFO, "How many teams for current running map"); sv_maxteams->modified = false; /* change anytime vars */ password = gi.Cvar_Get("password", "", CVAR_USERINFO, nullptr); sv_needpass = gi.Cvar_Get("sv_needpass", "0", CVAR_SERVERINFO, nullptr); sv_filterban = gi.Cvar_Get("sv_filterban", "1", 0, nullptr); sv_ai = gi.Cvar_Get("sv_ai", "1", 0, "Activate or deativate the ai"); sv_teamplay = gi.Cvar_Get("sv_teamplay", "0", CVAR_ARCHIVE | CVAR_LATCH | CVAR_SERVERINFO, "Is teamplay activated? see sv_maxclients, sv_maxplayersperteam, sv_maxsoldiersperteam and sv_maxsoldiersperplayer"); /* how many connected clients */ sv_maxclients = gi.Cvar_Get("sv_maxclients", "1", CVAR_SERVERINFO, "If sv_maxclients is 1 we are in singleplayer - otherwise we are mutliplayer mode (see sv_teamplay)"); sv_shot_origin = gi.Cvar_Get("sv_shot_origin", "8", 0, "Assumed distance of muzzle from model"); sv_send_edicts = gi.Cvar_Get("sv_send_edicts", "0", CVAR_ARCHIVE | CVAR_CHEAT, "Send server side edicts for client display like triggers"); sv_hurtaliens = gi.Cvar_Get("sv_hurtaliens", "0", CVAR_SERVERINFO, "Spawn hurt aliens"); ai_alienteam = gi.Cvar_Get("ai_alienteam", "ortnok", 0, "Alien team"); ai_civilianteam = gi.Cvar_Get("ai_civilianteam", "europe", 0, "Civilian team"); /* this cvar is set in singleplayer via campaign definition */ ai_equipment = gi.Cvar_Get("ai_equipment", "multiplayer_alien", 0, "Initial equipment definition for aliens"); /* aliens in singleplayer (can differ each mission) */ ai_singleplayeraliens = gi.Cvar_Get("ai_singleplayeraliens", "30", 0, "How many aliens in this battle (singleplayer)"); /* civilians for singleplayer */ ai_numcivilians = gi.Cvar_Get("ai_numcivilians", "10", 0, "How many civilians in this battle"); /* aliens in multiplayer */ ai_multiplayeraliens = gi.Cvar_Get("ai_multiplayeraliens", "8", CVAR_ARCHIVE, "How many (ai controlled) actors in this battle (multiplayer)"); mob_death = gi.Cvar_Get("mob_death", "10", CVAR_LATCH|CVAR_NOSET, nullptr); mob_wound = gi.Cvar_Get("mob_wound", "0.1", CVAR_LATCH|CVAR_NOSET, nullptr); mob_shoot = gi.Cvar_Get("mob_shoot", "0.1", CVAR_LATCH|CVAR_NOSET, nullptr); mof_watching = gi.Cvar_Get("mof_watching", "1.7", CVAR_LATCH|CVAR_NOSET, nullptr); mof_teamkill = gi.Cvar_Get("mof_teamkill", "2.0", CVAR_LATCH|CVAR_NOSET, nullptr); mof_civilian = gi.Cvar_Get("mof_civilian", "0.3", CVAR_LATCH|CVAR_NOSET, nullptr); mof_enemy = gi.Cvar_Get("mof_ememy", "0.5", CVAR_LATCH|CVAR_NOSET, nullptr); mor_pain = gi.Cvar_Get("mof_pain", "3.6", CVAR_LATCH|CVAR_NOSET, nullptr); /* everyone gets this times morale damage */ mor_default = gi.Cvar_Get("mor_default", "0.3", CVAR_LATCH|CVAR_NOSET, "Everyone gets this times morale damage"); /* at this distance the following two get halved (exponential scale) */ mor_distance = gi.Cvar_Get("mor_distance", "120", CVAR_LATCH|CVAR_NOSET, "At this distance the following two get halved (exponential scale)"); /* at this distance the following two get halved (exponential scale) */ mor_victim = gi.Cvar_Get("mor_victim", "0.7", CVAR_LATCH|CVAR_NOSET, "At this distance the following two get halved (exponential scale)"); /* at this distance the following two get halved (exponential scale) */ mor_attacker = gi.Cvar_Get("mor_attacker", "0.3", CVAR_LATCH|CVAR_NOSET, "At this distance the following two get halved (exponential scale)"); /* how much the morale depends on the size of the damaged team */ mon_teamfactor = gi.Cvar_Get("mon_teamfactor", "0.6", CVAR_LATCH|CVAR_NOSET, "How much the morale depends on the size of the damaged team"); mor_regeneration = gi.Cvar_Get("mor_regeneration", "15", CVAR_LATCH|CVAR_NOSET, nullptr); mor_shaken = gi.Cvar_Get("mor_shaken", "50", CVAR_LATCH|CVAR_NOSET, nullptr); mor_panic = gi.Cvar_Get("mor_panic", "30", CVAR_LATCH|CVAR_NOSET, nullptr); mor_brave = gi.Cvar_Get("mor_brave", "85", CVAR_LATCH|CVAR_NOSET, nullptr); m_sanity = gi.Cvar_Get("m_sanity", "1.0", CVAR_LATCH|CVAR_NOSET, nullptr); m_rage = gi.Cvar_Get("m_rage", "0.6", CVAR_LATCH|CVAR_NOSET, nullptr); m_rage_stop = gi.Cvar_Get("m_rage_stop", "2.0", CVAR_LATCH|CVAR_NOSET, nullptr); m_panic_stop = gi.Cvar_Get("m_panic_stop", "1.0", CVAR_LATCH|CVAR_NOSET, nullptr); g_endlessaliens = gi.Cvar_Get("g_endlessaliens", "0", CVAR_LATCH|CVAR_SERVERINFO, "Spawn endless aliens"); g_ailua = gi.Cvar_Get("g_ailua", "0", 0, "Activate or deactivate the LUA AI"); g_aihumans = gi.Cvar_Get("g_aihumans", "0", CVAR_DEVELOPER, "Activate or deactivate the ai for human actors"); g_aidebug = gi.Cvar_Get("g_aidebug", "0", CVAR_DEVELOPER|CVAR_CHEAT, "All AI actors are visible"); g_drawtraces = gi.Cvar_Get("g_drawtraces", "0", CVAR_DEVELOPER, "All traces will be rendered"); g_nodamage = gi.Cvar_Get("g_nodamage", "0", CVAR_DEVELOPER|CVAR_CHEAT, "No damage in developer mode"); g_notu = gi.Cvar_Get("g_notu", "0", CVAR_DEVELOPER|CVAR_CHEAT, "No TU costs while performing any action"); g_actorspeed = gi.Cvar_Get("g_actorspeed", "1.0", CVAR_ARCHIVE|CVAR_SERVERINFO, "Moving speed of the actor"); g_lastseen = gi.Cvar_Get("g_lastseen", "20", CVAR_ARCHIVE|CVAR_SERVERINFO, "Quit the match if no player was seen in this amount of rounds"); g_nospawn = gi.Cvar_Get("g_nospawn", "0", CVAR_DEVELOPER|CVAR_CHEAT, "Do not spawn a soldier"); /* flood control */ flood_msgs = gi.Cvar_Get("flood_msgs", "4", 0, nullptr); flood_persecond = gi.Cvar_Get("flood_persecond", "4", 0, nullptr); flood_waitdelay = gi.Cvar_Get("flood_waitdelay", "10", 0, "Delay until someone is unlocked from talking again"); g_difficulty = gi.Cvar_Get("g_difficulty", "0", CVAR_NOSET, "Singleplayer difficulty level"); game.sv_maxentities = sv_maxentities->integer; game.sv_maxplayersperteam = sv_maxplayersperteam->integer; /* initialize the entity storage */ globals.edicts = G_EdictsConstruct(); globals.max_edicts = game.sv_maxentities; globals.num_edicts = game.sv_maxplayersperteam; /* initialize all players for this game */ /* game.sv_maxplayersperteam for human controlled players * + game.sv_maxplayer for ai */ game.players = static_cast<player_t*>(G_TagMalloc(game.sv_maxplayersperteam * 2 * sizeof(game.players[0]), TAG_GAME)); globals.players = game.players; globals.maxplayersperteam = game.sv_maxplayersperteam; /* init csi and inventory */ INVSH_InitCSI(gi.csi); game.invi.initInventory("game", gi.csi, &inventoryImport); if (logstats->integer) logstatsfile = gi.Sys_Fopen(va("%s/stats.log", gi.FS_Gamedir()), "a"); else logstatsfile = nullptr; AI_Init(); AIL_Init(); }