useroptions.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. /*
  2. ** Command & Conquer Renegade(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. // Filename: useroptions.cpp
  20. // Author: Tom Spencer-Smith
  21. // Date: Dec 1999
  22. // Description:
  23. //
  24. #include "useroptions.h"
  25. #include "_globals.h"
  26. #include "wwdebug.h"
  27. #include "player.h"
  28. #include "cnetwork.h"
  29. #include "registry.h"
  30. #include "player.h"
  31. #include "playertype.h"
  32. #include "bandwidth.h"
  33. #include "bandwidthcheck.h"
  34. #include <stdio.h>
  35. #include "trim.h"
  36. #include "singletoninstancekeeper.h"
  37. #include "slavemaster.h"
  38. #include "debug.h"
  39. #include "rawfile.h"
  40. #include "serversettings.h"
  41. #include "autostart.h"
  42. #include "consolemode.h"
  43. #include "GameSpy_QnR.h"
  44. #include "gamespyadmin.h"
  45. #include "specialbuilds.h"
  46. #include "useroptions.h"
  47. extern char DefaultRegistryModifier[1024];
  48. //
  49. // Class statics
  50. //
  51. cRegistryBool cUserOptions::ShowNamesOnSoldier( APPLICATION_SUB_KEY_NAME_NETOPTIONS, "ShowNamesOnSoldier", true);
  52. cRegistryBool cUserOptions::SkipQuitConfirmDialog( APPLICATION_SUB_KEY_NAME_OPTIONS, "SkipQuitConfirmDialog", false);
  53. cRegistryBool cUserOptions::SkipIngameQuitConfirmDialog( APPLICATION_SUB_KEY_NAME_OPTIONS, "SkipIngameQuitConfirmDialog", false);
  54. cRegistryBool cUserOptions::CameraLockedToTurret( APPLICATION_SUB_KEY_NAME_OPTIONS, "CameraLockedToTurret", false);
  55. cRegistryBool cUserOptions::PermitDiagLogging( APPLICATION_SUB_KEY_NAME_OPTIONS, "PermitDiagLogging", true);
  56. cRegistryInt cUserOptions::Sku( APPLICATION_SUB_KEY_NAME, "SKU", RENEGADE_BASE_SKU);
  57. cRegistryInt cUserOptions::BandwidthType( APPLICATION_SUB_KEY_NAME_NETOPTIONS, "BandwidthType", BANDWIDTH_AUTO);
  58. cRegistryInt cUserOptions::BandwidthBps( APPLICATION_SUB_KEY_NAME_NETOPTIONS, "BandwidthBps", 33600);
  59. cRegistryInt cUserOptions::GameSpyBandwidthType( APPLICATION_SUB_KEY_NAME_GAMESPY, "GameSpyBandwidthType", BANDWIDTH_AUTO);
  60. cRegistryInt cUserOptions::PreferredGameSpyNic( APPLICATION_SUB_KEY_NAME_GAMESPY, "PreferredGameSpyNic", 0);
  61. cRegistryString cUserOptions::GameSpyNickname( APPLICATION_SUB_KEY_NAME_GAMESPY, "GameSpyNickname", "");
  62. cRegistryInt cUserOptions::GameSpyQueryPort( APPLICATION_SUB_KEY_NAME_GAMESPY, "GameSpyQueryPort", 25300);
  63. cRegistryInt cUserOptions::GameSpyGamePort( APPLICATION_SUB_KEY_NAME_GAMESPY, "GameSpyGamePort", 4848);
  64. cRegistryInt cUserOptions::SplashCount( APPLICATION_SUB_KEY_NAME_GAMESPY, "SplashCount", 0);
  65. cRegistryBool cUserOptions::DoneClientBandwidthTest( APPLICATION_SUB_KEY_NAME_GAMESPY, "DoneClientBandwidthTest", false);
  66. cRegistryInt cUserOptions::PreferredLanNic( APPLICATION_SUB_KEY_NAME_NETOPTIONS, "PreferredLanNic", 0);
  67. cRegistryInt cUserOptions::NetUpdateRate( APPLICATION_SUB_KEY_NAME_NETOPTIONS, "NetUpdateRate", 10);
  68. cRegistryFloat cUserOptions::ClientHintFactor( APPLICATION_SUB_KEY_NAME_NETOPTIONS, "ClientHintFactor", 10.0f);
  69. cRegistryFloat cUserOptions::MaxFacingPenalty( APPLICATION_SUB_KEY_NAME_NETOPTIONS, "MaxFacingPenalty", 0.3f);
  70. cRegistryFloat cUserOptions::IrrelevancePenalty( APPLICATION_SUB_KEY_NAME_NETOPTIONS, "IrrelevancePenalty", 0.2f);
  71. cRegistryInt cUserOptions::ResultsLogNumber( APPLICATION_SUB_KEY_NAME_NETOPTIONS, "ResultsLogNumber", 1);
  72. //-----------------------------------------------------------------------------
  73. bool cUserOptions::Parse_Command_Line(LPCSTR command)
  74. {
  75. WWASSERT(command != NULL);
  76. bool retcode = true;
  77. //
  78. // Convert to argv & argc for convenience.
  79. // First argument is supposed to be a pointer to the .EXE that is running
  80. // but we don't need that here.
  81. //
  82. int argc = 1; //Set argument count to 1
  83. char * argv[20]; //Pointers to command line arguments
  84. argv[0] = NULL; //Set 1st command line argument to point to full path
  85. //
  86. // Get pointers to command line arguments just like if we were in DOS
  87. //
  88. char *command_line = strdup(command);
  89. char *token = strtok(command_line, " ");
  90. while (argc < ARRAY_SIZE(argv) && token != NULL) {
  91. argv[argc++] = strtrim(token);
  92. token = strtok(NULL, " ");
  93. if (argc >= 19) {
  94. break;
  95. }
  96. }
  97. //
  98. // Loop through all the command line arguments.
  99. //
  100. char *cmd;
  101. for (int i=1 ; i<argc ; i++) {
  102. cmd = strupr(argv[i]);
  103. // Look for ip override.
  104. if (strstr(cmd, "IP=")) {
  105. extern ULONG g_ip_override;
  106. g_ip_override = ::inet_addr(strstr(cmd, "IP=") + 3);
  107. continue;
  108. }
  109. // See if multiple progrram instances are allowed.
  110. if (strstr(cmd, "MULTI")) {
  111. SingletonInstanceKeeperClass::Allow_Multiple_Instances(true);
  112. continue;
  113. }
  114. if (strstr(cmd, "REGMOD=")) {
  115. strcpy(DefaultRegistryModifier, strstr(cmd, "REGMOD=") + 7);
  116. #ifdef WWDEBUG
  117. OutputDebugString("Registry modifier on command line\n");
  118. #endif //WWDEBUG
  119. Reread();
  120. continue;
  121. }
  122. if (strstr(cmd, "SLAVE")) {
  123. SlaveMaster.Set_Slave_Mode(true);
  124. DebugManager::Set_Is_Slave(true);
  125. // Save out process ID so our master server can find us.
  126. char tempmod[512];
  127. strcpy(tempmod, DefaultRegistryModifier);
  128. strcpy(DefaultRegistryModifier, "");
  129. RegistryClass reg(APPLICATION_SUB_KEY_NAME);
  130. if (reg.Is_Valid()) {
  131. reg.Set_Int("ProcessId", GetCurrentProcessId());
  132. }
  133. strcpy(DefaultRegistryModifier, tempmod);
  134. RegistryClass::Set_Read_Only(true);
  135. continue;
  136. }
  137. if (strstr(cmd, "STARTSERVER=")) {
  138. Set_Server_INI_File(cmd);
  139. continue;
  140. }
  141. if (strstr(cmd, "GAMESPYSERVER=")) {
  142. char server_config_file[MAX_PATH];
  143. strcpy(server_config_file, strstr(cmd, "GAMESPYSERVER=") + 14);
  144. WWDEBUG_SAY(("Set to load gamespy server settings from config file %s\n", server_config_file));
  145. RawFileClass file(server_config_file);
  146. if (file.Is_Available()) {
  147. ServerSettingsClass::Set_Settings_File_Name(server_config_file);
  148. RegistryClass registry (APPLICATION_SUB_KEY_NAME_WOLSETTINGS);
  149. if (registry.Is_Valid ()) {
  150. registry.Set_Int(AutoRestartClass::REG_VALUE_AUTO_RESTART_FLAG, 1);
  151. registry.Set_Int(AutoRestartClass::REG_VALUE_AUTO_RESTART_TYPE, 0);
  152. }
  153. cGameSpyAdmin::Set_Is_Server_Gamespy_Listed(true);
  154. GameSpyQnR.Enable_Reporting(true);
  155. }
  156. continue;
  157. }
  158. if (strstr(cmd, "NODX")) {
  159. ConsoleBox.Set_Exclusive(true);
  160. continue;
  161. }
  162. }
  163. free(command_line);
  164. #ifndef BETACLIENT
  165. //GAMESPY
  166. //
  167. // Gamespy params follow different param format
  168. //
  169. char *tmpstr = strdup(command);
  170. tmpstr = _strupr(tmpstr);
  171. char * ip_param = ::strstr(tmpstr, "+CONNECT");
  172. if (ip_param != NULL) {
  173. ip_param += ::strlen("+connect");
  174. USHORT port = 4848;
  175. DWORD addr = 0;
  176. char ipaddr[300] = "";
  177. ::sscanf(ip_param, "%s", ipaddr);
  178. strtrim(ipaddr);
  179. char *tport = strchr(ipaddr, ':');
  180. if (tport) {
  181. *tport++ = 0;
  182. if (atoi(tport) != 0 || atoi(tport) > 0) {
  183. port = atoi(tport);
  184. }
  185. }
  186. addr = ::inet_addr(ipaddr);
  187. cGameSpyAdmin::Set_Game_Host_Ip(addr);
  188. cGameSpyAdmin::Set_Game_Host_Port(port);
  189. cGameSpyAdmin::Set_Is_Launch_From_Gamespy_Requested(true);
  190. }
  191. char * nickname_param = ::strstr(tmpstr, "+NETPLAYERNAME");
  192. if (nickname_param != NULL) {
  193. nickname_param = (char *)(command + (nickname_param-tmpstr));
  194. nickname_param += ::strlen("+NetPlayerName");
  195. char * start = nickname_param;
  196. // Strip leading spaces
  197. while (*start && *start == ' ') start++;
  198. // if we find a space before a quote then space delimit
  199. while (*start && *start != '"' && *start != ' ') {
  200. start++;
  201. }
  202. char * end = start;
  203. // Match the end quote
  204. if (*start && *start != ' ') {
  205. start++;
  206. end = start;
  207. while (*end && *end != '"') {
  208. end++;
  209. }
  210. }
  211. // Couldn't find any quotes, so delimit by spaces
  212. if (start == end) {
  213. start = nickname_param;
  214. while (*start && *start == ' ') start++;
  215. end = strchr(start, ' ');
  216. if (!end) end = start + strlen(start);
  217. }
  218. char nickname2[300] = "";
  219. ::strncpy(nickname2, start, end - start);
  220. nickname2[end - start] = 0;
  221. cUserOptions::GameSpyNickname.Set(nickname2);
  222. cGameSpyAdmin::Set_Is_Launch_From_Gamespy_Requested(true);
  223. }
  224. char * password_param = ::strstr(tmpstr, "+PASS");
  225. if (password_param != NULL) {
  226. char *tmp_param = ::strstr(tmpstr, "+PASSWORD");
  227. if (tmp_param) {
  228. password_param = (char *)(command + (tmp_param-tmpstr));
  229. password_param += ::strlen("+PASSWORD");
  230. } else {
  231. password_param = (char *)(command + (password_param-tmpstr));
  232. password_param += ::strlen("+PASS");
  233. }
  234. char * start = password_param;
  235. // Strip leading spaces
  236. while (*start && *start == ' ') start++;
  237. // if we find a space before a quote then space delimit
  238. while (*start && *start != '"' && *start != ' ') {
  239. start++;
  240. }
  241. char * end = start;
  242. // Match the end quote
  243. if (*start && *start != ' ') {
  244. start++;
  245. end = start;
  246. while (*end && *end != '"') {
  247. end++;
  248. }
  249. }
  250. // Couldn't find any quotes, so delimit by spaces
  251. if (start == end) {
  252. start = password_param;
  253. while (*start && *start == ' ') start++;
  254. end = strchr(start, ' ');
  255. if (!end) end = start + strlen(start);
  256. }
  257. char password[300] = "";
  258. ::strncpy(password, start, end - start);
  259. password[end - start] = 0;
  260. WideStringClass wide_password;
  261. wide_password.Convert_From(password);
  262. cGameSpyAdmin::Set_Password_Attempt(wide_password);
  263. }
  264. free(tmpstr);
  265. #endif // !BETACLIENT
  266. // Return true if command line options scanned OK.
  267. return(retcode);
  268. }
  269. //-----------------------------------------------------------------------------
  270. void cUserOptions::Set_Server_INI_File(char *cmd_line_entry)
  271. {
  272. char server_config_file[MAX_PATH];
  273. strcpy(server_config_file, strstr(cmd_line_entry, "STARTSERVER=") + 12);
  274. WWDEBUG_SAY(("Set to load server settings from config file %s\n", server_config_file));
  275. RawFileClass file(server_config_file);
  276. if (file.Is_Available()) {
  277. ServerSettingsClass::Set_Settings_File_Name(server_config_file);
  278. RegistryClass registry (APPLICATION_SUB_KEY_NAME_WOLSETTINGS);
  279. if (registry.Is_Valid ()) {
  280. registry.Set_Int(AutoRestartClass::REG_VALUE_AUTO_RESTART_FLAG, 1);
  281. registry.Set_Int(AutoRestartClass::REG_VALUE_AUTO_RESTART_TYPE, 1);
  282. }
  283. }
  284. }
  285. //-----------------------------------------------------------------------------
  286. void cUserOptions::Set_Bandwidth_Type(BANDWIDTH_TYPE_ENUM bandwidth_type)
  287. {
  288. if (cGameSpyAdmin::Is_Gamespy_Game()) {
  289. GameSpyBandwidthType.Set(bandwidth_type);
  290. } else {
  291. BandwidthType.Set(bandwidth_type);
  292. }
  293. if (bandwidth_type != BANDWIDTH_CUSTOM) {
  294. if (bandwidth_type == BANDWIDTH_AUTO && BandwidthCheckerClass::Got_Bandwidth()) {
  295. ULONG bps = BandwidthCheckerClass::Get_Upstream_Bandwidth();
  296. WWASSERT(bps > 0);
  297. BandwidthBps.Set(bps);
  298. } else {
  299. ULONG bps = cBandwidth::Get_Bandwidth_Bps_From_Type(bandwidth_type);
  300. WWASSERT(bps > 0);
  301. BandwidthBps.Set(bps);
  302. }
  303. }
  304. }
  305. //-----------------------------------------------------------------------------
  306. BANDWIDTH_TYPE_ENUM cUserOptions::Get_Bandwidth_Type(void)
  307. {
  308. if (cGameSpyAdmin::Is_Gamespy_Game()) {
  309. return (BANDWIDTH_TYPE_ENUM) GameSpyBandwidthType.Get();
  310. } else {
  311. return (BANDWIDTH_TYPE_ENUM) BandwidthType.Get();
  312. }
  313. }
  314. //-----------------------------------------------------------------------------
  315. void cUserOptions::Set_Bandwidth_Bps(int bandwidth_bps)
  316. {
  317. WWASSERT(bandwidth_bps > 0);
  318. if (cGameSpyAdmin::Is_Gamespy_Game()) {
  319. GameSpyBandwidthType.Set(BANDWIDTH_CUSTOM);
  320. } else {
  321. BandwidthType.Set(BANDWIDTH_CUSTOM);
  322. }
  323. BandwidthBps.Set(bandwidth_bps);
  324. }
  325. //-----------------------------------------------------------------------------
  326. void cUserOptions::Reread(void)
  327. {
  328. Sku.Set(RegistryClass(APPLICATION_SUB_KEY_NAME).Get_Int("SKU", Sku.Get()));
  329. BandwidthType.Set(RegistryClass(APPLICATION_SUB_KEY_NAME_NETOPTIONS).Get_Int("BandwidthType", BandwidthType.Get()));
  330. BandwidthBps.Set(RegistryClass(APPLICATION_SUB_KEY_NAME_NETOPTIONS).Get_Int("BandwidthBps", BandwidthBps.Get()));
  331. GameSpyBandwidthType.Set(RegistryClass(APPLICATION_SUB_KEY_NAME_GAMESPY).Get_Int("GameSpyBandwidthType", GameSpyBandwidthType.Get()));
  332. }
  333. /*
  334. cRegistryInt cUserOptions::GameListFilterMaxPing( APPLICATION_SUB_KEY_NAME_NETOPTIONS, "GameListFilterMaxPing", 9999);
  335. cRegistryInt cUserOptions::GameListFilterMinPlayersPresent( APPLICATION_SUB_KEY_NAME_NETOPTIONS, "GameListFilterMinPlayersPresent", 0);
  336. cRegistryInt cUserOptions::GameListFilterMaxPlayersPresent( APPLICATION_SUB_KEY_NAME_NETOPTIONS, "GameListFilterMaxPlayersPresent", 99);
  337. cRegistryInt cUserOptions::GameListFilterMaxPlayersPermitted( APPLICATION_SUB_KEY_NAME_NETOPTIONS, "GameListFilterMaxPlayersPermitted", 99);
  338. cRegistryBool cUserOptions::GameListFilterShowPrivateGames( APPLICATION_SUB_KEY_NAME_NETOPTIONS, "GameListFilterShowPrivateGames", true);
  339. cRegistryBool cUserOptions::GameListFilterShowOnlyDedicatedGames( APPLICATION_SUB_KEY_NAME_NETOPTIONS, "GameListFilterShowOnlyDedicatedGames", false);
  340. cRegistryBool cUserOptions::GameListFilterShowOnlyGamesIRankFor( APPLICATION_SUB_KEY_NAME_NETOPTIONS, "GameListFilterShowOnlyGamesIRankFor", false);
  341. */
  342. /*
  343. //
  344. // Gamespy client launch params.
  345. // All 3 must be specified.
  346. // Example: Renegade.exe GAMESPY_IPADDR=192.168.10.100 GAMESPY_PORT=3333 GAMESPY_NICKNAME="Bob 1234"
  347. //
  348. LPCSTR param = NULL;
  349. char * value = NULL;
  350. param = "GAMESPY_IPADDR=";
  351. value = ::strstr(cmd, param);
  352. if (value != NULL) {
  353. value += ::strlen(param);
  354. ULONG ip = ::inet_addr(value);
  355. cGameSpyAdmin::Set_Game_Host_Ip(ip);
  356. cGameSpyAdmin::Set_Is_Launch_From_Gamespy_Requested(true);
  357. continue;
  358. }
  359. param = "GAMESPY_PORT=";
  360. value = ::strstr(cmd, param);
  361. if (value != NULL) {
  362. value += ::strlen(param);
  363. USHORT port = (USHORT)::atol(value);
  364. cGameSpyAdmin::Set_Game_Host_Port(port);
  365. cGameSpyAdmin::Set_Is_Launch_From_Gamespy_Requested(true);
  366. continue;
  367. }
  368. param = "GAMESPY_NICKNAME=";
  369. value = ::strstr(cmd, param);
  370. if (value != NULL) {
  371. value += ::strlen(param);
  372. WideStringClass nickname;
  373. char temp[200] = "";
  374. char seps[] = "\"";
  375. char * start_token = ::strtok(value, seps);
  376. if (start_token != NULL) {
  377. start_token++;
  378. }
  379. char * end_token = ::strtok(NULL, seps);
  380. if (end_token != NULL && end_token > start_token) {
  381. ::strncpy(temp, start_token, end_token - start_token);
  382. temp[end_token - start_token] = 0;
  383. }
  384. nickname.Convert_From(temp);
  385. cGameSpyAdmin::Set_Player_Nickname(nickname);
  386. cGameSpyAdmin::Set_Is_Launch_From_Gamespy_Requested(true);
  387. continue;
  388. }
  389. */
  390. /*
  391. char nickname[300] = "";
  392. ::sscanf(nickname_param, "%s", nickname);
  393. nickname[::strlen(nickname) - 1] = ' ';
  394. nickname[0] = ' ';
  395. char nickname2[300] = "";
  396. ::sscanf(nickname, "%s", nickname2);
  397. */
  398. /*
  399. char seps[] = "\"";
  400. char * start_token = ::strtok(nickname_param, seps);
  401. if (start_token != NULL) {
  402. start_token++;
  403. }
  404. char * end_token = ::strtok(NULL, seps);
  405. char nickname2[300] = "";
  406. if (end_token != NULL && end_token > start_token) {
  407. char nickname2[300] = "";
  408. ::strncpy(nickname2, start_token, end_token - start_token);
  409. nickname2[end_token - start_token] = 0;
  410. }
  411. */
  412. /*
  413. WideStringClass wide_nickname;
  414. wide_nickname.Convert_From(nickname2);
  415. cGameSpyAdmin::Set_Player_Nickname(wide_nickname);
  416. */