CVarSystem.cpp 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. idCVar * idCVar::staticVars = NULL;
  23. /*
  24. ===============================================================================
  25. idInternalCVar
  26. ===============================================================================
  27. */
  28. class idInternalCVar : public idCVar {
  29. friend class idCVarSystemLocal;
  30. public:
  31. idInternalCVar( void );
  32. idInternalCVar( const char *newName, const char *newValue, int newFlags );
  33. idInternalCVar( const idCVar *cvar );
  34. virtual ~idInternalCVar( void );
  35. const char ** CopyValueStrings( const char **strings );
  36. void Update( const idCVar *cvar );
  37. void UpdateValue( void );
  38. void UpdateCheat( void );
  39. void Set( const char *newValue, bool force, bool fromServer );
  40. void Reset( void );
  41. private:
  42. idStr nameString; // name
  43. idStr resetString; // resetting will change to this value
  44. idStr valueString; // value
  45. idStr descriptionString; // description
  46. virtual void InternalSetString( const char *newValue );
  47. virtual void InternalServerSetString( const char *newValue );
  48. virtual void InternalSetBool( const bool newValue );
  49. virtual void InternalSetInteger( const int newValue );
  50. virtual void InternalSetFloat( const float newValue );
  51. };
  52. /*
  53. ============
  54. idInternalCVar::idInternalCVar
  55. ============
  56. */
  57. idInternalCVar::idInternalCVar( void ) {
  58. }
  59. /*
  60. ============
  61. idInternalCVar::idInternalCVar
  62. ============
  63. */
  64. idInternalCVar::idInternalCVar( const char *newName, const char *newValue, int newFlags ) {
  65. nameString = newName;
  66. name = nameString.c_str();
  67. valueString = newValue;
  68. value = valueString.c_str();
  69. resetString = newValue;
  70. descriptionString = "";
  71. description = descriptionString.c_str();
  72. flags = ( newFlags & ~CVAR_STATIC ) | CVAR_MODIFIED;
  73. valueMin = 1;
  74. valueMax = -1;
  75. valueStrings = NULL;
  76. valueCompletion = 0;
  77. UpdateValue();
  78. UpdateCheat();
  79. internalVar = this;
  80. }
  81. /*
  82. ============
  83. idInternalCVar::idInternalCVar
  84. ============
  85. */
  86. idInternalCVar::idInternalCVar( const idCVar *cvar ) {
  87. nameString = cvar->GetName();
  88. name = nameString.c_str();
  89. valueString = cvar->GetString();
  90. value = valueString.c_str();
  91. resetString = cvar->GetString();
  92. descriptionString = cvar->GetDescription();
  93. description = descriptionString.c_str();
  94. flags = cvar->GetFlags() | CVAR_MODIFIED;
  95. valueMin = cvar->GetMinValue();
  96. valueMax = cvar->GetMaxValue();
  97. valueStrings = CopyValueStrings( cvar->GetValueStrings() );
  98. valueCompletion = cvar->GetValueCompletion();
  99. UpdateValue();
  100. UpdateCheat();
  101. internalVar = this;
  102. }
  103. /*
  104. ============
  105. idInternalCVar::~idInternalCVar
  106. ============
  107. */
  108. idInternalCVar::~idInternalCVar( void ) {
  109. Mem_Free( valueStrings );
  110. valueStrings = NULL;
  111. }
  112. /*
  113. ============
  114. idInternalCVar::CopyValueStrings
  115. ============
  116. */
  117. const char **idInternalCVar::CopyValueStrings( const char **strings ) {
  118. int i, totalLength;
  119. const char **ptr;
  120. char *str;
  121. if ( !strings ) {
  122. return NULL;
  123. }
  124. totalLength = 0;
  125. for ( i = 0; strings[i] != NULL; i++ ) {
  126. totalLength += idStr::Length( strings[i] ) + 1;
  127. }
  128. ptr = (const char **) Mem_Alloc( ( i + 1 ) * sizeof( char * ) + totalLength );
  129. str = (char *) (((byte *)ptr) + ( i + 1 ) * sizeof( char * ) );
  130. for ( i = 0; strings[i] != NULL; i++ ) {
  131. ptr[i] = str;
  132. strcpy( str, strings[i] );
  133. str += idStr::Length( strings[i] ) + 1;
  134. }
  135. ptr[i] = NULL;
  136. return ptr;
  137. }
  138. /*
  139. ============
  140. idInternalCVar::Update
  141. ============
  142. */
  143. void idInternalCVar::Update( const idCVar *cvar ) {
  144. // if this is a statically declared variable
  145. if ( cvar->GetFlags() & CVAR_STATIC ) {
  146. if ( flags & CVAR_STATIC ) {
  147. // the code has more than one static declaration of the same variable, make sure they have the same properties
  148. if ( resetString.Icmp( cvar->GetString() ) != 0 ) {
  149. common->Warning( "CVar '%s' declared multiple times with different initial value", nameString.c_str() );
  150. }
  151. if ( ( flags & (CVAR_BOOL|CVAR_INTEGER|CVAR_FLOAT) ) != ( cvar->GetFlags() & (CVAR_BOOL|CVAR_INTEGER|CVAR_FLOAT) ) ) {
  152. common->Warning( "CVar '%s' declared multiple times with different type", nameString.c_str() );
  153. }
  154. if ( valueMin != cvar->GetMinValue() || valueMax != cvar->GetMaxValue() ) {
  155. common->Warning( "CVar '%s' declared multiple times with different minimum/maximum", nameString.c_str() );
  156. }
  157. }
  158. // the code is now specifying a variable that the user already set a value for, take the new value as the reset value
  159. resetString = cvar->GetString();
  160. descriptionString = cvar->GetDescription();
  161. description = descriptionString.c_str();
  162. valueMin = cvar->GetMinValue();
  163. valueMax = cvar->GetMaxValue();
  164. Mem_Free( valueStrings );
  165. valueStrings = CopyValueStrings( cvar->GetValueStrings() );
  166. valueCompletion = cvar->GetValueCompletion();
  167. UpdateValue();
  168. cvarSystem->SetModifiedFlags( cvar->GetFlags() );
  169. }
  170. flags |= cvar->GetFlags();
  171. UpdateCheat();
  172. // only allow one non-empty reset string without a warning
  173. if ( resetString.Length() == 0 ) {
  174. resetString = cvar->GetString();
  175. } else if ( cvar->GetString()[0] && resetString.Cmp( cvar->GetString() ) != 0 ) {
  176. common->Warning( "cvar \"%s\" given initial values: \"%s\" and \"%s\"\n", nameString.c_str(), resetString.c_str(), cvar->GetString() );
  177. }
  178. }
  179. /*
  180. ============
  181. idInternalCVar::UpdateValue
  182. ============
  183. */
  184. void idInternalCVar::UpdateValue( void ) {
  185. bool clamped = false;
  186. if ( flags & CVAR_BOOL ) {
  187. integerValue = ( atoi( value ) != 0 );
  188. floatValue = integerValue;
  189. if ( idStr::Icmp( value, "0" ) != 0 && idStr::Icmp( value, "1" ) != 0 ) {
  190. valueString = idStr( (bool)( integerValue != 0 ) );
  191. value = valueString.c_str();
  192. }
  193. } else if ( flags & CVAR_INTEGER ) {
  194. integerValue = (int)atoi( value );
  195. if ( valueMin < valueMax ) {
  196. if ( integerValue < valueMin ) {
  197. integerValue = (int)valueMin;
  198. clamped = true;
  199. } else if ( integerValue > valueMax ) {
  200. integerValue = (int)valueMax;
  201. clamped = true;
  202. }
  203. }
  204. if ( clamped || !idStr::IsNumeric( value ) || idStr::FindChar( value, '.' ) ) {
  205. valueString = idStr( integerValue );
  206. value = valueString.c_str();
  207. }
  208. floatValue = (float)integerValue;
  209. } else if ( flags & CVAR_FLOAT ) {
  210. floatValue = (float)atof( value );
  211. if ( valueMin < valueMax ) {
  212. if ( floatValue < valueMin ) {
  213. floatValue = valueMin;
  214. clamped = true;
  215. } else if ( floatValue > valueMax ) {
  216. floatValue = valueMax;
  217. clamped = true;
  218. }
  219. }
  220. if ( clamped || !idStr::IsNumeric( value ) ) {
  221. valueString = idStr( floatValue );
  222. value = valueString.c_str();
  223. }
  224. integerValue = (int)floatValue;
  225. } else {
  226. if ( valueStrings && valueStrings[0] ) {
  227. integerValue = 0;
  228. for ( int i = 0; valueStrings[i]; i++ ) {
  229. if ( valueString.Icmp( valueStrings[i] ) == 0 ) {
  230. integerValue = i;
  231. break;
  232. }
  233. }
  234. valueString = valueStrings[integerValue];
  235. value = valueString.c_str();
  236. floatValue = (float)integerValue;
  237. } else if ( valueString.Length() < 32 ) {
  238. floatValue = (float)atof( value );
  239. integerValue = (int)floatValue;
  240. } else {
  241. floatValue = 0.0f;
  242. integerValue = 0;
  243. }
  244. }
  245. }
  246. /*
  247. ============
  248. idInternalCVar::UpdateCheat
  249. ============
  250. */
  251. void idInternalCVar::UpdateCheat( void ) {
  252. // all variables are considered cheats except for a few types
  253. if ( flags & ( CVAR_NOCHEAT | CVAR_INIT | CVAR_ROM | CVAR_ARCHIVE | CVAR_USERINFO | CVAR_SERVERINFO | CVAR_NETWORKSYNC ) ) {
  254. flags &= ~CVAR_CHEAT;
  255. } else {
  256. flags |= CVAR_CHEAT;
  257. }
  258. }
  259. /*
  260. ============
  261. idInternalCVar::Set
  262. ============
  263. */
  264. void idInternalCVar::Set( const char *newValue, bool force, bool fromServer ) {
  265. if ( session && session->IsMultiplayer() && !fromServer ) {
  266. #ifndef ID_TYPEINFO
  267. if ( ( flags & CVAR_NETWORKSYNC ) && idAsyncNetwork::client.IsActive() ) {
  268. common->Printf( "%s is a synced over the network and cannot be changed on a multiplayer client.\n", nameString.c_str() );
  269. #if ID_ALLOW_CHEATS
  270. common->Printf( "ID_ALLOW_CHEATS override!\n" );
  271. #else
  272. return;
  273. #endif
  274. }
  275. #endif
  276. if ( ( flags & CVAR_CHEAT ) && !cvarSystem->GetCVarBool( "net_allowCheats" ) ) {
  277. common->Printf( "%s cannot be changed in multiplayer.\n", nameString.c_str() );
  278. #if ID_ALLOW_CHEATS
  279. common->Printf( "ID_ALLOW_CHEATS override!\n" );
  280. #else
  281. return;
  282. #endif
  283. }
  284. }
  285. if ( !newValue ) {
  286. newValue = resetString.c_str();
  287. }
  288. if ( !force ) {
  289. if ( flags & CVAR_ROM ) {
  290. common->Printf( "%s is read only.\n", nameString.c_str() );
  291. return;
  292. }
  293. if ( flags & CVAR_INIT ) {
  294. common->Printf( "%s is write protected.\n", nameString.c_str() );
  295. return;
  296. }
  297. }
  298. if ( valueString.Icmp( newValue ) == 0 ) {
  299. return;
  300. }
  301. valueString = newValue;
  302. value = valueString.c_str();
  303. UpdateValue();
  304. SetModified();
  305. cvarSystem->SetModifiedFlags( flags );
  306. }
  307. /*
  308. ============
  309. idInternalCVar::Reset
  310. ============
  311. */
  312. void idInternalCVar::Reset( void ) {
  313. valueString = resetString;
  314. value = valueString.c_str();
  315. UpdateValue();
  316. }
  317. /*
  318. ============
  319. idInternalCVar::InternalSetString
  320. ============
  321. */
  322. void idInternalCVar::InternalSetString( const char *newValue ) {
  323. Set( newValue, true, false );
  324. }
  325. /*
  326. ===============
  327. idInternalCVar::InternalServerSetString
  328. ===============
  329. */
  330. void idInternalCVar::InternalServerSetString( const char *newValue ) {
  331. Set( newValue, true, true );
  332. }
  333. /*
  334. ============
  335. idInternalCVar::InternalSetBool
  336. ============
  337. */
  338. void idInternalCVar::InternalSetBool( const bool newValue ) {
  339. Set( idStr( newValue ), true, false );
  340. }
  341. /*
  342. ============
  343. idInternalCVar::InternalSetInteger
  344. ============
  345. */
  346. void idInternalCVar::InternalSetInteger( const int newValue ) {
  347. Set( idStr( newValue ), true, false );
  348. }
  349. /*
  350. ============
  351. idInternalCVar::InternalSetFloat
  352. ============
  353. */
  354. void idInternalCVar::InternalSetFloat( const float newValue ) {
  355. Set( idStr( newValue ), true, false );
  356. }
  357. /*
  358. ===============================================================================
  359. idCVarSystemLocal
  360. ===============================================================================
  361. */
  362. class idCVarSystemLocal : public idCVarSystem {
  363. public:
  364. idCVarSystemLocal( void );
  365. virtual ~idCVarSystemLocal( void ) {}
  366. virtual void Init( void );
  367. virtual void Shutdown( void );
  368. virtual bool IsInitialized( void ) const;
  369. virtual void Register( idCVar *cvar );
  370. virtual idCVar * Find( const char *name );
  371. virtual void SetCVarString( const char *name, const char *value, int flags = 0 );
  372. virtual void SetCVarBool( const char *name, const bool value, int flags = 0 );
  373. virtual void SetCVarInteger( const char *name, const int value, int flags = 0 );
  374. virtual void SetCVarFloat( const char *name, const float value, int flags = 0 );
  375. virtual const char * GetCVarString( const char *name ) const;
  376. virtual bool GetCVarBool( const char *name ) const;
  377. virtual int GetCVarInteger( const char *name ) const;
  378. virtual float GetCVarFloat( const char *name ) const;
  379. virtual bool Command( const idCmdArgs &args );
  380. virtual void CommandCompletion( void(*callback)( const char *s ) );
  381. virtual void ArgCompletion( const char *cmdString, void(*callback)( const char *s ) );
  382. virtual void SetModifiedFlags( int flags );
  383. virtual int GetModifiedFlags( void ) const;
  384. virtual void ClearModifiedFlags( int flags );
  385. virtual void ResetFlaggedVariables( int flags );
  386. virtual void RemoveFlaggedAutoCompletion( int flags );
  387. virtual void WriteFlaggedVariables( int flags, const char *setCmd, idFile *f ) const;
  388. virtual const idDict * MoveCVarsToDict( int flags ) const;
  389. virtual void SetCVarsFromDict( const idDict &dict );
  390. void RegisterInternal( idCVar *cvar );
  391. idInternalCVar * FindInternal( const char *name ) const;
  392. void SetInternal( const char *name, const char *value, int flags );
  393. private:
  394. bool initialized;
  395. idList<idInternalCVar*> cvars;
  396. idHashIndex cvarHash;
  397. int modifiedFlags;
  398. // use a static dictionary to MoveCVarsToDict can be used from game
  399. static idDict moveCVarsToDict;
  400. private:
  401. static void Toggle_f( const idCmdArgs &args );
  402. static void Set_f( const idCmdArgs &args );
  403. static void SetS_f( const idCmdArgs &args );
  404. static void SetU_f( const idCmdArgs &args );
  405. static void SetT_f( const idCmdArgs &args );
  406. static void SetA_f( const idCmdArgs &args );
  407. static void Reset_f( const idCmdArgs &args );
  408. static void ListByFlags( const idCmdArgs &args, cvarFlags_t flags );
  409. static void List_f( const idCmdArgs &args );
  410. static void Restart_f( const idCmdArgs &args );
  411. };
  412. idCVarSystemLocal localCVarSystem;
  413. idCVarSystem * cvarSystem = &localCVarSystem;
  414. idDict idCVarSystemLocal::moveCVarsToDict;
  415. #define NUM_COLUMNS 77 // 78 - 1
  416. #define NUM_NAME_CHARS 33
  417. #define NUM_DESCRIPTION_CHARS ( NUM_COLUMNS - NUM_NAME_CHARS )
  418. #define FORMAT_STRING "%-32s "
  419. const char *CreateColumn( const char *text, int columnWidth, const char *indent, idStr &string ) {
  420. int i, lastLine;
  421. string.Clear();
  422. for ( lastLine = i = 0; text[i] != '\0'; i++ ) {
  423. if ( i - lastLine >= columnWidth || text[i] == '\n' ) {
  424. while( i > 0 && text[i] > ' ' && text[i] != '/' && text[i] != ',' && text[i] != '\\' ) {
  425. i--;
  426. }
  427. while( lastLine < i ) {
  428. string.Append( text[lastLine++] );
  429. }
  430. string.Append( indent );
  431. lastLine++;
  432. }
  433. }
  434. while( lastLine < i ) {
  435. string.Append( text[lastLine++] );
  436. }
  437. return string.c_str();
  438. }
  439. /*
  440. ============
  441. idCVarSystemLocal::FindInternal
  442. ============
  443. */
  444. idInternalCVar *idCVarSystemLocal::FindInternal( const char *name ) const {
  445. int hash = cvarHash.GenerateKey( name, false );
  446. for ( int i = cvarHash.First( hash ); i != -1; i = cvarHash.Next( i ) ) {
  447. if ( cvars[i]->nameString.Icmp( name ) == 0 ) {
  448. return cvars[i];
  449. }
  450. }
  451. return NULL;
  452. }
  453. /*
  454. ============
  455. idCVarSystemLocal::SetInternal
  456. ============
  457. */
  458. void idCVarSystemLocal::SetInternal( const char *name, const char *value, int flags ) {
  459. int hash;
  460. idInternalCVar *internal;
  461. internal = FindInternal( name );
  462. if ( internal ) {
  463. internal->InternalSetString( value );
  464. internal->flags |= flags & ~CVAR_STATIC;
  465. internal->UpdateCheat();
  466. } else {
  467. internal = new idInternalCVar( name, value, flags );
  468. hash = cvarHash.GenerateKey( internal->nameString.c_str(), false );
  469. cvarHash.Add( hash, cvars.Append( internal ) );
  470. }
  471. }
  472. /*
  473. ============
  474. idCVarSystemLocal::idCVarSystemLocal
  475. ============
  476. */
  477. idCVarSystemLocal::idCVarSystemLocal( void ) {
  478. initialized = false;
  479. modifiedFlags = 0;
  480. }
  481. /*
  482. ============
  483. idCVarSystemLocal::Init
  484. ============
  485. */
  486. void idCVarSystemLocal::Init( void ) {
  487. modifiedFlags = 0;
  488. cmdSystem->AddCommand( "toggle", Toggle_f, CMD_FL_SYSTEM, "toggles a cvar" );
  489. cmdSystem->AddCommand( "set", Set_f, CMD_FL_SYSTEM, "sets a cvar" );
  490. cmdSystem->AddCommand( "sets", SetS_f, CMD_FL_SYSTEM, "sets a cvar and flags it as server info" );
  491. cmdSystem->AddCommand( "setu", SetU_f, CMD_FL_SYSTEM, "sets a cvar and flags it as user info" );
  492. cmdSystem->AddCommand( "sett", SetT_f, CMD_FL_SYSTEM, "sets a cvar and flags it as tool" );
  493. cmdSystem->AddCommand( "seta", SetA_f, CMD_FL_SYSTEM, "sets a cvar and flags it as archive" );
  494. cmdSystem->AddCommand( "reset", Reset_f, CMD_FL_SYSTEM, "resets a cvar" );
  495. cmdSystem->AddCommand( "listCvars", List_f, CMD_FL_SYSTEM, "lists cvars" );
  496. cmdSystem->AddCommand( "cvar_restart", Restart_f, CMD_FL_SYSTEM, "restart the cvar system" );
  497. initialized = true;
  498. }
  499. /*
  500. ============
  501. idCVarSystemLocal::Shutdown
  502. ============
  503. */
  504. void idCVarSystemLocal::Shutdown( void ) {
  505. cvars.DeleteContents( true );
  506. cvarHash.Free();
  507. moveCVarsToDict.Clear();
  508. initialized = false;
  509. }
  510. /*
  511. ============
  512. idCVarSystemLocal::IsInitialized
  513. ============
  514. */
  515. bool idCVarSystemLocal::IsInitialized( void ) const {
  516. return initialized;
  517. }
  518. /*
  519. ============
  520. idCVarSystemLocal::Register
  521. ============
  522. */
  523. void idCVarSystemLocal::Register( idCVar *cvar ) {
  524. int hash;
  525. idInternalCVar *internal;
  526. cvar->SetInternalVar( cvar );
  527. internal = FindInternal( cvar->GetName() );
  528. if ( internal ) {
  529. internal->Update( cvar );
  530. } else {
  531. internal = new idInternalCVar( cvar );
  532. hash = cvarHash.GenerateKey( internal->nameString.c_str(), false );
  533. cvarHash.Add( hash, cvars.Append( internal ) );
  534. }
  535. cvar->SetInternalVar( internal );
  536. }
  537. /*
  538. ============
  539. idCVarSystemLocal::Find
  540. ============
  541. */
  542. idCVar *idCVarSystemLocal::Find( const char *name ) {
  543. return FindInternal( name );
  544. }
  545. /*
  546. ============
  547. idCVarSystemLocal::SetCVarString
  548. ============
  549. */
  550. void idCVarSystemLocal::SetCVarString( const char *name, const char *value, int flags ) {
  551. SetInternal( name, value, flags );
  552. }
  553. /*
  554. ============
  555. idCVarSystemLocal::SetCVarBool
  556. ============
  557. */
  558. void idCVarSystemLocal::SetCVarBool( const char *name, const bool value, int flags ) {
  559. SetInternal( name, idStr( value ), flags );
  560. }
  561. /*
  562. ============
  563. idCVarSystemLocal::SetCVarInteger
  564. ============
  565. */
  566. void idCVarSystemLocal::SetCVarInteger( const char *name, const int value, int flags ) {
  567. SetInternal( name, idStr( value ), flags );
  568. }
  569. /*
  570. ============
  571. idCVarSystemLocal::SetCVarFloat
  572. ============
  573. */
  574. void idCVarSystemLocal::SetCVarFloat( const char *name, const float value, int flags ) {
  575. SetInternal( name, idStr( value ), flags );
  576. }
  577. /*
  578. ============
  579. idCVarSystemLocal::GetCVarString
  580. ============
  581. */
  582. const char *idCVarSystemLocal::GetCVarString( const char *name ) const {
  583. idInternalCVar *internal = FindInternal( name );
  584. if ( internal ) {
  585. return internal->GetString();
  586. }
  587. return "";
  588. }
  589. /*
  590. ============
  591. idCVarSystemLocal::GetCVarBool
  592. ============
  593. */
  594. bool idCVarSystemLocal::GetCVarBool( const char *name ) const {
  595. idInternalCVar *internal = FindInternal( name );
  596. if ( internal ) {
  597. return internal->GetBool();
  598. }
  599. return false;
  600. }
  601. /*
  602. ============
  603. idCVarSystemLocal::GetCVarInteger
  604. ============
  605. */
  606. int idCVarSystemLocal::GetCVarInteger( const char *name ) const {
  607. idInternalCVar *internal = FindInternal( name );
  608. if ( internal ) {
  609. return internal->GetInteger();
  610. }
  611. return 0;
  612. }
  613. /*
  614. ============
  615. idCVarSystemLocal::GetCVarFloat
  616. ============
  617. */
  618. float idCVarSystemLocal::GetCVarFloat( const char *name ) const {
  619. idInternalCVar *internal = FindInternal( name );
  620. if ( internal ) {
  621. return internal->GetFloat();
  622. }
  623. return 0.0f;
  624. }
  625. /*
  626. ============
  627. idCVarSystemLocal::Command
  628. ============
  629. */
  630. bool idCVarSystemLocal::Command( const idCmdArgs &args ) {
  631. idInternalCVar *internal;
  632. internal = FindInternal( args.Argv( 0 ) );
  633. if ( internal == NULL ) {
  634. return false;
  635. }
  636. if ( args.Argc() == 1 ) {
  637. // print the variable
  638. common->Printf( "\"%s\" is:\"%s\"" S_COLOR_WHITE " default:\"%s\"\n",
  639. internal->nameString.c_str(), internal->valueString.c_str(), internal->resetString.c_str() );
  640. if ( idStr::Length( internal->GetDescription() ) > 0 ) {
  641. common->Printf( S_COLOR_WHITE "%s\n", internal->GetDescription() );
  642. }
  643. } else {
  644. // set the value
  645. internal->Set( args.Args(), false, false );
  646. }
  647. return true;
  648. }
  649. /*
  650. ============
  651. idCVarSystemLocal::CommandCompletion
  652. ============
  653. */
  654. void idCVarSystemLocal::CommandCompletion( void(*callback)( const char *s ) ) {
  655. for( int i = 0; i < cvars.Num(); i++ ) {
  656. callback( cvars[i]->GetName() );
  657. }
  658. }
  659. /*
  660. ============
  661. idCVarSystemLocal::ArgCompletion
  662. ============
  663. */
  664. void idCVarSystemLocal::ArgCompletion( const char *cmdString, void(*callback)( const char *s ) ) {
  665. idCmdArgs args;
  666. args.TokenizeString( cmdString, false );
  667. for( int i = 0; i < cvars.Num(); i++ ) {
  668. if ( !cvars[i]->valueCompletion ) {
  669. continue;
  670. }
  671. if ( idStr::Icmp( args.Argv( 0 ), cvars[i]->nameString.c_str() ) == 0 ) {
  672. cvars[i]->valueCompletion( args, callback );
  673. break;
  674. }
  675. }
  676. }
  677. /*
  678. ============
  679. idCVarSystemLocal::SetModifiedFlags
  680. ============
  681. */
  682. void idCVarSystemLocal::SetModifiedFlags( int flags ) {
  683. modifiedFlags |= flags;
  684. }
  685. /*
  686. ============
  687. idCVarSystemLocal::GetModifiedFlags
  688. ============
  689. */
  690. int idCVarSystemLocal::GetModifiedFlags( void ) const {
  691. return modifiedFlags;
  692. }
  693. /*
  694. ============
  695. idCVarSystemLocal::ClearModifiedFlags
  696. ============
  697. */
  698. void idCVarSystemLocal::ClearModifiedFlags( int flags ) {
  699. modifiedFlags &= ~flags;
  700. }
  701. /*
  702. ============
  703. idCVarSystemLocal::ResetFlaggedVariables
  704. ============
  705. */
  706. void idCVarSystemLocal::ResetFlaggedVariables( int flags ) {
  707. for( int i = 0; i < cvars.Num(); i++ ) {
  708. idInternalCVar *cvar = cvars[i];
  709. if ( cvar->GetFlags() & flags ) {
  710. cvar->Set( NULL, true, true );
  711. }
  712. }
  713. }
  714. /*
  715. ============
  716. idCVarSystemLocal::RemoveFlaggedAutoCompletion
  717. ============
  718. */
  719. void idCVarSystemLocal::RemoveFlaggedAutoCompletion( int flags ) {
  720. for( int i = 0; i < cvars.Num(); i++ ) {
  721. idInternalCVar *cvar = cvars[i];
  722. if ( cvar->GetFlags() & flags ) {
  723. cvar->valueCompletion = NULL;
  724. }
  725. }
  726. }
  727. /*
  728. ============
  729. idCVarSystemLocal::WriteFlaggedVariables
  730. Appends lines containing "set variable value" for all variables
  731. with the "flags" flag set to true.
  732. ============
  733. */
  734. void idCVarSystemLocal::WriteFlaggedVariables( int flags, const char *setCmd, idFile *f ) const {
  735. for( int i = 0; i < cvars.Num(); i++ ) {
  736. idInternalCVar *cvar = cvars[i];
  737. if ( cvar->GetFlags() & flags ) {
  738. f->Printf( "%s %s \"%s\"\n", setCmd, cvar->GetName(), cvar->GetString() );
  739. }
  740. }
  741. }
  742. /*
  743. ============
  744. idCVarSystemLocal::MoveCVarsToDict
  745. ============
  746. */
  747. const idDict* idCVarSystemLocal::MoveCVarsToDict( int flags ) const {
  748. moveCVarsToDict.Clear();
  749. for( int i = 0; i < cvars.Num(); i++ ) {
  750. idCVar *cvar = cvars[i];
  751. if ( cvar->GetFlags() & flags ) {
  752. moveCVarsToDict.Set( cvar->GetName(), cvar->GetString() );
  753. }
  754. }
  755. return &moveCVarsToDict;
  756. }
  757. /*
  758. ============
  759. idCVarSystemLocal::SetCVarsFromDict
  760. ============
  761. */
  762. void idCVarSystemLocal::SetCVarsFromDict( const idDict &dict ) {
  763. idInternalCVar *internal;
  764. for( int i = 0; i < dict.GetNumKeyVals(); i++ ) {
  765. const idKeyValue *kv = dict.GetKeyVal( i );
  766. internal = FindInternal( kv->GetKey() );
  767. if ( internal ) {
  768. internal->InternalServerSetString( kv->GetValue() );
  769. }
  770. }
  771. }
  772. /*
  773. ============
  774. idCVarSystemLocal::Toggle_f
  775. ============
  776. */
  777. void idCVarSystemLocal::Toggle_f( const idCmdArgs &args ) {
  778. int argc, i;
  779. float current, set;
  780. const char *text;
  781. argc = args.Argc();
  782. if ( argc < 2 ) {
  783. common->Printf ("usage:\n"
  784. " toggle <variable> - toggles between 0 and 1\n"
  785. " toggle <variable> <value> - toggles between 0 and <value>\n"
  786. " toggle <variable> [string 1] [string 2]...[string n] - cycles through all strings\n");
  787. return;
  788. }
  789. idInternalCVar *cvar = localCVarSystem.FindInternal( args.Argv( 1 ) );
  790. if ( cvar == NULL ) {
  791. common->Warning( "Toggle_f: cvar \"%s\" not found", args.Argv( 1 ) );
  792. return;
  793. }
  794. if ( argc > 3 ) {
  795. // cycle through multiple values
  796. text = cvar->GetString();
  797. for( i = 2; i < argc; i++ ) {
  798. if ( !idStr::Icmp( text, args.Argv( i ) ) ) {
  799. // point to next value
  800. i++;
  801. break;
  802. }
  803. }
  804. if ( i >= argc ) {
  805. i = 2;
  806. }
  807. common->Printf( "set %s = %s\n", args.Argv(1), args.Argv( i ) );
  808. cvar->Set( va("%s", args.Argv( i ) ), false, false );
  809. } else {
  810. // toggle between 0 and 1
  811. current = cvar->GetFloat();
  812. if ( argc == 3 ) {
  813. set = atof( args.Argv( 2 ) );
  814. } else {
  815. set = 1.0f;
  816. }
  817. if ( current == 0.0f ) {
  818. current = set;
  819. } else {
  820. current = 0.0f;
  821. }
  822. common->Printf( "set %s = %f\n", args.Argv(1), current );
  823. cvar->Set( idStr( current ), false, false );
  824. }
  825. }
  826. /*
  827. ============
  828. idCVarSystemLocal::Set_f
  829. ============
  830. */
  831. void idCVarSystemLocal::Set_f( const idCmdArgs &args ) {
  832. const char *str;
  833. str = args.Args( 2, args.Argc() - 1 );
  834. localCVarSystem.SetCVarString( args.Argv(1), str );
  835. }
  836. /*
  837. ============
  838. idCVarSystemLocal::SetS_f
  839. ============
  840. */
  841. void idCVarSystemLocal::SetS_f( const idCmdArgs &args ) {
  842. idInternalCVar *cvar;
  843. Set_f( args );
  844. cvar = localCVarSystem.FindInternal( args.Argv( 1 ) );
  845. if ( !cvar ) {
  846. return;
  847. }
  848. cvar->flags |= CVAR_SERVERINFO | CVAR_ARCHIVE;
  849. }
  850. /*
  851. ============
  852. idCVarSystemLocal::SetU_f
  853. ============
  854. */
  855. void idCVarSystemLocal::SetU_f( const idCmdArgs &args ) {
  856. idInternalCVar *cvar;
  857. Set_f( args );
  858. cvar = localCVarSystem.FindInternal( args.Argv( 1 ) );
  859. if ( !cvar ) {
  860. return;
  861. }
  862. cvar->flags |= CVAR_USERINFO | CVAR_ARCHIVE;
  863. }
  864. /*
  865. ============
  866. idCVarSystemLocal::SetT_f
  867. ============
  868. */
  869. void idCVarSystemLocal::SetT_f( const idCmdArgs &args ) {
  870. idInternalCVar *cvar;
  871. Set_f( args );
  872. cvar = localCVarSystem.FindInternal( args.Argv( 1 ) );
  873. if ( !cvar ) {
  874. return;
  875. }
  876. cvar->flags |= CVAR_TOOL;
  877. }
  878. /*
  879. ============
  880. idCVarSystemLocal::SetA_f
  881. ============
  882. */
  883. void idCVarSystemLocal::SetA_f( const idCmdArgs &args ) {
  884. idInternalCVar *cvar;
  885. Set_f( args );
  886. cvar = localCVarSystem.FindInternal( args.Argv( 1 ) );
  887. if ( !cvar ) {
  888. return;
  889. }
  890. // FIXME: enable this for ship, so mods can store extra data
  891. // but during development we don't want obsolete cvars to continue
  892. // to be saved
  893. // cvar->flags |= CVAR_ARCHIVE;
  894. }
  895. /*
  896. ============
  897. idCVarSystemLocal::Reset_f
  898. ============
  899. */
  900. void idCVarSystemLocal::Reset_f( const idCmdArgs &args ) {
  901. idInternalCVar *cvar;
  902. if ( args.Argc() != 2 ) {
  903. common->Printf ("usage: reset <variable>\n");
  904. return;
  905. }
  906. cvar = localCVarSystem.FindInternal( args.Argv( 1 ) );
  907. if ( !cvar ) {
  908. return;
  909. }
  910. cvar->Reset();
  911. }
  912. /*
  913. ============
  914. idCVarSystemLocal::ListByFlags
  915. ============
  916. */
  917. // NOTE: the const wonkyness is required to make msvc happy
  918. template<>
  919. ID_INLINE int idListSortCompare( const idInternalCVar * const *a, const idInternalCVar * const *b ) {
  920. return idStr::Icmp( (*a)->GetName(), (*b)->GetName() );
  921. }
  922. void idCVarSystemLocal::ListByFlags( const idCmdArgs &args, cvarFlags_t flags ) {
  923. int i, argNum;
  924. idStr match, indent, string;
  925. const idInternalCVar *cvar;
  926. idList<const idInternalCVar *>cvarList;
  927. enum {
  928. SHOW_VALUE,
  929. SHOW_DESCRIPTION,
  930. SHOW_TYPE,
  931. SHOW_FLAGS
  932. } show;
  933. argNum = 1;
  934. show = SHOW_VALUE;
  935. if ( idStr::Icmp( args.Argv( argNum ), "-" ) == 0 || idStr::Icmp( args.Argv( argNum ), "/" ) == 0 ) {
  936. if ( idStr::Icmp( args.Argv( argNum + 1 ), "help" ) == 0 || idStr::Icmp( args.Argv( argNum + 1 ), "?" ) == 0 ) {
  937. argNum = 3;
  938. show = SHOW_DESCRIPTION;
  939. } else if ( idStr::Icmp( args.Argv( argNum + 1 ), "type" ) == 0 || idStr::Icmp( args.Argv( argNum + 1 ), "range" ) == 0 ) {
  940. argNum = 3;
  941. show = SHOW_TYPE;
  942. } else if ( idStr::Icmp( args.Argv( argNum + 1 ), "flags" ) == 0 ) {
  943. argNum = 3;
  944. show = SHOW_FLAGS;
  945. }
  946. }
  947. if ( args.Argc() > argNum ) {
  948. match = args.Args( argNum, -1 );
  949. match.Replace( " ", "" );
  950. } else {
  951. match = "";
  952. }
  953. for ( i = 0; i < localCVarSystem.cvars.Num(); i++ ) {
  954. cvar = localCVarSystem.cvars[i];
  955. if ( !( cvar->GetFlags() & flags ) ) {
  956. continue;
  957. }
  958. if ( match.Length() && !cvar->nameString.Filter( match, false ) ) {
  959. continue;
  960. }
  961. cvarList.Append( cvar );
  962. }
  963. cvarList.Sort();
  964. switch( show ) {
  965. case SHOW_VALUE: {
  966. for ( i = 0; i < cvarList.Num(); i++ ) {
  967. cvar = cvarList[i];
  968. common->Printf( FORMAT_STRING S_COLOR_WHITE "\"%s\"\n", cvar->nameString.c_str(), cvar->valueString.c_str() );
  969. }
  970. break;
  971. }
  972. case SHOW_DESCRIPTION: {
  973. indent.Fill( ' ', NUM_NAME_CHARS );
  974. indent.Insert( "\n", 0 );
  975. for ( i = 0; i < cvarList.Num(); i++ ) {
  976. cvar = cvarList[i];
  977. common->Printf( FORMAT_STRING S_COLOR_WHITE "%s\n", cvar->nameString.c_str(), CreateColumn( cvar->GetDescription(), NUM_DESCRIPTION_CHARS, indent, string ) );
  978. }
  979. break;
  980. }
  981. case SHOW_TYPE: {
  982. for ( i = 0; i < cvarList.Num(); i++ ) {
  983. cvar = cvarList[i];
  984. if ( cvar->GetFlags() & CVAR_BOOL ) {
  985. common->Printf( FORMAT_STRING S_COLOR_CYAN "bool\n", cvar->GetName() );
  986. } else if ( cvar->GetFlags() & CVAR_INTEGER ) {
  987. if ( cvar->GetMinValue() < cvar->GetMaxValue() ) {
  988. common->Printf( FORMAT_STRING S_COLOR_GREEN "int " S_COLOR_WHITE "[%d, %d]\n", cvar->GetName(), (int) cvar->GetMinValue(), (int) cvar->GetMaxValue() );
  989. } else {
  990. common->Printf( FORMAT_STRING S_COLOR_GREEN "int\n", cvar->GetName() );
  991. }
  992. } else if ( cvar->GetFlags() & CVAR_FLOAT ) {
  993. if ( cvar->GetMinValue() < cvar->GetMaxValue() ) {
  994. common->Printf( FORMAT_STRING S_COLOR_RED "float " S_COLOR_WHITE "[%s, %s]\n", cvar->GetName(), idStr( cvar->GetMinValue() ).c_str(), idStr( cvar->GetMaxValue() ).c_str() );
  995. } else {
  996. common->Printf( FORMAT_STRING S_COLOR_RED "float\n", cvar->GetName() );
  997. }
  998. } else if ( cvar->GetValueStrings() ) {
  999. common->Printf( FORMAT_STRING S_COLOR_WHITE "string " S_COLOR_WHITE "[", cvar->GetName() );
  1000. for ( int j = 0; cvar->GetValueStrings()[j] != NULL; j++ ) {
  1001. if ( j ) {
  1002. common->Printf( S_COLOR_WHITE ", %s", cvar->GetValueStrings()[j] );
  1003. } else {
  1004. common->Printf( S_COLOR_WHITE "%s", cvar->GetValueStrings()[j] );
  1005. }
  1006. }
  1007. common->Printf( S_COLOR_WHITE "]\n" );
  1008. } else {
  1009. common->Printf( FORMAT_STRING S_COLOR_WHITE "string\n", cvar->GetName() );
  1010. }
  1011. }
  1012. break;
  1013. }
  1014. case SHOW_FLAGS: {
  1015. for ( i = 0; i < cvarList.Num(); i++ ) {
  1016. cvar = cvarList[i];
  1017. common->Printf( FORMAT_STRING, cvar->GetName() );
  1018. string = "";
  1019. if ( cvar->GetFlags() & CVAR_BOOL ) {
  1020. string += S_COLOR_CYAN "B ";
  1021. } else if ( cvar->GetFlags() & CVAR_INTEGER ) {
  1022. string += S_COLOR_GREEN "I ";
  1023. } else if ( cvar->GetFlags() & CVAR_FLOAT ) {
  1024. string += S_COLOR_RED "F ";
  1025. } else {
  1026. string += S_COLOR_WHITE "S ";
  1027. }
  1028. if ( cvar->GetFlags() & CVAR_SYSTEM ) {
  1029. string += S_COLOR_WHITE "SYS ";
  1030. } else if ( cvar->GetFlags() & CVAR_RENDERER ) {
  1031. string += S_COLOR_WHITE "RNDR ";
  1032. } else if ( cvar->GetFlags() & CVAR_SOUND ) {
  1033. string += S_COLOR_WHITE "SND ";
  1034. } else if ( cvar->GetFlags() & CVAR_GUI ) {
  1035. string += S_COLOR_WHITE "GUI ";
  1036. } else if ( cvar->GetFlags() & CVAR_GAME ) {
  1037. string += S_COLOR_WHITE "GAME ";
  1038. } else if ( cvar->GetFlags() & CVAR_TOOL ) {
  1039. string += S_COLOR_WHITE "TOOL ";
  1040. } else {
  1041. string += S_COLOR_WHITE " ";
  1042. }
  1043. string += ( cvar->GetFlags() & CVAR_USERINFO ) ? "UI " : " ";
  1044. string += ( cvar->GetFlags() & CVAR_SERVERINFO ) ? "SI " : " ";
  1045. string += ( cvar->GetFlags() & CVAR_STATIC ) ? "ST " : " ";
  1046. string += ( cvar->GetFlags() & CVAR_CHEAT ) ? "CH " : " ";
  1047. string += ( cvar->GetFlags() & CVAR_INIT ) ? "IN " : " ";
  1048. string += ( cvar->GetFlags() & CVAR_ROM ) ? "RO " : " ";
  1049. string += ( cvar->GetFlags() & CVAR_ARCHIVE ) ? "AR " : " ";
  1050. string += ( cvar->GetFlags() & CVAR_MODIFIED ) ? "MO " : " ";
  1051. string += "\n";
  1052. common->Printf( string );
  1053. }
  1054. break;
  1055. }
  1056. }
  1057. common->Printf( "\n%i cvars listed\n\n", cvarList.Num() );
  1058. common->Printf( "listCvar [search string] = list cvar values\n"
  1059. "listCvar -help [search string] = list cvar descriptions\n"
  1060. "listCvar -type [search string] = list cvar types\n"
  1061. "listCvar -flags [search string] = list cvar flags\n" );
  1062. }
  1063. /*
  1064. ============
  1065. idCVarSystemLocal::List_f
  1066. ============
  1067. */
  1068. void idCVarSystemLocal::List_f( const idCmdArgs &args ) {
  1069. ListByFlags( args, CVAR_ALL );
  1070. }
  1071. /*
  1072. ============
  1073. idCVarSystemLocal::Restart_f
  1074. ============
  1075. */
  1076. void idCVarSystemLocal::Restart_f( const idCmdArgs &args ) {
  1077. int i, hash;
  1078. idInternalCVar *cvar;
  1079. for ( i = 0; i < localCVarSystem.cvars.Num(); i++ ) {
  1080. cvar = localCVarSystem.cvars[i];
  1081. // don't mess with rom values
  1082. if ( cvar->flags & ( CVAR_ROM | CVAR_INIT ) ) {
  1083. continue;
  1084. }
  1085. // throw out any variables the user created
  1086. if ( !( cvar->flags & CVAR_STATIC ) ) {
  1087. hash = localCVarSystem.cvarHash.GenerateKey( cvar->nameString, false );
  1088. delete cvar;
  1089. localCVarSystem.cvars.RemoveIndex( i );
  1090. localCVarSystem.cvarHash.RemoveIndex( hash, i );
  1091. i--;
  1092. continue;
  1093. }
  1094. cvar->Reset();
  1095. }
  1096. }