/** * @brief Sets a cvar from console with the given flags * @note flags are: * CVAR_ARCHIVE These cvars will be saved. * CVAR_USERINFO Added to userinfo when changed. * CVAR_SERVERINFO Added to serverinfo when changed. * CVAR_NOSET Don't allow change from console at all but can be set from the command line. * CVAR_LATCH Save changes until server restart. * * @param varName Which cvar * @param value Which value for the cvar * @param flags which flags * @sa Cvar_Set_f */ cvar_t* Cvar_FullSet (const char* varName, const char* value, int flags) { cvar_t* var; if (!value) return nullptr; var = Cvar_FindVar(varName); /* create it */ if (!var) return Cvar_GetOrCreate(varName, value, flags); var->modified = true; /* transmit at next opportunity */ if (var->flags & CVAR_USERINFO) Com_SetUserinfoModified(true); Mem_Free(var->oldString); /* free the old value string */ var->oldString = var->string; var->string = Mem_PoolStrDup(value, com_cvarSysPool, 0); var->value = atof(var->string); var->integer = atoi(var->string); var->flags = flags; return var; }
/** * @note Only call @c CL_Connect if there is no connection yet (@c cls.netStream is @c nullptr) * @sa CL_Disconnect * @sa CL_SendChangedUserinfos */ static void CL_Connect (void) { Com_SetUserinfoModified(false); assert(!cls.netStream); if (cls.servername[0] != '\0') { assert(cls.serverport[0] != '\0'); Com_Printf("Connecting to %s %s...\n", cls.servername, cls.serverport); cls.netStream = NET_Connect(cls.servername, cls.serverport, CL_FreeClientStream); } else { Com_Printf("Connecting to localhost...\n"); cls.netStream = NET_ConnectToLoopBack(CL_FreeClientStream); } if (cls.netStream) { char info[MAX_INFO_STRING]; NET_OOB_Printf(cls.netStream, SV_CMD_CONNECT " %i \"%s\"\n", PROTOCOL_VERSION, Cvar_Userinfo(info, sizeof(info))); cls.connectTime = CL_Milliseconds(); } else { if (cls.servername[0] != '\0') { assert(cls.serverport[0]); Com_Printf("Could not connect to %s %s\n", cls.servername, cls.serverport); } else { Com_Printf("Could not connect to localhost\n"); } } }
/** * @brief Send the userinfo to the server (and to all other clients) * when they changed (CVAR_USERINFO) * @sa CL_Connect */ static void CL_SendChangedUserinfos (void) { /* send a userinfo update if needed */ if (cls.state < ca_connected) return; if (!Com_IsUserinfoModified()) return; char info[MAX_INFO_STRING]; const char* userInfo = Cvar_Userinfo(info, sizeof(info)); dbuffer msg(strlen(userInfo) + 2); NET_WriteByte(&msg, clc_userinfo); NET_WriteString(&msg, userInfo); NET_WriteMsg(cls.netStream, msg); Com_SetUserinfoModified(false); }
/** * @brief Sets a cvar values * Handles write protection and latched cvars as expected * @param[in] varName Which cvar * @param[in] value Set the cvar to the value specified by 'value' * @param[in] force Force the update of the cvar */ static cvar_t* Cvar_Set2 (const char* varName, const char* value, bool force) { cvar_t* var; if (!value) return nullptr; var = Cvar_FindVar(varName); /* create it */ if (!var) return Cvar_GetOrCreate(varName, value); if (var->flags & (CVAR_USERINFO | CVAR_SERVERINFO)) { if (!Cvar_InfoValidate(value)) { Com_Printf("invalid info cvar value '%s' of cvar '%s'\n", value, varName); return var; } } if (!force) { if (var->flags & CVAR_NOSET) { Com_Printf("%s is write protected.\n", varName); return var; } #ifndef DEBUG if (var->flags & CVAR_DEVELOPER) { Com_Printf("%s is a developer cvar.\n", varName); return var; } #endif if (var->flags & CVAR_LATCH) { if (var->latchedString) { if (Q_streq(value, var->latchedString)) return var; Mem_Free(var->latchedString); var->latchedString = nullptr; } else { if (Q_streq(value, var->string)) return var; } /* if we are running a server */ if (Com_ServerState()) { Com_Printf("%s will be changed for next game.\n", varName); var->latchedString = Mem_PoolStrDup(value, com_cvarSysPool, 0); } else { Mem_Free(var->oldString); var->oldString = var->string; var->string = Mem_PoolStrDup(value, com_cvarSysPool, 0); var->value = atof(var->string); var->integer = atoi(var->string); } if (var->check && var->check(var)) Com_Printf("Invalid value for cvar %s\n", varName); return var; } } else { Mem_Free(var->latchedString); var->latchedString = nullptr; } if (Q_streq(value, var->string)) return var; /* not changed */ if (var->flags & CVAR_R_MASK) Com_SetRenderModified(true); Mem_Free(var->oldString); /* free the old value string */ var->oldString = var->string; var->modified = true; if (var->flags & CVAR_USERINFO) Com_SetUserinfoModified(true); /* transmit at next opportunity */ var->string = Mem_PoolStrDup(value, com_cvarSysPool, 0); var->value = atof(var->string); var->integer = atoi(var->string); if (var->check && var->check(var)) { Com_Printf("Invalid value for cvar %s\n", varName); return var; } Cvar_ExecuteChangeListener(var); return var; }
/** * @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"); } }