UserPreferences.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program 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. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. ///////////////////////////////////////////////////////////////////////////////////////
  24. // FILE: UserPreferences.cpp
  25. // Author: Matthew D. Campbell, April 2002
  26. // Description: Saving/Loading of user preferences
  27. ///////////////////////////////////////////////////////////////////////////////////////
  28. //-----------------------------------------------------------------------------
  29. // SYSTEM INCLUDES ////////////////////////////////////////////////////////////
  30. //-----------------------------------------------------------------------------
  31. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  32. //-----------------------------------------------------------------------------
  33. // USER INCLUDES //////////////////////////////////////////////////////////////
  34. //-----------------------------------------------------------------------------
  35. #include "Common/GameSpyMiscPreferences.h"
  36. #include "Common/UserPreferences.h"
  37. #include "Common/LadderPreferences.h"
  38. #include "Common/Player.h"
  39. #include "Common/PlayerTemplate.h"
  40. #include "Common/Registry.h"
  41. #include "Common/QuickmatchPreferences.h"
  42. #include "Common/CustomMatchPreferences.h"
  43. #include "Common/IgnorePreferences.h"
  44. #include "Common/QuotedPrintable.h"
  45. #include "Common/MultiplayerSettings.h"
  46. #include "GameClient/MapUtil.h"
  47. #include "GameClient/ChallengeGenerals.h"
  48. #include "GameNetwork/GameSpy/PeerDefs.h"
  49. #ifdef _INTERNAL
  50. // for occasional debugging...
  51. //#pragma optimize("", off)
  52. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  53. #endif
  54. //-----------------------------------------------------------------------------
  55. // DEFINES ////////////////////////////////////////////////////////////////////
  56. //-----------------------------------------------------------------------------
  57. //-----------------------------------------------------------------------------
  58. // PRIVATE TYPES //////////////////////////////////////////////////////////////
  59. //-----------------------------------------------------------------------------
  60. //-----------------------------------------------------------------------------
  61. // PRIVATE DATA ///////////////////////////////////////////////////////////////
  62. //-----------------------------------------------------------------------------
  63. //-----------------------------------------------------------------------------
  64. // PUBLIC DATA ////////////////////////////////////////////////////////////////
  65. //-----------------------------------------------------------------------------
  66. //-----------------------------------------------------------------------------
  67. // PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
  68. //-----------------------------------------------------------------------------
  69. //-----------------------------------------------------------------------------
  70. // PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
  71. //-----------------------------------------------------------------------------
  72. static AsciiString intAsStr(Int val)
  73. {
  74. AsciiString ret;
  75. ret.format("%d", val);
  76. return ret;
  77. }
  78. static AsciiString boolAsStr(Bool val)
  79. {
  80. AsciiString ret;
  81. ret.format("%d", val);
  82. return ret;
  83. }
  84. static AsciiString realAsStr(Real val)
  85. {
  86. AsciiString ret;
  87. ret.format("%g", val);
  88. return ret;
  89. }
  90. //-----------------------------------------------------------------------------
  91. // PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
  92. //-----------------------------------------------------------------------------
  93. //-----------------------------------------------------------------------------
  94. // UserPreferences Class
  95. //-----------------------------------------------------------------------------
  96. UserPreferences::UserPreferences( void )
  97. {
  98. }
  99. UserPreferences::~UserPreferences( void )
  100. {
  101. }
  102. #define LINE_LEN 2048
  103. Bool UserPreferences::load(AsciiString fname)
  104. {
  105. // if (strstr(fname.str(), "\\"))
  106. // throw INI_INVALID_DATA; // must be a leaf name
  107. m_filename = TheGlobalData->getPath_UserData();
  108. m_filename.concat(fname);
  109. FILE *fp = fopen(m_filename.str(), "r");
  110. if (fp)
  111. {
  112. char buf[LINE_LEN];
  113. while( fgets( buf, LINE_LEN, fp ) != NULL )
  114. {
  115. AsciiString line = buf;
  116. line.trim();
  117. AsciiString key, val;
  118. line.nextToken(&key, "=");
  119. val = line.str() + 1;
  120. key.trim();
  121. val.trim();
  122. if (key.isEmpty() || val.isEmpty())
  123. continue;
  124. (*this)[key] = val;
  125. } // end while
  126. fclose(fp);
  127. return true;
  128. }
  129. return false;
  130. }
  131. Bool UserPreferences::write( void )
  132. {
  133. if (m_filename.isEmpty())
  134. return false;
  135. FILE *fp = fopen(m_filename.str(), "w");
  136. if (fp)
  137. {
  138. PreferenceMap::const_iterator it = begin();
  139. while (it != end())
  140. {
  141. fprintf(fp, "%s = %s\n", it->first.str(), it->second.str());
  142. ++it;
  143. }
  144. fclose(fp);
  145. return true;
  146. }
  147. return false;
  148. }
  149. Bool UserPreferences::getBool(AsciiString key, Bool defaultValue) const
  150. {
  151. AsciiString val = getAsciiString(key, AsciiString::TheEmptyString);
  152. if (val.isEmpty())
  153. {
  154. return defaultValue;
  155. }
  156. val.toLower();
  157. return (val == "1" || val == "t" || val == "true" || val == "y" || val == "yes" || val == "ok");
  158. }
  159. Real UserPreferences::getReal(AsciiString key, Real defaultValue) const
  160. {
  161. AsciiString val = getAsciiString(key, AsciiString::TheEmptyString);
  162. if (val.isEmpty())
  163. {
  164. return defaultValue;
  165. }
  166. return (Real)atof(val.str());
  167. }
  168. Int UserPreferences::getInt(AsciiString key, Int defaultValue) const
  169. {
  170. AsciiString val = getAsciiString(key, AsciiString::TheEmptyString);
  171. if (val.isEmpty())
  172. {
  173. return defaultValue;
  174. }
  175. return atoi(val.str());
  176. }
  177. AsciiString UserPreferences::getAsciiString(AsciiString key, AsciiString defaultValue) const
  178. {
  179. UserPreferences::const_iterator it = find(key);
  180. if (it == end())
  181. {
  182. return defaultValue;
  183. }
  184. return it->second;
  185. }
  186. void UserPreferences::setBool(AsciiString key, Bool val)
  187. {
  188. (*this)[key] = boolAsStr(val);
  189. }
  190. void UserPreferences::setReal(AsciiString key, Real val)
  191. {
  192. (*this)[key] = realAsStr(val);
  193. }
  194. void UserPreferences::setInt(AsciiString key, Int val)
  195. {
  196. (*this)[key] = intAsStr(val);
  197. }
  198. void UserPreferences::setAsciiString(AsciiString key, AsciiString val)
  199. {
  200. (*this)[key] = val;
  201. }
  202. //-----------------------------------------------------------------------------
  203. // QuickMatchPreferences base class
  204. //-----------------------------------------------------------------------------
  205. QuickMatchPreferences::QuickMatchPreferences()
  206. {
  207. AsciiString userPrefFilename;
  208. Int localProfile = TheGameSpyInfo->getLocalProfileID();
  209. userPrefFilename.format("GeneralsOnline\\QMPref%d.ini", localProfile);
  210. load(userPrefFilename);
  211. }
  212. QuickMatchPreferences::~QuickMatchPreferences()
  213. {
  214. }
  215. void QuickMatchPreferences::setMapSelected(const AsciiString& mapName, Bool selected)
  216. {
  217. (*this)[AsciiStringToQuotedPrintable(mapName)] = (selected)?"1":"0";
  218. }
  219. Bool QuickMatchPreferences::isMapSelected(const AsciiString& mapName)
  220. {
  221. Int ret;
  222. QuickMatchPreferences::const_iterator it = find(AsciiStringToQuotedPrintable(mapName));
  223. if (it == end())
  224. {
  225. return TRUE;
  226. }
  227. ret = atoi(it->second.str());
  228. return (ret != 0);
  229. }
  230. void QuickMatchPreferences::setLastLadder(const AsciiString& addr, UnsignedShort port)
  231. {
  232. AsciiString strVal;
  233. strVal.format("%d", port);
  234. (*this)["LastLadderAddr"] = addr;
  235. (*this)["LastLadderPort"] = strVal;
  236. }
  237. AsciiString QuickMatchPreferences::getLastLadderAddr( void )
  238. {
  239. QuickMatchPreferences::const_iterator it = find("LastLadderAddr");
  240. if (it == end())
  241. {
  242. return AsciiString::TheEmptyString;
  243. }
  244. return it->second;
  245. }
  246. UnsignedShort QuickMatchPreferences::getLastLadderPort( void )
  247. {
  248. QuickMatchPreferences::const_iterator it = find("LastLadderPort");
  249. if (it == end())
  250. {
  251. return 0;
  252. }
  253. return atoi(it->second.str());
  254. }
  255. void QuickMatchPreferences::setMaxDisconnects(Int val)
  256. {
  257. AsciiString strVal;
  258. strVal.format("%d", val);
  259. (*this)["MaxDisconnects"] = strVal;
  260. }
  261. Int QuickMatchPreferences::getMaxDisconnects( void )
  262. {
  263. QuickMatchPreferences::const_iterator it = find("MaxDisconnects");
  264. if (it == end())
  265. {
  266. return 0;
  267. }
  268. return atoi(it->second.str());
  269. }
  270. void QuickMatchPreferences::setMaxPoints(Int val)
  271. {
  272. AsciiString strVal;
  273. strVal.format("%d", val);
  274. (*this)["MaxPoints"] = strVal;
  275. }
  276. Int QuickMatchPreferences::getMaxPoints( void )
  277. {
  278. QuickMatchPreferences::const_iterator it = find("MaxPoints");
  279. if (it == end())
  280. {
  281. return 1000;
  282. }
  283. return atoi(it->second.str());
  284. }
  285. void QuickMatchPreferences::setMinPoints(Int val)
  286. {
  287. AsciiString strVal;
  288. strVal.format("%d", val);
  289. (*this)["MinPoints"] = strVal;
  290. }
  291. Int QuickMatchPreferences::getMinPoints( void )
  292. {
  293. QuickMatchPreferences::const_iterator it = find("MinPoints");
  294. if (it == end())
  295. {
  296. return 0;
  297. }
  298. return atoi(it->second.str());
  299. }
  300. void QuickMatchPreferences::setWaitTime(Int val)
  301. {
  302. AsciiString strVal;
  303. strVal.format("%d", val);
  304. (*this)["WaitTime"] = strVal;
  305. }
  306. Int QuickMatchPreferences::getWaitTime( void )
  307. {
  308. QuickMatchPreferences::const_iterator it = find("WaitTime");
  309. if (it == end())
  310. {
  311. return 0;
  312. }
  313. return atoi(it->second.str());
  314. }
  315. void QuickMatchPreferences::setNumPlayers(Int val)
  316. {
  317. AsciiString strVal;
  318. strVal.format("%d", val);
  319. (*this)["NumPlayers"] = strVal;
  320. }
  321. Int QuickMatchPreferences::getNumPlayers( void )
  322. {
  323. QuickMatchPreferences::const_iterator it = find("NumPlayers");
  324. if (it == end())
  325. {
  326. return 0; // first in list, 1v1
  327. }
  328. return atoi(it->second.str());
  329. }
  330. void QuickMatchPreferences::setMaxPing(Int val)
  331. {
  332. AsciiString strVal;
  333. strVal.format("%d", val);
  334. (*this)["MaxPing"] = strVal;
  335. }
  336. Int QuickMatchPreferences::getMaxPing( void )
  337. {
  338. QuickMatchPreferences::const_iterator it = find("MaxPing");
  339. if (it == end())
  340. {
  341. return 5;
  342. }
  343. return atoi(it->second.str());
  344. }
  345. void QuickMatchPreferences::setColor( Int val )
  346. {
  347. setInt("Color", val);
  348. }
  349. Int QuickMatchPreferences::getColor( void )
  350. {
  351. return getInt("Color", 0);
  352. }
  353. void QuickMatchPreferences::setSide( Int val )
  354. {
  355. setInt("Side", val);
  356. }
  357. Int QuickMatchPreferences::getSide( void )
  358. {
  359. return getInt("Side", 0);
  360. }
  361. //-----------------------------------------------------------------------------
  362. // CustomMatchPreferences base class
  363. //-----------------------------------------------------------------------------
  364. CustomMatchPreferences::CustomMatchPreferences()
  365. {
  366. AsciiString userPrefFilename;
  367. Int localProfile = TheGameSpyInfo->getLocalProfileID();
  368. userPrefFilename.format("GeneralsOnline\\CustomPref%d.ini", localProfile);
  369. load(userPrefFilename);
  370. }
  371. CustomMatchPreferences::~CustomMatchPreferences()
  372. {
  373. }
  374. void CustomMatchPreferences::setLastLadder(const AsciiString& addr, UnsignedShort port)
  375. {
  376. AsciiString strVal;
  377. strVal.format("%d", port);
  378. (*this)["LastLadderAddr"] = addr;
  379. (*this)["LastLadderPort"] = strVal;
  380. }
  381. AsciiString CustomMatchPreferences::getLastLadderAddr( void )
  382. {
  383. QuickMatchPreferences::const_iterator it = find("LastLadderAddr");
  384. if (it == end())
  385. {
  386. return AsciiString::TheEmptyString;
  387. }
  388. return it->second;
  389. }
  390. UnsignedShort CustomMatchPreferences::getLastLadderPort( void )
  391. {
  392. QuickMatchPreferences::const_iterator it = find("LastLadderPort");
  393. if (it == end())
  394. {
  395. return 0;
  396. }
  397. return atoi(it->second.str());
  398. }
  399. Int CustomMatchPreferences::getPreferredColor(void)
  400. {
  401. Int ret;
  402. CustomMatchPreferences::const_iterator it = find("Color");
  403. if (it == end())
  404. {
  405. return -1;
  406. }
  407. ret = atoi(it->second.str());
  408. if (ret < -1 || ret >= TheMultiplayerSettings->getNumColors())
  409. ret = -1;
  410. return ret;
  411. }
  412. void CustomMatchPreferences::setPreferredColor(Int val)
  413. {
  414. AsciiString s;
  415. s.format("%d", val);
  416. (*this)["Color"] = s;
  417. }
  418. Int CustomMatchPreferences::getChatSizeSlider(void)
  419. {
  420. Int ret;
  421. CustomMatchPreferences::const_iterator it = find("ChatSlider");
  422. if (it == end())
  423. {
  424. return 45;
  425. }
  426. ret = atoi(it->second.str());
  427. if (ret < 0 || ret > 100)
  428. ret = 45;
  429. return ret;
  430. }
  431. void CustomMatchPreferences::setChatSizeSlider(Int val)
  432. {
  433. AsciiString s;
  434. s.format("%d", val);
  435. (*this)["ChatSlider"] = s;
  436. }
  437. Int CustomMatchPreferences::getPreferredFaction(void)
  438. {
  439. Int ret;
  440. CustomMatchPreferences::const_iterator it = find("PlayerTemplate");
  441. if (it == end())
  442. {
  443. return PLAYERTEMPLATE_RANDOM;
  444. }
  445. ret = atoi(it->second.str());
  446. if (ret == PLAYERTEMPLATE_OBSERVER || ret < PLAYERTEMPLATE_MIN || ret >= ThePlayerTemplateStore->getPlayerTemplateCount())
  447. ret = PLAYERTEMPLATE_RANDOM;
  448. if (ret >= 0)
  449. {
  450. const PlayerTemplate *fac = ThePlayerTemplateStore->getNthPlayerTemplate(ret);
  451. if (!fac)
  452. ret = PLAYERTEMPLATE_RANDOM;
  453. else if (fac->getStartingBuilding().isEmpty())
  454. ret = PLAYERTEMPLATE_RANDOM;
  455. else if (TheGameInfo && TheGameInfo->oldFactionsOnly() && !fac->isOldFaction())
  456. ret = PLAYERTEMPLATE_RANDOM;
  457. else {
  458. // Prevent from loading the disabled Generals, in case you had previously selected one as your preferred faction.
  459. // This is also enforced at GUI setup (GUIUtil.cpp and GameLogic.cpp).
  460. // @todo: unlock these when something rad happens
  461. Bool disallowLockedGenerals = TRUE;
  462. const GeneralPersona *general = TheChallengeGenerals->getGeneralByTemplateName(fac->getName());
  463. Bool startsLocked = general ? !general->isStartingEnabled() : FALSE;
  464. if (disallowLockedGenerals && startsLocked)
  465. ret = PLAYERTEMPLATE_RANDOM;
  466. }
  467. }
  468. return ret;
  469. }
  470. void CustomMatchPreferences::setPreferredFaction(Int val)
  471. {
  472. AsciiString s;
  473. s.format("%d", val);
  474. (*this)["PlayerTemplate"] = s;
  475. }
  476. Bool CustomMatchPreferences::usesSystemMapDir(void)
  477. {
  478. CustomMatchPreferences::const_iterator it = find("UseSystemMapDir");
  479. if (it == end())
  480. return TRUE;
  481. if (stricmp(it->second.str(), "1") == 0) {
  482. return TRUE;
  483. }
  484. return FALSE;
  485. }
  486. void CustomMatchPreferences::setUsesSystemMapDir(Bool val)
  487. {
  488. AsciiString s;
  489. s.format("%d", val);
  490. (*this)["UseSystemMapDir"] = s;
  491. }
  492. Bool CustomMatchPreferences::usesLongGameList(void)
  493. {
  494. return TRUE;
  495. CustomMatchPreferences::const_iterator it = find("UseLongGameList");
  496. if (it == end())
  497. return FALSE;
  498. if (stricmp(it->second.str(), "1") == 0) {
  499. return TRUE;
  500. }
  501. return FALSE;
  502. }
  503. void CustomMatchPreferences::setUsesLongGameList(Bool val)
  504. {
  505. AsciiString s;
  506. s.format("%d", val);
  507. (*this)["UseLongGameList"] = s;
  508. }
  509. Bool CustomMatchPreferences::allowsObservers(void)
  510. {
  511. CustomMatchPreferences::const_iterator it = find("AllowObservers");
  512. if (it == end())
  513. return TRUE;
  514. if (stricmp(it->second.str(), "1") == 0) {
  515. return TRUE;
  516. }
  517. return FALSE;
  518. }
  519. void CustomMatchPreferences::setAllowsObserver(Bool val)
  520. {
  521. AsciiString s;
  522. s.format("%d", val);
  523. (*this)["AllowObservers"] = s;
  524. }
  525. Bool CustomMatchPreferences::getDisallowAsianText( void )
  526. {
  527. CustomMatchPreferences::const_iterator it = find("DisallowAsianText");
  528. if (it == end())
  529. {
  530. // since English Win98 machines don't have a Unicode font installed by default,
  531. // we're forced to disable asian chat by default for English builds.
  532. if (GetRegistryLanguage().compareNoCase("chinese") == 0 || GetRegistryLanguage().compareNoCase("korean") == 0 )
  533. return FALSE;
  534. else
  535. return TRUE;
  536. }
  537. if (stricmp(it->second.str(), "1") == 0) {
  538. return TRUE;
  539. }
  540. return FALSE;
  541. }
  542. void CustomMatchPreferences::setDisallowAsianText(Bool val)
  543. {
  544. AsciiString s;
  545. s.format("%d", val);
  546. (*this)["DisallowAsianText"] = s;
  547. }
  548. Bool CustomMatchPreferences::getDisallowNonAsianText( void )
  549. {
  550. CustomMatchPreferences::const_iterator it = find("DisallowNonAsianText");
  551. if (it == end())
  552. return FALSE;
  553. if (stricmp(it->second.str(), "1") == 0) {
  554. return TRUE;
  555. }
  556. return FALSE;
  557. }
  558. void CustomMatchPreferences::setDisallowNonAsianText( Bool val )
  559. {
  560. AsciiString s;
  561. s.format("%d", val);
  562. (*this)["DisallowNonAsianText"] = s;
  563. }
  564. AsciiString CustomMatchPreferences::getPreferredMap(void)
  565. {
  566. AsciiString ret;
  567. CustomMatchPreferences::const_iterator it = find("Map");
  568. if (it == end())
  569. { //found find map, use default instead
  570. ret = getDefaultOfficialMap();
  571. return ret;
  572. }
  573. ret = QuotedPrintableToAsciiString(it->second);
  574. ret.trim();
  575. if (ret.isEmpty() || !isValidMap(ret, TRUE))
  576. { //map is invalid, use default instead
  577. ret = getDefaultOfficialMap();
  578. return ret;
  579. }
  580. //can only use official maps if recording stats
  581. if( getUseStats() && !isOfficialMap(ret) )
  582. ret = getDefaultOfficialMap();
  583. return ret;
  584. }
  585. void CustomMatchPreferences::setPreferredMap(AsciiString val)
  586. {
  587. (*this)["Map"] = AsciiStringToQuotedPrintable(val);
  588. }
  589. static const char superweaponRestrictionKey[] = "SuperweaponRestrict";
  590. Bool CustomMatchPreferences::getSuperweaponRestricted(void) const
  591. {
  592. const_iterator it = find(superweaponRestrictionKey);
  593. if (it == end())
  594. {
  595. return false;
  596. }
  597. return ( it->second.compareNoCase( "yes" ) == 0 );
  598. }
  599. void CustomMatchPreferences::setSuperweaponRestricted( Bool superweaponRestricted )
  600. {
  601. (*this)[superweaponRestrictionKey] = superweaponRestricted ? "Yes" : "No";
  602. }
  603. static const char startingCashKey[] = "StartingCash";
  604. Money CustomMatchPreferences::getStartingCash(void) const
  605. {
  606. const_iterator it = find(startingCashKey);
  607. if (it == end())
  608. {
  609. return TheMultiplayerSettings->getDefaultStartingMoney();
  610. }
  611. Money money;
  612. money.deposit( strtoul( it->second.str(), NULL, 10 ), FALSE );
  613. return money;
  614. }
  615. void CustomMatchPreferences::setStartingCash( const Money & startingCash )
  616. {
  617. AsciiString option;
  618. option.format( "%d", startingCash.countMoney() );
  619. (*this)[startingCashKey] = option;
  620. }
  621. static const char limitFactionsKey[] = "LimitArmies";
  622. // Prefers to only use the original 3 sides, not USA Air Force General, GLA Toxin General, et al
  623. Bool CustomMatchPreferences::getFactionsLimited(void) const
  624. {
  625. const_iterator it = find(limitFactionsKey);
  626. if (it == end())
  627. {
  628. return false; // The default
  629. }
  630. return ( it->second.compareNoCase( "yes" ) == 0 );
  631. }
  632. void CustomMatchPreferences::setFactionsLimited( Bool factionsLimited )
  633. {
  634. (*this)[limitFactionsKey] = factionsLimited ? "Yes" : "No";
  635. }
  636. static const char useStatsKey[] = "UseStats";
  637. Bool CustomMatchPreferences::getUseStats(void) const
  638. {
  639. const_iterator it = find(useStatsKey);
  640. if (it == end())
  641. {
  642. return true; // The default
  643. }
  644. return ( it->second.compareNoCase( "yes" ) == 0 );
  645. }
  646. void CustomMatchPreferences::setUseStats( Bool useStats )
  647. {
  648. (*this)[useStatsKey] = useStats ? "Yes" : "No";
  649. }
  650. //-----------------------------------------------------------------------------
  651. // GameSpyMiscPreferences base class
  652. //-----------------------------------------------------------------------------
  653. GameSpyMiscPreferences::GameSpyMiscPreferences()
  654. {
  655. AsciiString userPrefFilename;
  656. Int localProfile = TheGameSpyInfo->getLocalProfileID();
  657. userPrefFilename.format("GeneralsOnline\\GSMiscPref%d.ini", localProfile);
  658. load(userPrefFilename);
  659. }
  660. GameSpyMiscPreferences::~GameSpyMiscPreferences()
  661. {
  662. }
  663. Int GameSpyMiscPreferences::getLocale( void )
  664. {
  665. return getInt("Locale", 0);
  666. }
  667. void GameSpyMiscPreferences::setLocale( Int val )
  668. {
  669. setInt("Locale", val);
  670. }
  671. AsciiString GameSpyMiscPreferences::getCachedStats( void )
  672. {
  673. return getAsciiString("CachedStats", AsciiString::TheEmptyString);
  674. }
  675. void GameSpyMiscPreferences::setCachedStats( AsciiString val )
  676. {
  677. setAsciiString("CachedStats", val);
  678. }
  679. Bool GameSpyMiscPreferences::getQuickMatchResLocked( void )
  680. {
  681. return getBool("QMResLock", FALSE);
  682. }
  683. Int GameSpyMiscPreferences::getMaxMessagesPerUpdate( void )
  684. {
  685. return getInt("MaxMessagesPerUpdate", 100);
  686. }
  687. //-----------------------------------------------------------------------------
  688. // IgnorePreferences base class
  689. //-----------------------------------------------------------------------------
  690. IgnorePreferences::IgnorePreferences()
  691. {
  692. AsciiString userPrefFilename;
  693. // if(!TheGameSpyInfo)
  694. Int localProfile = TheGameSpyInfo->getLocalProfileID();
  695. userPrefFilename.format("GeneralsOnline\\IgnorePref%d.ini", localProfile);
  696. load(userPrefFilename);
  697. }
  698. IgnorePreferences::~IgnorePreferences()
  699. {
  700. }
  701. void IgnorePreferences::setIgnore(const AsciiString& userName, Int profileID, Bool ignore)
  702. {
  703. AsciiString strVal;
  704. strVal.format("%d", profileID);
  705. if (ignore)
  706. {
  707. (*this)[strVal] = userName;
  708. }
  709. else
  710. {
  711. erase(strVal);
  712. }
  713. }
  714. IgnorePrefMap IgnorePreferences::getIgnores(void)
  715. {
  716. IgnorePrefMap ignores;
  717. IgnorePreferences::iterator it;
  718. for (it = begin(); it != end(); ++it)
  719. {
  720. AsciiString profileStr = it->first;
  721. AsciiString lastLoginStr = it->second;
  722. Int profileID = atoi(profileStr.str());
  723. ignores[profileID] = lastLoginStr;
  724. }
  725. return ignores;
  726. }
  727. //-----------------------------------------------------------------------------
  728. // LadderPreferences base class
  729. //-----------------------------------------------------------------------------
  730. LadderPreferences::LadderPreferences()
  731. {
  732. }
  733. LadderPreferences::~LadderPreferences()
  734. {
  735. }
  736. Bool LadderPreferences::loadProfile( Int profileID )
  737. {
  738. clear();
  739. m_ladders.clear();
  740. AsciiString userPrefFilename;
  741. userPrefFilename.format("GeneralsOnline\\Ladders%d.ini", profileID);
  742. Bool success = load(userPrefFilename);
  743. if (!success)
  744. return success;
  745. // parse out our ladders
  746. for (LadderPreferences::iterator it = begin(); it != end(); ++it)
  747. {
  748. LadderPref p;
  749. AsciiString ladName = it->first;
  750. AsciiString ladData = it->second;
  751. DEBUG_LOG(("Looking at [%s] = [%s]\n", ladName.str(), ladData.str()));
  752. const char *ptr = ladName.reverseFind(':');
  753. DEBUG_ASSERTCRASH(ptr, ("Did not find ':' in ladder name - skipping"));
  754. if (!ptr)
  755. continue;
  756. p.port = atoi( ptr + 1 );
  757. for (Int i=0; i<strlen(ptr); ++i)
  758. {
  759. ladName.removeLastChar();
  760. }
  761. p.address = QuotedPrintableToAsciiString(ladName);
  762. ptr = ladData.reverseFind(':');
  763. DEBUG_ASSERTCRASH(ptr, ("Did not find ':' in ladder data - skipping"));
  764. if (!ptr)
  765. continue;
  766. p.lastPlayDate = atoi( ptr + 1 );
  767. for (i=0; i<strlen(ptr); ++i)
  768. {
  769. ladData.removeLastChar();
  770. }
  771. p.name = QuotedPrintableToUnicodeString(ladData);
  772. m_ladders[p.lastPlayDate] = p;
  773. }
  774. return true;
  775. }
  776. bool LadderPreferences::write( void )
  777. {
  778. clear();
  779. LadderPrefMap::iterator lpIt;
  780. static const Int MAX_LADDERS = 5;
  781. Int count;
  782. for (lpIt = m_ladders.begin(), count=0; lpIt != m_ladders.end() && count<MAX_LADDERS; ++lpIt, ++count)
  783. {
  784. LadderPref p = lpIt->second;
  785. AsciiString ladName;
  786. AsciiString ladData;
  787. ladName.format("%s:%d", AsciiStringToQuotedPrintable(p.address).str(), p.port);
  788. ladData.format("%s:%d", UnicodeStringToQuotedPrintable(p.name).str(), p.lastPlayDate);
  789. (*this)[ladName] = ladData;
  790. }
  791. return UserPreferences::write();
  792. }
  793. const LadderPrefMap& LadderPreferences::getRecentLadders( void )
  794. {
  795. return m_ladders;
  796. }
  797. void LadderPreferences::addRecentLadder( LadderPref ladder )
  798. {
  799. for (LadderPrefMap::iterator it = m_ladders.begin(); it != m_ladders.end(); ++it)
  800. {
  801. if (it->second == ladder)
  802. {
  803. m_ladders.erase(it);
  804. break;
  805. }
  806. }
  807. m_ladders[ladder.lastPlayDate] = ladder;
  808. }