/* ============ Cvar_Get If the variable already exists, the value will not be set unless CVAR_ROM The flags will be or'ed in if the variable exists. ============ */ cvar_t *Cvar_Get(const char* name, const char* value, int flags) { Cvar::Register(nullptr, name, "--", flags, value); return Cvar_FindVar(name); }
/* ============ Cvar_VariableValue ============ */ float Cvar_VariableValue(const char* name) { cvar_t* var = Cvar_FindVar(name); return var ? var->value : 0.0f; }
static qsocket_t *_Datagram_CheckNewConnections (void) { struct qsockaddr clientaddr; struct qsockaddr newaddr; int newsock; int acceptsock; qsocket_t *sock; qsocket_t *s; int len; int command; int control; int ret; acceptsock = dfunc.CheckNewConnections(); if (acceptsock == -1) return NULL; SZ_Clear(&net_message); len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr); if (len < sizeof(int)) return NULL; net_message.cursize = len; MSG_BeginReading (); control = BigLong(*((int *)net_message.data)); MSG_ReadLong(); if (control == -1) return NULL; if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL) return NULL; if ((control & NETFLAG_LENGTH_MASK) != len) return NULL; command = MSG_ReadByte(); if (command == CCREQ_SERVER_INFO) { if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0) return NULL; SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); MSG_WriteByte(&net_message, CCREP_SERVER_INFO); dfunc.GetSocketAddr(acceptsock, &newaddr); MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr)); MSG_WriteString(&net_message, hostname.string); MSG_WriteString(&net_message, sv.name); MSG_WriteByte(&net_message, net_activeconnections); MSG_WriteByte(&net_message, svs.maxclients); MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION); *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); SZ_Clear(&net_message); return NULL; } if (command == CCREQ_PLAYER_INFO) { int playerNumber; int activeNumber; int clientNumber; client_t *client; playerNumber = MSG_ReadByte(); activeNumber = -1; for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++) { if (client->active) { activeNumber++; if (activeNumber == playerNumber) break; } } if (clientNumber == svs.maxclients) return NULL; SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); MSG_WriteByte(&net_message, CCREP_PLAYER_INFO); MSG_WriteByte(&net_message, playerNumber); MSG_WriteString(&net_message, client->name); MSG_WriteLong(&net_message, client->colors); MSG_WriteLong(&net_message, (int)client->edict->v.frags); MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime)); MSG_WriteString(&net_message, client->netconnection->address); *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); SZ_Clear(&net_message); return NULL; } if (command == CCREQ_RULE_INFO) { char *prevCvarName; cvar_t *var; // find the search start location prevCvarName = MSG_ReadString(); if (*prevCvarName) { var = Cvar_FindVar (prevCvarName); if (!var) return NULL; var = var->next; } else var = cvar_vars; // search for the next server cvar while (var) { if (var->server) break; var = var->next; } // send the response SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); MSG_WriteByte(&net_message, CCREP_RULE_INFO); if (var) { MSG_WriteString(&net_message, var->name); MSG_WriteString(&net_message, var->string); } *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); SZ_Clear(&net_message); return NULL; } if (command != CCREQ_CONNECT) return NULL; if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0) return NULL; if (MSG_ReadByte() != NET_PROTOCOL_VERSION) { SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); MSG_WriteByte(&net_message, CCREP_REJECT); MSG_WriteString(&net_message, "Incompatible version.\n"); *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); SZ_Clear(&net_message); return NULL; } #ifdef BAN_TEST // check for a ban if (clientaddr.sa_family == AF_INET) { unsigned long testAddr; testAddr = ((struct sockaddr_in *)&clientaddr)->sin_addr.s_addr; if ((testAddr & banMask) == banAddr) { SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); MSG_WriteByte(&net_message, CCREP_REJECT); MSG_WriteString(&net_message, "You have been banned.\n"); *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); SZ_Clear(&net_message); return NULL; } } #endif // see if this guy is already connected for (s = net_activeSockets; s; s = s->next) { if (s->driver != net_driverlevel) continue; ret = dfunc.AddrCompare(&clientaddr, &s->addr); if (ret >= 0) { // is this a duplicate connection reqeust? if (ret == 0 && net_time - s->connecttime < 2.0) { // yes, so send a duplicate reply SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); MSG_WriteByte(&net_message, CCREP_ACCEPT); dfunc.GetSocketAddr(s->socket, &newaddr); MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr)); *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); SZ_Clear(&net_message); return NULL; } // it's somebody coming back in from a crash/disconnect // so close the old qsocket and let their retry get them back in NET_Close(s); return NULL; } } // allocate a QSocket sock = NET_NewQSocket (); if (sock == NULL) { // no room; try to let him know SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); MSG_WriteByte(&net_message, CCREP_REJECT); MSG_WriteString(&net_message, "Server is full.\n"); *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); SZ_Clear(&net_message); return NULL; } // allocate a network socket newsock = dfunc.OpenSocket(0); if (newsock == -1) { NET_FreeQSocket(sock); return NULL; } // connect to the client if (dfunc.Connect (newsock, &clientaddr) == -1) { dfunc.CloseSocket(newsock); NET_FreeQSocket(sock); return NULL; } // everything is allocated, just fill in the details sock->socket = newsock; sock->landriver = net_landriverlevel; sock->addr = clientaddr; Q_strcpy(sock->address, dfunc.AddrToString(&clientaddr)); // send him back the info about the server connection he has been allocated SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); MSG_WriteByte(&net_message, CCREP_ACCEPT); dfunc.GetSocketAddr(newsock, &newaddr); MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr)); // MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr)); *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); SZ_Clear(&net_message); return sock; }
/* ============ Cmd_ExecuteString A complete command line has been parsed, so try to execute it FIXME: this function is getting really messy... ============ */ void Cmd_ExecuteString (char *text) { cmd_function_t *cmd; cmd_alias_t *a; int key; static char buf[1024]; cbuf_t *inserttarget; #ifndef SERVERONLY char **s; #endif Cmd_ExpandString (text, buf); Cmd_TokenizeString (buf); // execute the command line if (!Cmd_Argc()) return; // no tokens inserttarget = &cbuf_main; #ifndef SERVERONLY if (cbuf_current == &cbuf_safe) inserttarget = &cbuf_safe; if (cbuf_current == &cbuf_svc) { if (CL_CheckServerCommand()) return; } #endif key = Com_HashKey (cmd_argv[0]); // check functions for (cmd=cmd_hash_array[key] ; cmd ; cmd=cmd->hash_next) { if (!Q_stricmp (cmd_argv[0], cmd->name)) { #ifndef SERVERONLY // special check for msg_trigger commands if (cbuf_current == &cbuf_safe) { for (s = safe_commands; *s; s++) { if (!Q_stricmp(cmd_argv[0], *s)) break; } if (!*s) { if (cl_warncmd.value || developer.value) Com_Printf ("\"%s\" cannot be used in message triggers\n", cmd_argv[0]); return; } } #endif if (cmd->function) cmd->function (); else Cmd_ForwardToServer (); return; } } // some bright guy decided to use "skill" as a mod command in Custom TF, sigh if (!strcmp(Cmd_Argv(0), "skill") && Cmd_Argc() == 1 && Cmd_FindAlias("skill")) goto checkaliases; // check cvars if (Cvar_Command()) return; // check alias checkaliases: for (a=cmd_alias_hash[key] ; a ; a=a->hash_next) { if (!Q_stricmp (cmd_argv[0], a->name)) { #ifndef SERVERONLY if (cbuf_current == &cbuf_svc) { Cbuf_AddText (a->value); Cbuf_AddText ("\n"); } else #endif { Cbuf_InsertTextEx (inserttarget, "\n"); // if the alias value is a command or cvar and // the alias is called with parameters, add them if (Cmd_Argc() > 1 && !strchr(a->value, ' ') && !strchr(a->value, '\t') && (Cvar_FindVar(a->value) || (Cmd_FindCommand(a->value) && a->value[0] != '+' && a->value[0] != '-'))) { Cbuf_InsertTextEx (inserttarget, Cmd_Args()); Cbuf_InsertTextEx (inserttarget, " "); } Cbuf_InsertTextEx (inserttarget, a->value); } return; } } if (Cmd_LegacyCommand()) return; if (!host_initialized && Cmd_Argc() > 1) { if (Cvar_CreateTempVar()) return; } #ifndef SERVERONLY if (cbuf_current != &cbuf_svc) #endif if (cl_warncmd.value || developer.value) Com_Printf ("Unknown command \"%s\"\n", Cmd_Argv(0)); }
cvar_t *Cvar_Set2(const char *var_name, const char *value, qboolean force) { cvar_t *var; //Com_DPrintf("Cvar_Set2: %s %s\n", var_name, value); if (!Cvar_ValidateString(var_name)) { Com_Printf("invalid cvar name string: %s\n", var_name); var_name = "BADNAME"; } var = Cvar_FindVar(var_name); if (!var) { if (!value) { return NULL; } // create it if (!force) { return Cvar_Get(var_name, value, CVAR_USER_CREATED); } else { return Cvar_Get(var_name, value, 0); } } if (!value) { value = var->resetString; } if (var->flags & CVAR_USERINFO) { char *cleaned = Cvar_ClearForeignCharacters(value); if (strcmp(value, cleaned)) { #ifdef DEDICATED Com_Printf(FOREIGN_MSG); #else Com_Printf("%s", CL_TranslateStringBuf(FOREIGN_MSG)); #endif Com_Printf("Using %s instead of %s\n", cleaned, value); return Cvar_Set2(var_name, cleaned, force); } } if ((var->flags & CVAR_LATCH) && var->latchedString) { if (!strcmp(value, var->string)) { Z_Free(var->latchedString); var->latchedString = NULL; return var; } if (!strcmp(value, var->latchedString)) { return var; } } else if (!strcmp(value, var->string)) { return var; } // note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo) cvar_modifiedFlags |= var->flags; if (!force) { // don't set unsafe variables when com_crashed is set if ((var->flags & CVAR_UNSAFE) && com_crashed != NULL && com_crashed->integer) { Com_Printf("%s is unsafe. Check com_crashed.\n", var_name); return var; } if (var->flags & CVAR_ROM) { Com_Printf("%s is read only.\n", var_name); return var; } if (var->flags & CVAR_INIT) { Com_Printf("%s is write protected.\n", var_name); return var; } if (var->flags & CVAR_LATCH) { if (var->latchedString) { if (strcmp(value, var->latchedString) == 0) { return var; } Z_Free(var->latchedString); } else { if (strcmp(value, var->string) == 0) { return var; } } Com_Printf("%s will be changed upon restarting.\n", var_name); var->latchedString = CopyString(value); var->modified = qtrue; var->modificationCount++; return var; } if ((var->flags & CVAR_CHEAT) && !cvar_cheats->integer) { Com_Printf("%s is cheat protected.\n", var_name); return var; } if (var->flags & CVAR_SHADER) { Com_Printf("%s will be changed upon recompiling shaders.\n", var_name); Cvar_Set("r_recompileShaders", "1"); } } else { if (var->latchedString) { Z_Free(var->latchedString); var->latchedString = NULL; } } if (!strcmp(value, var->string)) { return var; // not changed } var->modified = qtrue; var->modificationCount++; Z_Free(var->string); // free the old value string var->string = CopyString(value); var->value = atof(var->string); var->integer = atoi(var->string); return var; }
/* ============ Cvar_Set2 ============ */ cvar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) { cvar_t *var; // Com_DPrintf( "Cvar_Set2: %s %s\n", var_name, value ); if ( !Cvar_ValidateString( var_name ) ) { Com_Printf("invalid cvar name string: %s\n", var_name ); var_name = "BADNAME"; } #if 0 // FIXME if ( value && !Cvar_ValidateString( value ) ) { Com_Printf("invalid cvar value string: %s\n", value ); var_value = "BADVALUE"; } #endif var = Cvar_FindVar (var_name); if (!var) { if ( !value ) { return NULL; } // create it if ( !force ) { return Cvar_Get( var_name, value, CVAR_USER_CREATED ); } else { return Cvar_Get (var_name, value, 0); } } if (!value ) { value = var->resetString; } if((var->flags & CVAR_LATCH) && var->latchedString) { if(!strcmp(value,var->latchedString)) return var; } else if (!strcmp(value,var->string)) { return var; } // note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo) cvar_modifiedFlags |= var->flags; if (!force) { if (var->flags & CVAR_ROM) { Com_Printf ("%s is read only.\n", var_name); return var; } if (var->flags & CVAR_INIT) { Com_Printf ("%s is write protected.\n", var_name); return var; } if (var->flags & CVAR_LATCH) { if (var->latchedString) { if (strcmp(value, var->latchedString) == 0) return var; Z_Free (var->latchedString); } else { if (strcmp(value, var->string) == 0) return var; } Com_Printf ("%s will be changed upon restarting.\n", var_name); var->latchedString = CopyString(value); var->modified = qtrue; var->modificationCount++; return var; } if ( (var->flags & CVAR_CHEAT) && !cvar_cheats->integer ) { Com_Printf ("%s is cheat protected.\n", var_name); return var; } } else { if (var->latchedString) { Z_Free (var->latchedString); var->latchedString = NULL; } } if (!strcmp(value, var->string)) return var; // not changed var->modified = qtrue; var->modificationCount++; Z_Free (var->string); // free the old value string var->string = CopyString(value); var->value = atof (var->string); var->integer = atoi (var->string); return var; }
/* ====================== CSCR_WriteGameCVars Print all cvars declared in script to gamesettings.cfg file ====================== */ int CSCR_WriteGameCVars( file_t *cfg, const char *scriptfilename ) { int count = 0; fs_offset_t length = 0; char *start; parserstate_t state = {0}; qboolean success = false; state.filename = scriptfilename; state.buf = (char*)FS_LoadFile( scriptfilename, &length, true ); start = state.buf; if( state.buf == 0 || length == 0 ) { if( start ) Mem_Free( start ); return 0; } MsgDev( D_INFO, "Reading config script file %s\n", scriptfilename ); if( !CSCR_ParseHeader( &state ) ) { MsgDev( D_ERROR, "Failed to parse header!\n" ); goto finish; } FS_Printf( cfg, "// declared in %s:\n", scriptfilename ); while( !CSCR_ExpectString( &state, "}", false, false ) ) { scrvardef_t var = { 0 }; if( CSCR_ParseSingleCvar( &state, &var ) ) { convar_t *cvar = Cvar_FindVar( var.name ); if( cvar && !( cvar->flags & ( CVAR_SERVERNOTIFY | CVAR_ARCHIVE ) ) ) { // cvars will be placed in gamesettings.cfg and restored on map start if( var.flags & CVAR_USERINFO ) FS_Printf( cfg, "// %s ( %s )\nsetu %s \"%s\"\n", var.desc, var.value, var.name, cvar->string ); else FS_Printf( cfg, "// %s ( %s )\nset %s \"%s\"\n", var.desc, var.value, var.name, cvar->string ); } count++; } else break; if( count > 1024 ) break; } if( COM_ParseFile( state.buf, state.token ) ) MsgDev( D_ERROR, "Got extra tokens!\n" ); else success = true; finish: if( !success ) { state.token[ sizeof( state.token ) - 1 ] = 0; if( start && state.buf ) MsgDev( D_ERROR, "Parse error in %s, byte %d, token %s\n", scriptfilename, (int)( state.buf - start ), state.token ); else MsgDev( D_ERROR, "Parse error in %s, token %s\n", scriptfilename, state.token ); } if( start ) Mem_Free( start ); return count; }
qboolean demoCut(const char *oldName, int startTime, int endTime) { fileHandle_t oldHandle = 0; fileHandle_t newHandle = 0; msg_t oldMsg; byte oldData[MAX_MSGLEN]; int oldSize; char newName[MAX_OSPATH]; int buf; int readGamestate = 0; int i; demoPlay_t *play = demo.play.handle; qboolean ret = qfalse; int framesSaved = 0; char newGameDir[MAX_QPATH]; char next; char *ext; if (!play) { Com_Printf("Demo cutting is allowed in mme mode only.\n"); return qfalse; } startTime += play->startTime; endTime += play->startTime; ext = Cvar_FindVar("mme_demoExt")->string; if (!*ext) ext = ".dm_26"; oldSize = FS_FOpenFileRead(va("demos/%s%s", oldName, ext), &oldHandle, qtrue); if (!oldHandle) { Com_Printf("Failed to open %s for cutting.\n", oldName); return qfalse; } memset(&demo.cut.Clc, 0, sizeof(demo.cut.Clc)); Com_SetLoadingMsg("Cutting the demo..."); while (oldSize > 0) { cutcontinue: MSG_Init(&oldMsg, oldData, sizeof(oldData)); /* Read the sequence number */ if (FS_Read(&demo.cut.Clc.serverMessageSequence, 4, oldHandle) != 4) goto cuterror; demo.cut.Clc.serverMessageSequence = LittleLong(demo.cut.Clc.serverMessageSequence); oldSize -= 4; /* Read the message size */ if (FS_Read(&oldMsg.cursize,4, oldHandle) != 4) goto cuterror; oldMsg.cursize = LittleLong(oldMsg.cursize); oldSize -= 4; /* Negative size signals end of demo */ if (oldMsg.cursize < 0) break; if (oldMsg.cursize > oldMsg.maxsize) goto cuterror; /* Read the actual message */ if (FS_Read(oldMsg.data, oldMsg.cursize, oldHandle) != oldMsg.cursize) goto cuterror; oldSize -= oldMsg.cursize; // init the bitstream MSG_BeginReading(&oldMsg); // Skip the reliable sequence acknowledge number MSG_ReadLong(&oldMsg); // // parse the message // while (1) { byte cmd; if (oldMsg.readcount > oldMsg.cursize) { Com_Printf("Demo cutter, read past end of server message.\n"); goto cuterror; } cmd = MSG_ReadByte(&oldMsg); if (cmd == svc_EOF) { break; } // skip all the gamestates until we reach needed if (readGamestate < demo.currentNum) { if (cmd == svc_gamestate) { readGamestate++; } goto cutcontinue; } // other commands switch (cmd) { default: Com_Printf(S_COLOR_RED"ERROR: CL_ParseServerMessage: Illegible server message\n"); goto cuterror; case svc_nop: break; case svc_serverCommand: demoCutParseCommandString(&oldMsg, &demo.cut.Clc); break; case svc_gamestate: if (readGamestate > demo.currentNum) { Com_Printf("Warning: unexpected new gamestate, finishing cutting.\n"); goto cutcomplete; } if (!demoCutParseGamestate(&oldMsg, &demo.cut.Clc, &demo.cut.Cl)) { goto cuterror; } Com_sprintf(newName, sizeof(newName), "demos/%s_cut%s", oldName, ext); newHandle = FS_FOpenFileWrite(newName); if (!newHandle) { Com_Printf("Failed to open %s for target cutting.\n", newName); return qfalse; } readGamestate++; break; case svc_snapshot: if (!demoCutParseSnapshot(&oldMsg, &demo.cut.Clc, &demo.cut.Cl)) { goto cuterror; } break; case svc_download: // read block number buf = MSG_ReadShort(&oldMsg); if (!buf) //0 block, read file size MSG_ReadLong(&oldMsg); // read block size buf = MSG_ReadShort(&oldMsg); // read the data block for (;buf>0;buf--) MSG_ReadByte(&oldMsg); break; case svc_setgame: i = 0; while (i < MAX_QPATH) { next = MSG_ReadByte(&oldMsg); if(next) { newGameDir[i] = next; } else { break; } i++; } newGameDir[i] = 0; // But here we stop, and don't do more. If this goes horribly wrong sometime, you might have to go and actually do something with this. break; case svc_mapchange: // nothing to parse. break; } } int firstServerCommand = demo.cut.Clc.lastExecutedServerCommand; // process any new server commands for (;demo.cut.Clc.lastExecutedServerCommand < demo.cut.Clc.serverCommandSequence; demo.cut.Clc.lastExecutedServerCommand++) { char *command = demo.cut.Clc.serverCommands[demo.cut.Clc.lastExecutedServerCommand & (MAX_RELIABLE_COMMANDS - 1)]; Cmd_TokenizeString(command); char *cmd = Cmd_Argv(0); if (cmd[0]) { firstServerCommand = demo.cut.Clc.lastExecutedServerCommand; } if (!strcmp(cmd, "cs")) { if (!demoCutConfigstringModified(&demo.cut.Cl)) { goto cuterror; } } } if (demo.cut.Cl.snap.serverTime > endTime) { goto cutcomplete; } else if (framesSaved > 0) { /* this msg is in range, write it */ if (framesSaved > max(10, demo.cut.Cl.snap.messageNum - demo.cut.Cl.snap.deltaNum)) { demoCutWriteDemoMessage(&oldMsg, newHandle, &demo.cut.Clc); } else { demoCutWriteDeltaSnapshot(firstServerCommand, newHandle, qfalse, &demo.cut.Clc, &demo.cut.Cl); } framesSaved++; } else if (demo.cut.Cl.snap.serverTime >= startTime) { demoCutWriteDemoHeader(newHandle, &demo.cut.Clc, &demo.cut.Cl); demoCutWriteDeltaSnapshot(firstServerCommand, newHandle, qtrue, &demo.cut.Clc, &demo.cut.Cl); // copy rest framesSaved = 1; } } cutcomplete: if (newHandle) { buf = -1; FS_Write(&buf, 4, newHandle); FS_Write(&buf, 4, newHandle); ret = qtrue; } cuterror: //remove previosly converted demo from the same cut if (newHandle) { memset(newName, 0, sizeof(newName)); if (demo.currentNum > 0) { Com_sprintf(newName, sizeof(newName), "mmedemos/%s.%d_cut.mme", oldName, demo.currentNum); } else { Com_sprintf(newName, sizeof(newName), "mmedemos/%s_cut.mme", oldName); } if (FS_FileExists(newName)) FS_FileErase(newName); } FS_FCloseFile(oldHandle); FS_FCloseFile(newHandle); return ret; }
/* ============ Cvar_Set ============ */ void Cvar_Set (const char *var_name, const char *value) { cvar_t *var; size_t varlen; var = Cvar_FindVar (var_name); if (!var) { // there is an error in C code if this happens Con_Printf ("%s: variable %s not found\n", __thisfunc__, var_name); return; } if ( var->flags & (CVAR_ROM|CVAR_LOCKED) ) return; // cvar is marked read-only or locked temporarily if (var->flags & CVAR_REGISTERED) { if ( !strcmp(var->string, value) ) return; // no change } else { var->flags |= CVAR_REGISTERED; } varlen = strlen(value); if (var->string == NULL) { var->string = (char *) Z_Malloc (varlen + 1, Z_MAINZONE); } else if (strlen(var->string) != varlen) { Z_Free ((void *)var->string); // free the old value string var->string = (char *) Z_Malloc (varlen + 1, Z_MAINZONE); } memcpy ((char *)var->string, value, varlen + 1); var->value = atof (var->string); var->integer = (int) var->value; // handle notifications #if defined (H2W) # if defined(SERVERONLY) if (var->flags & CVAR_SERVERINFO) { Info_SetValueForKey (svs.info, var_name, value, MAX_SERVERINFO_STRING); SV_BroadcastCommand ("fullserverinfo \"%s\"\n", svs.info); } # else /* HWCL */ if (var->flags & CVAR_USERINFO) { Info_SetValueForKey (cls.userinfo, var_name, value, MAX_INFO_STRING); if (cls.state >= ca_connected) { MSG_WriteByte (&cls.netchan.message, clc_stringcmd); SZ_Print (&cls.netchan.message, va("setinfo \"%s\" \"%s\"\n", var_name, value)); } } # endif #else /* ! H2W */ if (var->flags & CVAR_NOTIFY) { if (sv.active) SV_BroadcastPrintf ("\"%s\" changed to \"%s\"\n", var_name, value); } #endif /* H2W */ // don't allow deathmatch and coop at the same time #if !defined(H2W) || defined(SERVERONLY) if ( !strcmp(var->name, deathmatch.name) ) { if (var->integer != 0) Cvar_Set("coop", "0"); } else if ( !strcmp(var->name, coop.name) ) { if (var->integer != 0) Cvar_Set("deathmatch", "0"); } #endif /* coop && deathmatch */ }
void Cvar_UnlockVar (const char *var_name) { cvar_t *var = Cvar_FindVar (var_name); if (var) var->flags &= ~CVAR_LOCKED; }
/* ============ Cvar_Get If the variable already exists, the value will not be set unless CVAR_ROM The flags will be or'ed in if the variable exists. ============ */ cvar_t *Cvar_Get(const char *var_name, const char *var_value, int flags) { cvar_t *var; long hash; if (!var_name || !var_value) { Com_Error(ERR_FATAL, "Cvar_Get: NULL parameter\n"); } if (!Cvar_ValidateString(var_name)) { Com_Printf("invalid cvar name string: %s\n", var_name); var_name = "BADNAME"; } #if 0 // FIXME: values with backslash happen if (!Cvar_ValidateString(var_value)) { Com_Printf("invalid cvar value string: %s\n", var_value); var_value = "BADVALUE"; } #endif var = Cvar_FindVar(var_name); if (var) { // if the C code is now specifying a variable that the user already // set a value for, take the new value as the reset value if ((var->flags & CVAR_USER_CREATED) && !(flags & CVAR_USER_CREATED) && var_value[0]) { var->flags &= ~CVAR_USER_CREATED; Z_Free(var->resetString); var->resetString = CopyString(var_value); // ZOID--needs to be set so that cvars the game sets as // SERVERINFO get sent to clients cvar_modifiedFlags |= flags; } var->flags |= flags; // only allow one non-empty reset string without a warning if (!var->resetString[0]) { // we don't have a reset string yet Z_Free(var->resetString); var->resetString = CopyString(var_value); } else if (var_value[0] && strcmp(var->resetString, var_value)) { Com_DPrintf("Warning: cvar \"%s\" given initial values: \"%s\" and \"%s\"\n", var_name, var->resetString, var_value); } // if we have a latched string, take that value now if (var->latchedString) { char *s; s = var->latchedString; var->latchedString = NULL; // otherwise cvar_set2 would free it Cvar_Set2(var_name, s, qtrue); Z_Free(s); } // if CVAR_USERINFO was toggled on for an existing cvar, check wether the value needs to be cleaned from foreigh characters // (for instance, seta name "name-with-foreign-chars" in the config file, and toggle to CVAR_USERINFO happens later in CL_Init) if (flags & CVAR_USERINFO) { char *cleaned = Cvar_ClearForeignCharacters(var->string); // NOTE: it is probably harmless to call Cvar_Set2 in all cases, but I don't want to risk it if (strcmp(var->string, cleaned)) { Cvar_Set2(var->name, var->string, qfalse); // call Cvar_Set2 with the value to be cleaned up for verbosity } } // use a CVAR_SET for rom sets, get won't override #if 0 // CVAR_ROM always overrides if (flags & CVAR_ROM) { Cvar_Set2(var_name, var_value, qtrue); } #endif return var; } // allocate a new cvar if (cvar_numIndexes >= MAX_CVARS) { Com_Error(ERR_FATAL, "Cvar_Get: MAX_CVARS (%d) hit -- too many cvars!\n", MAX_CVARS); } var = &cvar_indexes[cvar_numIndexes]; cvar_numIndexes++; var->name = CopyString(var_name); var->string = CopyString(var_value); var->modified = qtrue; var->modificationCount = 1; var->value = atof(var->string); var->integer = atoi(var->string); var->resetString = CopyString(var_value); // link the variable in var->next = cvar_vars; cvar_vars = var; var->flags = flags; hash = generateHashValue(var_name); var->hashNext = hashTable[hash]; hashTable[hash] = var; return var; }
/* <4c63> ../engine/cmd.c:521 */ void Cmd_Alias_f(void) { cmdalias_t *a; const char *s; char cmd[MAX_CMD_LINE]; int i, c; if (Cmd_Argc() == 1) { // Output all aliases Con_Printf("Current alias commands:\n"); for (a = cmd_alias; a; a = a->next) { Con_Printf("%s : %s", a->name, a->value); // Don't need \n here, because each alias value is appended with it } return; } s = Cmd_Argv(1); if (Q_strlen(s) >= MAX_ALIAS_NAME) { Con_Printf("Alias name is too long\n"); return; } if (Cvar_FindVar(s)) { Con_Printf("Alias name is invalid\n"); return; } SetCStrikeFlags(); // TODO: Do this once somewhere at the server start if ((g_bIsCStrike || g_bIsCZero) && (!Q_stricmp(s, "cl_autobuy") || !Q_stricmp(s, "cl_rebuy") || !Q_stricmp(s, "gl_ztrick") || !Q_stricmp(s, "gl_ztrick_old") || !Q_stricmp(s, "gl_d3dflip"))) { Con_Printf("Alias name is invalid\n"); return; } // Say hello to my little friend! (c) if (g_bIsTFC && (!Q_stricmp(s, "_special") || !Q_stricmp(s, "special"))) { Con_Printf("Alias name is invalid\n"); return; } // Gather arguments into one string cmd[0] = 0; c = Cmd_Argc(); for (i = 2; i <= c; i++) { Q_strncat(cmd, Cmd_Argv(i), MAX_CMD_LINE - 2 - Q_strlen(cmd)); // always have a space for \n or ' ' and \0 if (i != c) { Q_strcat(cmd, " "); } } Q_strcat(cmd, "\n"); // Search for existing alias for (a = cmd_alias; a; a = a->next) { if (!Q_stricmp(a->name, s)) { if (!Q_strcmp(a->value, cmd)) { // Same value on the alias, return return; } // Release value, will realloc Z_Free(a->value); break; } } if (!a) { // Alloc new alias a = (cmdalias_t *)Z_Malloc(sizeof(cmdalias_t)); a->next = cmd_alias; cmd_alias = a; Q_strncpy(a->name, s, ARRAYSIZE(a->name) - 1); a->name[ARRAYSIZE(a->name) - 1] = 0; } a->value = CopyString(cmd); }
/** * @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 NULL; var = Cvar_FindVar(varName); /* create it */ if (!var) return Cvar_Get(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 = NULL; } 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 = NULL; } 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; }
/* ============ Cvar_VariableIntegerValue ============ */ int Cvar_VariableIntegerValue( const char* name ) { cvar_t* var = Cvar_FindVar(name); return var ? var->integer : 0; }
/* ============ Cvar_Set2 ============ */ cvar_t *Cvar_Set2( const char *var_name, const char *value, uint32_t defaultFlags, qboolean force ) { cvar_t *var; if ( !Cvar_ValidateString( var_name ) ) { Com_Printf("invalid cvar name string: %s\n", var_name ); var_name = "BADNAME"; } #if 0 // FIXME if ( value && !Cvar_ValidateString( value ) ) { Com_Printf("invalid cvar value string: %s\n", value ); var_value = "BADVALUE"; } #endif var = Cvar_FindVar (var_name); if (!var) { if ( !value ) { return NULL; } // create it return Cvar_Get( var_name, value, defaultFlags ); } if (!value ) { value = var->resetString; } value = Cvar_Validate(var, value, qtrue); if((var->flags & CVAR_LATCH) && var->latchedString) { if(!strcmp(value, var->string)) { Cvar_FreeString(var->latchedString); var->latchedString = NULL; return var; } if(!strcmp(value, var->latchedString)) return var; } else if(!strcmp(value, var->string)) return var; // note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo) cvar_modifiedFlags |= var->flags; if (!force) { if ( (var->flags & (CVAR_SYSTEMINFO|CVAR_SERVER_CREATED)) && com_sv_running && !com_sv_running->integer && CL_ConnectedToServer() ) { Com_Printf ("%s can only be set by server.\n", var_name); return var; } if (var->flags & CVAR_ROM) { Com_Printf ("%s is read only.\n", var_name); return var; } if (var->flags & CVAR_INIT) { Com_Printf ("%s is write protected.\n", var_name); return var; } if (var->flags & CVAR_LATCH) { if (var->latchedString) { if (strcmp(value, var->latchedString) == 0) return var; Cvar_FreeString (var->latchedString); } else { if (strcmp(value, var->string) == 0) return var; } Com_Printf ("%s will be changed upon restarting.\n", var_name); var->latchedString = CopyString(value); var->modified = qtrue; var->modificationCount++; return var; } if ( (var->flags & CVAR_CHEAT) && !cvar_cheats->integer ) { Com_Printf ("%s is cheat protected.\n", var_name); return var; } } else { if (var->latchedString) { Cvar_FreeString (var->latchedString); var->latchedString = NULL; } } if (!strcmp(value, var->string)) return var; // not changed var->modified = qtrue; var->modificationCount++; Cvar_FreeString (var->string); // free the old value string var->string = CopyString(value); var->value = atof (var->string); var->integer = atoi (var->string); return var; }
/* ============ Cvar_VariableString ============ */ char* Cvar_VariableString(const char* name) { cvar_t* var = Cvar_FindVar(name); return var ? var->string : (char*)""; }
/* ============ Cvar_Get If the variable already exists, the value will not be set unless CVAR_ROM The flags will be or'ed in if the variable exists. ============ */ cvar_t* Cvar_Get( const char *var_name, const char *var_value, int flags ) { if ( !var_name || !var_value ) { Com_Error( ERR_FATAL, "Cvar_Get: NULL parameter" ); } if ( !Cvar_ValidateString( var_name ) ) { Com_Printf("invalid cvar name string: %s\n", var_name ); var_name = "BADNAME"; } cvar_t* var = Cvar_FindVar( var_name ); if ( var ) { // if the C code is now specifying a variable that the user already // set a value for, take the new value as the reset value if ( ( var->flags & CVAR_USER_CREATED ) && !( flags & CVAR_USER_CREATED ) && var_value[0] ) { var->flags &= ~CVAR_USER_CREATED; Z_Free( var->resetString ); var->resetString = CopyString( var_value ); // needs to be set so that cvars the game tags as SERVERINFO get sent to clients cvar_modifiedFlags |= flags; } var->flags |= flags; // only allow one non-empty reset string without a warning // KHB 071110 no, that's wrong for several reasons, notably vm changes caused by pure if ((flags & CVAR_ROM) || !var->resetString[0]) { Z_Free( var->resetString ); var->resetString = CopyString( var_value ); } else if ( var_value[0] && strcmp( var->resetString, var_value ) ) { Com_DPrintf( "Warning: cvar \"%s\" given initial values: \"%s\" and \"%s\"\n", var_name, var->resetString, var_value ); } // if we have a latched string, take that value now if ( var->latchedString ) { char* s = var->latchedString; var->latchedString = NULL; // otherwise cvar_set2 would free it Cvar_Set2( var_name, s, qtrue ); Z_Free( s ); } /* KHB note that this is #if 0'd in the 132 code, but is actually REQUIRED for correctness consider a cgame that sets a CVAR_ROM client version: you connect to a v1 server, load the v1 cgame, and set the ROM version to v1 you then connect to a v2 server and correctly load the v2 cgame, but when that registers its GENUINELY "NEW" version var, the value is ignored so now you have a CVAR_ROM with the wrong value in it. gg. i'm preserving this incorrect behavior FOR NOW for compatability, because game\ai_main.c(1352): trap_Cvar_Register( &mapname, "mapname", "", CVAR_SERVERINFO | CVAR_ROM ); breaks every single mod except CPMA otherwise, but it IS wrong, and critically so // CVAR_ROM always overrides if (flags & CVAR_ROM) { Cvar_Set2( var_name, var_value, qtrue ); } */ return var; } // // allocate a new cvar // if ( cvar_numIndexes >= MAX_CVARS ) { Com_Error( ERR_FATAL, "MAX_CVARS" ); } var = &cvar_indexes[cvar_numIndexes]; cvar_numIndexes++; var->name = CopyString( var_name ); var->string = CopyString( var_value ); var->modified = qtrue; var->modificationCount = 1; var->value = atof(var->string); var->integer = atoi(var->string); var->resetString = CopyString( var_value ); // link the variable in var->next = cvar_vars; cvar_vars = var; var->flags = flags; cvar_modifiedFlags |= flags; // needed so USERINFO cvars created by cgame actually get sent long hash = Cvar_Hash(var_name); var->hashNext = hashTable[hash]; hashTable[hash] = var; return var; }
/** * @brief If the variable already exists, the value will not be set unless CVAR_ROM * The flags will be or'ed in if the variable exists. */ cvar_t *Cvar_Get(const char *var_name, const char *var_value, int flags) { cvar_t *var; long hash; int index; if (!var_name || !var_value) { Com_Error(ERR_FATAL, "Cvar_Get: NULL parameter"); } if (!Cvar_ValidateString(var_name)) { Com_Printf("invalid cvar name string: %s\n", var_name); var_name = "BADNAME"; } #if 0 // FIXME: values with backslash happen if (!Cvar_ValidateString(var_value)) { Com_Printf("invalid cvar value string: %s\n", var_value); var_value = "BADVALUE"; } #endif var = Cvar_FindVar(var_name); if (var) { // if the C code is now specifying a variable that the user already // set a value for, take the new value as the reset value if (var->flags & CVAR_USER_CREATED) { var->flags &= ~CVAR_USER_CREATED; Z_Free(var->resetString); var->resetString = CopyString(var_value); if (flags & CVAR_ROM) { // this variable was set by the user, // so force it to value given by the engine. if (var->latchedString) { Z_Free(var->latchedString); } var->latchedString = CopyString(var_value); } } // Make sure the game code cannot mark engine-added variables as gamecode vars if (var->flags & CVAR_VM_CREATED) { if (!(flags & CVAR_VM_CREATED)) { var->flags &= ~CVAR_VM_CREATED; } } else { if (flags & CVAR_VM_CREATED) { flags &= ~CVAR_VM_CREATED; } } // Make sure servers cannot mark engine-added variables as SERVER_CREATED if (var->flags & CVAR_SERVER_CREATED) { if (!(flags & CVAR_SERVER_CREATED)) { var->flags &= ~CVAR_SERVER_CREATED; } } else { if (flags & CVAR_SERVER_CREATED) { flags &= ~CVAR_SERVER_CREATED; } } var->flags |= flags; // only allow one non-empty reset string without a warning if (!var->resetString[0]) { // we don't have a reset string yet Z_Free(var->resetString); var->resetString = CopyString(var_value); } else if (var_value[0] && strcmp(var->resetString, var_value)) { Com_DPrintf("Warning: cvar \"%s\" given initial values: \"%s\" and \"%s\"\n", var_name, var->resetString, var_value); } // if we have a latched string, take that value now if (var->latchedString) { char *s; s = var->latchedString; var->latchedString = NULL; // otherwise cvar_set2 would free it Cvar_Set2(var_name, s, qtrue); Z_Free(s); } // if CVAR_USERINFO was toggled on for an existing cvar, check wether the value needs to be cleaned from foreigh characters // (for instance, seta name "name-with-foreign-chars" in the config file, and toggle to CVAR_USERINFO happens later in CL_Init) if (flags & CVAR_USERINFO) { char *cleaned = Cvar_ClearForeignCharacters(var->string); // NOTE: it is probably harmless to call Cvar_Set2 in all cases, but I don't want to risk it if (strcmp(var->string, cleaned)) { Cvar_Set2(var->name, var->string, qfalse); // call Cvar_Set2 with the value to be cleaned up for verbosity } } // ZOID--needs to be set so that cvars the game sets as // SERVERINFO get sent to clients cvar_modifiedFlags |= flags; return var; } // // allocate a new cvar // // find a free cvar for (index = 0; index < MAX_CVARS; index++) { if (!cvar_indexes[index].name) { break; } } if (index >= MAX_CVARS) { if (!com_errorEntered) { Com_Error(ERR_FATAL, "Error: Too many cvars (%d), cannot create a new one!", MAX_CVARS); } return NULL; } var = &cvar_indexes[index]; if (index >= cvar_numIndexes) { cvar_numIndexes = index + 1; } var->name = CopyString(var_name); var->string = CopyString(var_value); var->modified = qtrue; var->modificationCount = 1; var->value = atof(var->string); var->integer = atoi(var->string); var->resetString = CopyString(var_value); // link the variable in var->next = cvar_vars; if (cvar_vars) { cvar_vars->prev = var; } var->prev = NULL; cvar_vars = var; var->flags = flags; // note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo) cvar_modifiedFlags |= var->flags; hash = generateHashValue(var_name); var->hashIndex = hash; var->hashNext = hashTable[hash]; if (hashTable[hash]) { hashTable[hash]->hashPrev = var; } var->hashPrev = NULL; hashTable[hash] = var; return var; }
/* ============ Cvar_VariableString ============ */ char* Cvar_LatchedVariableString(const char* name) { cvar_t* var = Cvar_FindVar(name); return var && var->latchedString ? var->latchedString : (char*)""; }
/* ============ Cvar_Get If the variable already exists, the value will not be set unless CVAR_ROM The flags will be or'ed in if the variable exists. ============ */ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) { cvar_t *var; long hash; if ( !var_name || ! var_value ) { Com_Error( ERR_FATAL, "Cvar_Get: NULL parameter" ); } if ( !Cvar_ValidateString( var_name ) ) { Com_Printf("invalid cvar name string: %s\n", var_name ); var_name = "BADNAME"; } #if 0 // FIXME: values with backslash happen if ( !Cvar_ValidateString( var_value ) ) { Com_Printf("invalid cvar value string: %s\n", var_value ); var_value = "BADVALUE"; } #endif var = Cvar_FindVar (var_name); if ( var ) { // if the C code is now specifying a variable that the user already // set a value for, take the new value as the reset value if ( ( var->flags & CVAR_USER_CREATED ) && !( flags & CVAR_USER_CREATED ) && var_value[0] ) { var->flags &= ~CVAR_USER_CREATED; Z_Free( var->resetString ); var->resetString = CopyString( var_value ); // ZOID--needs to be set so that cvars the game sets as // SERVERINFO get sent to clients cvar_modifiedFlags |= flags; } var->flags |= flags; // only allow one non-empty reset string without a warning if ( !var->resetString[0] ) { // we don't have a reset string yet Z_Free( var->resetString ); var->resetString = CopyString( var_value ); } else if ( var_value[0] && strcmp( var->resetString, var_value ) ) { Com_DPrintf( "Warning: cvar \"%s\" given initial values: \"%s\" and \"%s\"\n", var_name, var->resetString, var_value ); } // if we have a latched string, take that value now if ( var->latchedString ) { char *s; s = var->latchedString; var->latchedString = NULL; // otherwise cvar_set2 would free it Cvar_Set2( var_name, s, qtrue ); Z_Free( s ); } // use a CVAR_SET for rom sets, get won't override #if 0 // CVAR_ROM always overrides if ( flags & CVAR_ROM ) { Cvar_Set2( var_name, var_value, qtrue ); } #endif return var; } // // allocate a new cvar // if ( cvar_numIndexes >= MAX_CVARS ) { Com_Error( ERR_FATAL, "MAX_CVARS" ); } var = &cvar_indexes[cvar_numIndexes]; cvar_numIndexes++; var->name = CopyString (var_name); var->string = CopyString (var_value); var->modified = qtrue; var->modificationCount = 1; var->value = atof (var->string); var->integer = atoi(var->string); var->resetString = CopyString( var_value ); // link the variable in var->next = cvar_vars; cvar_vars = var; var->flags = flags; // note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo) cvar_modifiedFlags |= var->flags; hash = generateHashValue(var_name); var->hashNext = hashTable[hash]; hashTable[hash] = var; return var; }
/* ============ Cvar_Set2 ============ */ static cvar_t *Cvar_Set2 (const char *var_name, const char *value, qboolean force) { cvar_t *var; char *old_string; Q_assert (var_name != NULL); Q_assert (value != NULL); if (var_name[0] == '$' && !force) { Com_Printf ("%s is write protected.\n", LOG_GENERAL, var_name); return NULL; } var = Cvar_FindVar (var_name); if (!var) { // create it return Cvar_Get (var_name, value, 0); } if (var->flags & (CVAR_USERINFO | CVAR_SERVERINFO)) { if (!Cvar_InfoValidate (value)) { Com_Printf("invalid info cvar value\n", LOG_GENERAL); return var; } } if (!force) { #ifdef _DEBUG if (var->flags & CVAR_NOSET && !Cvar_IntValue ("developer")) #else if (var->flags & CVAR_NOSET) #endif { Com_Printf ("%s is write protected.\n", LOG_GENERAL, var_name); return var; } if (var->flags & CVAR_LATCH) { if (var->latched_string) { if (strcmp(value, var->latched_string) == 0) return var; Z_Free (var->latched_string); } else { if (strcmp(value, var->string) == 0) return var; } if (Com_ServerState()) { Com_Printf ("%s will be changed for next map.\n", LOG_GENERAL, var_name); var->latched_string = CopyString(value, TAGMALLOC_CVAR); } else { //memleak fix, thanks Maniac- Z_Free (var->string); var->string = CopyString(value, TAGMALLOC_CVAR); var->value = (float)atof (var->string); var->intvalue = (int)var->value; //r1: fix 0 case if (!var->intvalue && FLOAT_NE_ZERO(var->value)) var->intvalue = 1; if (!strcmp(var->name, "game")) { FS_SetGamedir (var->string); if (!Cvar_IntValue ("dedicated")) FS_ExecConfig ("autoexec.cfg"); } } return var; } } else { if (var->latched_string) { Z_Free (var->latched_string); var->latched_string = NULL; } } if (!strcmp(value, var->string)) return var; // not changed old_string = var->string; var->string = CopyString(value, TAGMALLOC_CVAR); var->value = (float)atof (var->string); var->intvalue = (int)var->value; //r1: fix 0 case if (!var->intvalue && FLOAT_NE_ZERO(var->value)) var->intvalue = 1; var->modified = true; if (var->changed) var->changed (var, old_string, var->string); if (var->flags & CVAR_USERINFO) userinfo_modified = true; // transmit at next oportunity Z_Free (old_string); // free the old value string return var; }
/* ============ Cvar_Set2 ============ */ cvar_t *Cvar_Set2 (char *var_name, char *value, int force) { cvar_t *var; var = Cvar_FindVar (var_name); if (!var) { // create it return Cvar_Get (var_name, value, 0); } if (var->flags & (CVAR_USERINFO | CVAR_SERVERINFO)) { if (!Cvar_InfoValidate (value)) { Com_Printf("invalid info cvar value\n"); return var; } } if (!force) { if (var->flags & CVAR_NOSET) { Com_Printf ("%s is write protected.\n", var_name); return var; } if (var->flags & CVAR_LATCH) { if (var->latched_string) { if (strcmp(value, var->latched_string) == 0) return var; Z_Free (var->latched_string); } else { if (strcmp(value, var->string) == 0) return var; } if (Com_ServerState()) { Com_Printf ("%s will be changed for next game.\n", var_name); var->latched_string = CopyString(value); } else { var->string = CopyString(value); var->value = atof (var->string); if (!strcmp(var->name, "game")) { FS_SetGamedir (var->string); FS_ExecAutoexec (); } } return var; } } else { if (var->latched_string) { Z_Free (var->latched_string); var->latched_string = NULL; } } if (!strcmp(value, var->string)) return var; // not changed var->modified = 1; if (var->flags & CVAR_USERINFO) userinfo_modified = 1; // transmit at next oportunity Z_Free (var->string); // free the old value string var->string = CopyString(value); var->value = atof (var->string); return var; }
/** * @brief Check if an expression is true * @return True if the expression is true */ bool UI_GetBooleanFromExpression (uiAction_t* expression, const uiCallContext_t* context) { if (expression == nullptr) return false; switch (expression->type & EA_HIGHT_MASK) { case EA_VALUE: return UI_GetFloatFromExpression(expression, context) != 0; case EA_OPERATOR_BOOLEAN2BOOLEAN: { #define VALUE1 UI_GetBooleanFromExpression(expression->d.nonTerminal.left, context) #define VALUE2 UI_GetBooleanFromExpression(expression->d.nonTerminal.right, context) switch (expression->type) { case EA_OPERATOR_AND: return VALUE1 && VALUE2; case EA_OPERATOR_OR: return VALUE1 || VALUE2; case EA_OPERATOR_XOR: return VALUE1 ^ VALUE2; case EA_OPERATOR_NOT: return !VALUE1; default: Com_Error(ERR_FATAL, "UI_GetBooleanFromExpression: (BOOL2BOOL) Invalid expression type"); } } case EA_OPERATOR_FLOAT2BOOLEAN: { const float value1 = UI_GetFloatFromExpression(expression->d.nonTerminal.left, context); const float value2 = UI_GetFloatFromExpression(expression->d.nonTerminal.right, context); switch (expression->type) { case EA_OPERATOR_EQ: return value1 == value2; case EA_OPERATOR_LE: return value1 <= value2; case EA_OPERATOR_GE: return value1 >= value2; case EA_OPERATOR_GT: return value1 > value2; case EA_OPERATOR_LT: return value1 < value2; case EA_OPERATOR_NE: return value1 != value2; default: Com_Error(ERR_FATAL, "UI_GetBooleanFromExpression: (FLOAT2BOOL) Invalid expression type"); } } case EA_OPERATOR_UNARY: switch (expression->type) { case EA_OPERATOR_EXISTS: { const uiAction_t* e = expression->d.nonTerminal.left; const char* name; assert(e); name = e->d.terminal.d1.constString; switch (e->type) { case EA_VALUE_CVARNAME_WITHINJECTION: name = UI_GenInjectedString(name, false, context); case EA_VALUE_CVARNAME: return Cvar_FindVar(name) != nullptr; case EA_VALUE_PATHNODE_WITHINJECTION: name = UI_GenInjectedString(name, false, context); case EA_VALUE_PATHNODE: { uiNode_t* node = nullptr; const value_t* property; UI_ReadNodePath(name, context->source, context->tagNode, &node, &property); return node != nullptr; } default: return false; } } case EA_OPERATOR_PATHPROPERTYFROM: return UI_GetFloatFromExpression(expression, context) != 0; default: Com_Error(ERR_FATAL, "UI_GetBooleanFromExpression: (EA_OPERATOR_UNARY) Invalid expression type %i", expression->type); } case EA_OPERATOR_STRING2BOOLEAN: { const char* value1 = UI_GetStringFromExpression(expression->d.nonTerminal.left, context); const char* value2 = UI_GetStringFromExpression(expression->d.nonTerminal.right, context); switch (expression->type) { case EA_OPERATOR_STR_EQ: return Q_streq(value1, value2); case EA_OPERATOR_STR_NE: return !Q_streq(value1, value2); default: Com_Error(ERR_FATAL, "UI_GetBooleanFromExpression: (STRING2BOOL) Invalid expression type"); } } default: Com_Error(ERR_FATAL, "UI_GetBooleanFromExpression: Unsupported expression type: %i", expression->type); } }
/* ============ Cvar_Get If the variable already exists, the value will not be set unless CVAR_ROM The flags will be or'ed in if the variable exists. ============ */ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) { cvar_t *var; long hash; int index; if ( !var_name || ! var_value ) { Com_Error( ERR_FATAL, "Cvar_Get: NULL parameter" ); } if ( !Cvar_ValidateString( var_name ) ) { Com_Printf("invalid cvar name string: %s\n", var_name ); var_name = "BADNAME"; } #if 0 // FIXME: values with backslash happen if ( !Cvar_ValidateString( var_value ) ) { Com_Printf("invalid cvar value string: %s\n", var_value ); var_value = "BADVALUE"; } #endif var = Cvar_FindVar (var_name); if(var) { var_value = Cvar_Validate(var, var_value, qfalse); // if the C code is now specifying a variable that the user already // set a value for, take the new value as the reset value if(var->flags & CVAR_USER_CREATED) { var->flags &= ~CVAR_USER_CREATED; Z_Free( var->resetString ); var->resetString = CopyString( var_value ); if( (flags & CVAR_ROM) && !(flags & CVAR_ARCHIVE) ) { // this variable was set by the user, // so force it to value given by the engine. if(var->latchedString) Z_Free(var->latchedString); var->latchedString = CopyString(var_value); } } // Make sure the game code cannot mark engine-added variables as gamecode vars if(var->flags & CVAR_VM_CREATED) { if(!(flags & CVAR_VM_CREATED)) var->flags &= ~CVAR_VM_CREATED; } else { if(flags & CVAR_VM_CREATED) flags &= ~CVAR_VM_CREATED; } var->flags |= flags; // only allow one non-empty reset string without a warning if ( !var->resetString[0] ) { // we don't have a reset string yet Z_Free( var->resetString ); var->resetString = CopyString( var_value ); } else if ( var_value[0] && strcmp( var->resetString, var_value ) ) { Com_DPrintf( "Warning: cvar \"%s\" given initial values: \"%s\" and \"%s\"\n", var_name, var->resetString, var_value ); } // if we have a latched string, take that value now if ( var->latchedString ) { char *s; s = var->latchedString; var->latchedString = NULL; // otherwise cvar_set2 would free it Cvar_Set2( var_name, s, qtrue ); Z_Free( s ); } // ZOID--needs to be set so that cvars the game sets as // SERVERINFO get sent to clients cvar_modifiedFlags |= flags; return var; } // // allocate a new cvar // // find a free cvar for(index = 0; index < MAX_CVARS; index++) { if(!cvar_indexes[index].name) break; } if(index >= MAX_CVARS) { if(!com_errorEntered) Com_Error(ERR_FATAL, "Error: Too many cvars, cannot create a new one!"); return NULL; } var = &cvar_indexes[index]; if(index >= cvar_numIndexes) cvar_numIndexes = index + 1; var->name = CopyString (var_name); var->string = CopyString (var_value); var->modified = qtrue; var->modificationCount = 1; var->value = atof (var->string); var->integer = atoi(var->string); var->resetString = CopyString( var_value ); var->validate = qfalse; // link the variable in var->next = cvar_vars; if(cvar_vars) cvar_vars->prev = var; var->prev = NULL; cvar_vars = var; var->flags = flags; // note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo) cvar_modifiedFlags |= var->flags; hash = generateHashValue(var_name); var->hashIndex = hash; var->hashNext = hashTable[hash]; if(hashTable[hash]) hashTable[hash]->hashPrev = var; var->hashPrev = NULL; hashTable[hash] = var; return var; }
void Cmd_ExpandString (char *data, char *dest) { unsigned int c; char buf[255]; int i, len; cvar_t *var, *bestvar; int quotes = 0; char *str = NULL; int name_length = 0; #ifndef SERVERONLY extern int macro_length; #endif len = 0; while ( (c = *data) != 0) { if (c == '"') quotes++; if (c == '$' && !(quotes&1)) { data++; // Copy the text after '$' to a temp buffer i = 0; buf[0] = 0; bestvar = NULL; while ((c = *data) > 32) { if (c == '$') break; data++; buf[i++] = c; buf[i] = 0; if ( (var = Cvar_FindVar(buf)) != NULL ) bestvar = var; } #ifndef SERVERONLY if (dedicated) str = NULL; else { str = TP_MacroString (buf); name_length = macro_length; } if (bestvar && (!str || (strlen(bestvar->name) > macro_length))) { str = bestvar->string; name_length = strlen(bestvar->name); } #else if (bestvar) { str = bestvar->string; name_length = strlen(bestvar->name); } else str = NULL; #endif if (str) { // check buffer size if (len + strlen(str) >= 1024-1) break; strcpy(&dest[len], str); len += strlen(str); i = name_length; while (buf[i]) dest[len++] = buf[i++]; } else { // no matching cvar or macro dest[len++] = '$'; if (len + strlen(buf) >= 1024-1) break; strcpy (&dest[len], buf); len += strlen(buf); } } else { dest[len] = c; data++; len++; if (len >= 1024-1) break; } }; dest[len] = 0; }