Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

475 lines
13 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include <stdio.h>
  8. #include <time.h>
  9. #include "CreateMultiplayerGameGameplayPage.h"
  10. using namespace vgui;
  11. #include <KeyValues.h>
  12. #include <vgui/ILocalize.h>
  13. #include <vgui_controls/ComboBox.h>
  14. #include <vgui_controls/CheckButton.h>
  15. #include <vgui_controls/Label.h>
  16. #include <vgui_controls/TextEntry.h>
  17. #include "filesystem.h"
  18. #include "PanelListPanel.h"
  19. #include "scriptobject.h"
  20. #include <tier0/vcrmode.h>
  21. // memdbgon must be the last include file in a .cpp file!!!
  22. #include <tier0/memdbgon.h>
  23. #define OPTIONS_DIR "cfg"
  24. #define DEFAULT_OPTIONS_FILE OPTIONS_DIR "/settings_default.scr"
  25. #define OPTIONS_FILE OPTIONS_DIR "/settings.scr"
  26. //-----------------------------------------------------------------------------
  27. // Purpose: class for loading/saving server config file
  28. //-----------------------------------------------------------------------------
  29. class CServerDescription : public CDescription
  30. {
  31. public:
  32. CServerDescription( void );
  33. void WriteScriptHeader( FileHandle_t fp );
  34. void WriteFileHeader( FileHandle_t fp );
  35. };
  36. //-----------------------------------------------------------------------------
  37. // Purpose: Constructor
  38. //-----------------------------------------------------------------------------
  39. CCreateMultiplayerGameGameplayPage::CCreateMultiplayerGameGameplayPage(vgui::Panel *parent, const char *name) : PropertyPage(parent, name)
  40. {
  41. SetSize( 10, 10 ); // Quiet "parent not sized yet" spew
  42. m_pOptionsList = new CPanelListPanel(this, "GameOptions");
  43. m_pDescription = new CServerDescription();
  44. m_pDescription->InitFromFile( DEFAULT_OPTIONS_FILE );
  45. m_pDescription->InitFromFile( OPTIONS_FILE );
  46. m_pList = NULL;
  47. LoadControlSettings("Resource/CreateMultiplayerGameGameplayPage.res");
  48. LoadGameOptionsList();
  49. }
  50. //-----------------------------------------------------------------------------
  51. // Purpose: Destructor
  52. //-----------------------------------------------------------------------------
  53. CCreateMultiplayerGameGameplayPage::~CCreateMultiplayerGameGameplayPage()
  54. {
  55. delete m_pDescription;
  56. }
  57. //-----------------------------------------------------------------------------
  58. // Purpose:
  59. //-----------------------------------------------------------------------------
  60. int CCreateMultiplayerGameGameplayPage::GetMaxPlayers()
  61. {
  62. return atoi(GetValue("maxplayers", "32"));
  63. }
  64. //-----------------------------------------------------------------------------
  65. // Purpose:
  66. //-----------------------------------------------------------------------------
  67. const char *CCreateMultiplayerGameGameplayPage::GetPassword()
  68. {
  69. return GetValue("sv_password", "");
  70. }
  71. //-----------------------------------------------------------------------------
  72. // Purpose:
  73. //-----------------------------------------------------------------------------
  74. const char *CCreateMultiplayerGameGameplayPage::GetHostName()
  75. {
  76. return GetValue("hostname", "Half-Life");
  77. }
  78. //-----------------------------------------------------------------------------
  79. // Purpose:
  80. //-----------------------------------------------------------------------------
  81. const char *CCreateMultiplayerGameGameplayPage::GetValue(const char *cvarName, const char *defaultValue)
  82. {
  83. for (mpcontrol_t *mp = m_pList; mp != NULL; mp = mp->next)
  84. {
  85. Panel *control = mp->pControl;
  86. if (control && !stricmp(mp->GetName(), cvarName))
  87. {
  88. KeyValues *data = new KeyValues("GetText");
  89. static char buf[128];
  90. if (control && control->RequestInfo(data))
  91. {
  92. strncpy(buf, data->GetString("text", defaultValue), sizeof(buf) - 1);
  93. }
  94. else
  95. {
  96. // no value found, copy in default text
  97. strncpy(buf, defaultValue, sizeof(buf) - 1);
  98. }
  99. // ensure null termination of string
  100. buf[sizeof(buf) - 1] = 0;
  101. // free
  102. data->deleteThis();
  103. return buf;
  104. }
  105. }
  106. return defaultValue;
  107. }
  108. //-----------------------------------------------------------------------------
  109. // Purpose: called to get data from the page
  110. //-----------------------------------------------------------------------------
  111. void CCreateMultiplayerGameGameplayPage::OnApplyChanges()
  112. {
  113. // Get the values from the controls
  114. GatherCurrentValues();
  115. // Create the game.cfg file
  116. if ( m_pDescription )
  117. {
  118. FileHandle_t fp;
  119. // Add settings to config.cfg
  120. m_pDescription->WriteToConfig();
  121. // save out in the settings file
  122. g_pFullFileSystem->CreateDirHierarchy( OPTIONS_DIR, "GAME" );
  123. fp = g_pFullFileSystem->Open( OPTIONS_FILE, "wb", "GAME" );
  124. if ( fp )
  125. {
  126. m_pDescription->WriteToScriptFile( fp );
  127. g_pFullFileSystem->Close( fp );
  128. }
  129. }
  130. }
  131. //-----------------------------------------------------------------------------
  132. // Purpose: Creates all the controls in the game options list
  133. //-----------------------------------------------------------------------------
  134. void CCreateMultiplayerGameGameplayPage::LoadGameOptionsList()
  135. {
  136. // destroy any existing controls
  137. mpcontrol_t *p, *n;
  138. p = m_pList;
  139. while ( p )
  140. {
  141. n = p->next;
  142. //
  143. delete p->pControl;
  144. delete p->pPrompt;
  145. delete p;
  146. p = n;
  147. }
  148. m_pList = NULL;
  149. // Go through desciption creating controls
  150. CScriptObject *pObj;
  151. pObj = m_pDescription->pObjList;
  152. mpcontrol_t *pCtrl;
  153. CheckButton *pBox;
  154. TextEntry *pEdit;
  155. ComboBox *pCombo;
  156. CScriptListItem *pListItem;
  157. Panel *objParent = m_pOptionsList;
  158. while ( pObj )
  159. {
  160. if ( pObj->type == O_OBSOLETE )
  161. {
  162. pObj = pObj->pNext;
  163. continue;
  164. }
  165. pCtrl = new mpcontrol_t( objParent, pObj->cvarname );
  166. pCtrl->type = pObj->type;
  167. switch ( pCtrl->type )
  168. {
  169. case O_BOOL:
  170. pBox = new CheckButton( pCtrl, "DescCheckButton", pObj->prompt );
  171. pBox->SetSelected( pObj->fdefValue != 0.0f ? true : false );
  172. pCtrl->pControl = (Panel *)pBox;
  173. break;
  174. case O_STRING:
  175. case O_NUMBER:
  176. pEdit = new TextEntry( pCtrl, "DescEdit");
  177. pEdit->InsertString(pObj->defValue);
  178. pCtrl->pControl = (Panel *)pEdit;
  179. break;
  180. case O_LIST:
  181. pCombo = new ComboBox( pCtrl, "DescEdit", 5, false );
  182. pListItem = pObj->pListItems;
  183. while ( pListItem )
  184. {
  185. pCombo->AddItem(pListItem->szItemText, NULL);
  186. pListItem = pListItem->pNext;
  187. }
  188. pCombo->ActivateItemByRow((int)pObj->fdefValue);
  189. pCtrl->pControl = (Panel *)pCombo;
  190. break;
  191. default:
  192. break;
  193. }
  194. if ( pCtrl->type != O_BOOL )
  195. {
  196. pCtrl->pPrompt = new vgui::Label( pCtrl, "DescLabel", "" );
  197. pCtrl->pPrompt->SetContentAlignment( vgui::Label::a_west );
  198. pCtrl->pPrompt->SetTextInset( 5, 0 );
  199. pCtrl->pPrompt->SetText( pObj->prompt );
  200. }
  201. pCtrl->pScrObj = pObj;
  202. pCtrl->SetSize( 100, 28 );
  203. //pCtrl->SetBorder( scheme()->GetBorder(1, "DepressedButtonBorder") );
  204. m_pOptionsList->AddItem( pCtrl );
  205. // Link it in
  206. if ( !m_pList )
  207. {
  208. m_pList = pCtrl;
  209. pCtrl->next = NULL;
  210. }
  211. else
  212. {
  213. mpcontrol_t *p;
  214. p = m_pList;
  215. while ( p )
  216. {
  217. if ( !p->next )
  218. {
  219. p->next = pCtrl;
  220. pCtrl->next = NULL;
  221. break;
  222. }
  223. p = p->next;
  224. }
  225. }
  226. pObj = pObj->pNext;
  227. }
  228. }
  229. //-----------------------------------------------------------------------------
  230. // Purpose: applies all the values in the page
  231. //-----------------------------------------------------------------------------
  232. void CCreateMultiplayerGameGameplayPage::GatherCurrentValues()
  233. {
  234. if ( !m_pDescription )
  235. return;
  236. // OK
  237. CheckButton *pBox;
  238. TextEntry *pEdit;
  239. ComboBox *pCombo;
  240. mpcontrol_t *pList;
  241. CScriptObject *pObj;
  242. CScriptListItem *pItem;
  243. char szValue[256];
  244. char strValue[256];
  245. wchar_t w_szStrValue[256];
  246. pList = m_pList;
  247. while ( pList )
  248. {
  249. pObj = pList->pScrObj;
  250. if ( !pList->pControl )
  251. {
  252. pObj->SetCurValue( pObj->defValue );
  253. pList = pList->next;
  254. continue;
  255. }
  256. switch ( pObj->type )
  257. {
  258. case O_BOOL:
  259. pBox = (CheckButton *)pList->pControl;
  260. Q_snprintf( szValue, sizeof( szValue ), "%s", pBox->IsSelected() ? "1" : "0" );
  261. break;
  262. case O_NUMBER:
  263. pEdit = ( TextEntry * )pList->pControl;
  264. pEdit->GetText( strValue, sizeof( strValue ) );
  265. Q_snprintf( szValue, sizeof( szValue ), "%s", strValue );
  266. break;
  267. case O_STRING:
  268. pEdit = ( TextEntry * )pList->pControl;
  269. pEdit->GetText( strValue, sizeof( strValue ) );
  270. Q_snprintf( szValue, sizeof( szValue ), "%s", strValue );
  271. break;
  272. case O_LIST:
  273. pCombo = ( ComboBox *)pList->pControl;
  274. pCombo->GetText( w_szStrValue, sizeof( w_szStrValue ) / sizeof( wchar_t ) );
  275. pItem = pObj->pListItems;
  276. while ( pItem )
  277. {
  278. wchar_t *wLocalizedString = NULL;
  279. wchar_t w_szStrTemp[256];
  280. // Localized string?
  281. if ( pItem->szItemText[0] == '#' )
  282. {
  283. wLocalizedString = g_pVGuiLocalize->Find( pItem->szItemText );
  284. }
  285. if ( wLocalizedString )
  286. {
  287. // Copy the string we found into our temp array
  288. V_wcscpy_safe( w_szStrTemp, wLocalizedString );
  289. }
  290. else
  291. {
  292. // Just convert what we have to Unicode
  293. g_pVGuiLocalize->ConvertANSIToUnicode( pItem->szItemText, w_szStrTemp, sizeof( w_szStrTemp ) );
  294. }
  295. if ( _wcsicmp( w_szStrTemp, w_szStrValue ) == 0 )
  296. {
  297. // Found a match!
  298. break;
  299. }
  300. pItem = pItem->pNext;
  301. }
  302. if ( pItem )
  303. {
  304. Q_snprintf( szValue, sizeof( szValue ), "%s", pItem->szValue );
  305. }
  306. else //Couldn't find index
  307. {
  308. Q_snprintf( szValue, sizeof( szValue ), "%s", pObj->defValue );
  309. }
  310. break;
  311. }
  312. // Remove double quotes and % characters
  313. UTIL_StripInvalidCharacters( szValue, sizeof( szValue ) );
  314. Q_strncpy( strValue, szValue, sizeof( strValue ) );
  315. pObj->SetCurValue( strValue );
  316. pList = pList->next;
  317. }
  318. }
  319. //-----------------------------------------------------------------------------
  320. // Purpose: Constructor, load/save server settings object
  321. //-----------------------------------------------------------------------------
  322. CServerDescription::CServerDescription( void ) : CDescription()
  323. {
  324. setHint( "// NOTE: THIS FILE IS AUTOMATICALLY REGENERATED, \r\n"
  325. "//DO NOT EDIT THIS HEADER, YOUR COMMENTS WILL BE LOST IF YOU DO\r\n"
  326. "// Multiplayer options script\r\n"
  327. "//\r\n"
  328. "// Format:\r\n"
  329. "// Version [float]\r\n"
  330. "// Options description followed by \r\n"
  331. "// Options defaults\r\n"
  332. "//\r\n"
  333. "// Option description syntax:\r\n"
  334. "//\r\n"
  335. "// \"cvar\" { \"Prompt\" { type [ type info ] } { default } }\r\n"
  336. "//\r\n"
  337. "// type = \r\n"
  338. "// BOOL (a yes/no toggle)\r\n"
  339. "// STRING\r\n"
  340. "// NUMBER\r\n"
  341. "// LIST\r\n"
  342. "//\r\n"
  343. "// type info:\r\n"
  344. "// BOOL no type info\r\n"
  345. "// NUMBER min max range, use -1 -1 for no limits\r\n"
  346. "// STRING no type info\r\n"
  347. "// LIST "" delimited list of options value pairs\r\n"
  348. "//\r\n"
  349. "//\r\n"
  350. "// default depends on type\r\n"
  351. "// BOOL is \"0\" or \"1\"\r\n"
  352. "// NUMBER is \"value\"\r\n"
  353. "// STRING is \"value\"\r\n"
  354. "// LIST is \"index\", where index \"0\" is the first element of the list\r\n\r\n\r\n" );
  355. setDescription ( "SERVER_OPTIONS" );
  356. }
  357. //-----------------------------------------------------------------------------
  358. // Purpose:
  359. //-----------------------------------------------------------------------------
  360. void CServerDescription::WriteScriptHeader( FileHandle_t fp )
  361. {
  362. char am_pm[] = "AM";
  363. tm newtime;
  364. VCRHook_LocalTime( &newtime );
  365. if( newtime.tm_hour > 12 ) /* Set up extension. */
  366. Q_strncpy( am_pm, "PM", sizeof( am_pm ) );
  367. if( newtime.tm_hour > 12 ) /* Convert from 24-hour */
  368. newtime.tm_hour -= 12; /* to 12-hour clock. */
  369. if( newtime.tm_hour == 0 ) /*Set hour to 12 if midnight. */
  370. newtime.tm_hour = 12;
  371. g_pFullFileSystem->FPrintf( fp, (char *)getHint() );
  372. // Write out the comment and Cvar Info:
  373. g_pFullFileSystem->FPrintf( fp, "// Half-Life Server Configuration Layout Script (stores last settings chosen, too)\r\n" );
  374. g_pFullFileSystem->FPrintf( fp, "// File generated: %.19s %s\r\n", asctime( &newtime ), am_pm );
  375. g_pFullFileSystem->FPrintf( fp, "//\r\n//\r\n// Cvar\t-\tSetting\r\n\r\n" );
  376. g_pFullFileSystem->FPrintf( fp, "VERSION %.1f\r\n\r\n", SCRIPT_VERSION );
  377. g_pFullFileSystem->FPrintf( fp, "DESCRIPTION SERVER_OPTIONS\r\n{\r\n" );
  378. }
  379. //-----------------------------------------------------------------------------
  380. // Purpose:
  381. //-----------------------------------------------------------------------------
  382. void CServerDescription::WriteFileHeader( FileHandle_t fp )
  383. {
  384. char am_pm[] = "AM";
  385. tm newtime;
  386. VCRHook_LocalTime( &newtime );
  387. if( newtime.tm_hour > 12 ) /* Set up extension. */
  388. Q_strncpy( am_pm, "PM", sizeof( am_pm ) );
  389. if( newtime.tm_hour > 12 ) /* Convert from 24-hour */
  390. newtime.tm_hour -= 12; /* to 12-hour clock. */
  391. if( newtime.tm_hour == 0 ) /*Set hour to 12 if midnight. */
  392. newtime.tm_hour = 12;
  393. g_pFullFileSystem->FPrintf( fp, "// Half-Life Server Configuration Settings\r\n" );
  394. g_pFullFileSystem->FPrintf( fp, "// DO NOT EDIT, GENERATED BY HALF-LIFE\r\n" );
  395. g_pFullFileSystem->FPrintf( fp, "// File generated: %.19s %s\r\n", asctime( &newtime ), am_pm );
  396. g_pFullFileSystem->FPrintf( fp, "//\r\n//\r\n// Cvar\t-\tSetting\r\n\r\n" );
  397. }