Counter Strike : Global Offensive Source Code
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.

635 lines
17 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ====
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "stdafx.h"
  7. #include <direct.h>
  8. #include <io.h>
  9. #include <WorldSize.h>
  10. #include "Gameconfig.h"
  11. #include "GlobalFunctions.h"
  12. #include "fgdlib/HelperInfo.h"
  13. #include "hammer.h"
  14. #include "KeyValues.h"
  15. #include "MapDoc.h"
  16. #include "MapDoc.h"
  17. #include "MapEntity.h"
  18. #include "MapInstance.h"
  19. #include "MapWorld.h"
  20. #include "filesystem_tools.h"
  21. #include "TextureSystem.h"
  22. #include "tier1/strtools.h"
  23. #include "gridnav.h"
  24. // memdbgon must be the last include file in a .cpp file!!!
  25. #include "tier0/memdbgon.h"
  26. #pragma warning(disable:4244)
  27. const int MAX_ERRORS = 5;
  28. GameData *pGD;
  29. CGameConfig g_DefaultGameConfig;
  30. CGameConfig *g_pGameConfig = &g_DefaultGameConfig;
  31. float g_MAX_MAP_COORD = 4096;
  32. float g_MIN_MAP_COORD = -4096;
  33. //-----------------------------------------------------------------------------
  34. // Purpose:
  35. //-----------------------------------------------------------------------------
  36. CGameConfig *CGameConfig::GetActiveGame(void)
  37. {
  38. return g_pGameConfig;
  39. }
  40. //-----------------------------------------------------------------------------
  41. // Purpose:
  42. // Input : pGame -
  43. //-----------------------------------------------------------------------------
  44. void CGameConfig::SetActiveGame(CGameConfig *pGame)
  45. {
  46. if (pGame != NULL)
  47. {
  48. g_pGameConfig = pGame;
  49. pGD = &pGame->GD;
  50. if (pGame->mapformat == mfHalfLife)
  51. {
  52. g_MAX_MAP_COORD = 4096;
  53. g_MIN_MAP_COORD = -4096;
  54. }
  55. else
  56. {
  57. g_MAX_MAP_COORD = pGD->GetMaxMapCoord();
  58. g_MIN_MAP_COORD = pGD->GetMinMapCoord();
  59. }
  60. CGridNav::Init( pGD->IsGridNavActive(), pGD->GetGridNavEdgeSize(), pGD->GetGridNavOffsetX(), pGD->GetGridNavOffsetY(), pGD->GetTraceHeight() );
  61. }
  62. else
  63. {
  64. g_pGameConfig = &g_DefaultGameConfig;
  65. pGD = NULL;
  66. g_MAX_MAP_COORD = 4096;
  67. g_MIN_MAP_COORD = -4096;
  68. CGridNav::Init( false );
  69. }
  70. // Moved out of here for single config running, since we set the active
  71. // game BEFORE initializing the file system and the texture system now.
  72. //FileSystem_SetGame(g_pGameConfig->m_szModDir);
  73. //g_Textures.SetActiveConfig(g_pGameConfig);
  74. }
  75. //-----------------------------------------------------------------------------
  76. // Purpose: Constructor. Maintains a static counter uniquely identifying each
  77. // game configuration.
  78. //-----------------------------------------------------------------------------
  79. CGameConfig::CGameConfig(void)
  80. {
  81. nGDFiles = 0;
  82. textureformat = tfNone;
  83. m_fDefaultTextureScale = DEFAULT_TEXTURE_SCALE;
  84. m_nDefaultLightmapScale = DEFAULT_LIGHTMAP_SCALE;
  85. m_MaterialExcludeCount = 0;
  86. memset(szName, 0, sizeof(szName));
  87. memset(szExecutable, 0, sizeof(szExecutable));
  88. memset(szDefaultPoint, 0, sizeof(szDefaultPoint));
  89. memset(szDefaultSolid, 0, sizeof(szDefaultSolid));
  90. memset(szBSP, 0, sizeof(szBSP));
  91. memset(szLIGHT, 0, sizeof(szLIGHT));
  92. memset(szVIS, 0, sizeof(szVIS));
  93. memset(szMapDir, 0, sizeof(szMapDir));
  94. memset(m_szGameExeDir, 0, sizeof(m_szGameExeDir));
  95. memset(szBSPDir, 0, sizeof(szBSPDir));
  96. memset(m_szPrefabDir, 0, sizeof(m_szPrefabDir));
  97. memset(m_szModDir, 0, sizeof(m_szModDir));
  98. strcpy(m_szCordonTexture, "BLACK");
  99. m_szSteamDir[0] = '\0';
  100. m_szSteamAppID[0] = '\0';
  101. static DWORD __dwID = 0;
  102. dwID = __dwID++;
  103. }
  104. //-----------------------------------------------------------------------------
  105. // Purpose: Imports an old binary GameCfg.wc file.
  106. // Input : file -
  107. // fVersion -
  108. // Output : Returns TRUE on success, FALSE on failure.
  109. //-----------------------------------------------------------------------------
  110. BOOL CGameConfig::Import(std::fstream& file, float fVersion)
  111. {
  112. file.read(szName, sizeof szName);
  113. file.read((char*)&nGDFiles, sizeof nGDFiles);
  114. file.read((char*)&textureformat, sizeof textureformat);
  115. if (fVersion >= 1.1f)
  116. {
  117. file.read((char*)&mapformat, sizeof mapformat);
  118. }
  119. else
  120. {
  121. mapformat = mfQuake;
  122. }
  123. //
  124. // If reading an old (pre 1.4) format file, skip past the obselete palette
  125. // file path.
  126. //
  127. if (fVersion < 1.4f)
  128. {
  129. char szPalette[128];
  130. file.read(szPalette, sizeof szPalette);
  131. }
  132. file.read(szExecutable, sizeof szExecutable);
  133. file.read(szDefaultSolid, sizeof szDefaultSolid);
  134. file.read(szDefaultPoint, sizeof szDefaultPoint);
  135. if (fVersion >= 1.2f)
  136. {
  137. file.read(szBSP, sizeof szBSP);
  138. file.read(szLIGHT, sizeof szLIGHT);
  139. file.read(szVIS, sizeof szVIS);
  140. file.read(m_szGameExeDir, sizeof m_szGameExeDir);
  141. file.read(szMapDir, sizeof szMapDir);
  142. }
  143. if (fVersion >= 1.3f)
  144. {
  145. file.read(szBSPDir, sizeof(szBSPDir));
  146. }
  147. if (fVersion >= 1.4f)
  148. {
  149. // CSG setting is gone now.
  150. char szTempCSG[128];
  151. file.read(szTempCSG, sizeof(szTempCSG));
  152. file.read(m_szModDir, sizeof(m_szModDir));
  153. // gamedir is gone now.
  154. char tempGameDir[128];
  155. file.read(tempGameDir, sizeof(tempGameDir));
  156. }
  157. // read game data files
  158. char szBuf[128];
  159. for(int i = 0; i < nGDFiles; i++)
  160. {
  161. file.read(szBuf, sizeof szBuf);
  162. GDFiles.Add(CString(szBuf));
  163. }
  164. LoadGDFiles();
  165. return TRUE;
  166. }
  167. //-----------------------------------------------------------------------------
  168. // Purpose: Loads this game configuration from a keyvalue block.
  169. // Output : Returns true on success, false on failure.
  170. //-----------------------------------------------------------------------------
  171. bool CGameConfig::Load(KeyValues *pkv)
  172. {
  173. char szKey[MAX_PATH];
  174. // We should at least be able to get the game name and the game dir.
  175. Q_strncpy(szName, pkv->GetName(), sizeof(szName));
  176. Q_strncpy(m_szModDir, pkv->GetString("GameDir"), sizeof(m_szModDir));
  177. // Try to get the Hammer settings.
  178. KeyValues *pkvHammer = pkv->FindKey("Hammer");
  179. if (!pkvHammer)
  180. return true;
  181. //
  182. // Load the game data filenames from the "GameData0..GameDataN" keys.
  183. //
  184. nGDFiles = 0;
  185. bool bAdded = true;
  186. do
  187. {
  188. sprintf(szKey, "GameData%d", nGDFiles);
  189. const char *pszGameData = pkvHammer->GetString(szKey);
  190. if (pszGameData[0] != '\0')
  191. {
  192. GDFiles.Add(pszGameData);
  193. nGDFiles++;
  194. }
  195. else
  196. {
  197. bAdded = false;
  198. }
  199. } while (bAdded);
  200. textureformat = (TEXTUREFORMAT)pkvHammer->GetInt("TextureFormat", tfVMT);
  201. mapformat = (MAPFORMAT)pkvHammer->GetInt("MapFormat", mfHalfLife2);
  202. m_fDefaultTextureScale = pkvHammer->GetFloat("DefaultTextureScale", DEFAULT_TEXTURE_SCALE);
  203. if (m_fDefaultTextureScale == 0)
  204. {
  205. m_fDefaultTextureScale = DEFAULT_TEXTURE_SCALE;
  206. }
  207. m_nDefaultLightmapScale = pkvHammer->GetInt("DefaultLightmapScale", DEFAULT_LIGHTMAP_SCALE);
  208. Q_strncpy(szExecutable, pkvHammer->GetString("GameExe"), sizeof(szExecutable));
  209. Q_strncpy(szDefaultSolid, pkvHammer->GetString("DefaultSolidEntity"), sizeof(szDefaultSolid));
  210. Q_strncpy(szDefaultPoint, pkvHammer->GetString("DefaultPointEntity"), sizeof(szDefaultPoint));
  211. Q_strncpy(szBSP, pkvHammer->GetString("BSP"), sizeof(szBSP));
  212. Q_strncpy(szVIS, pkvHammer->GetString("Vis"), sizeof(szVIS));
  213. Q_strncpy(szLIGHT, pkvHammer->GetString("Light"), sizeof(szLIGHT));
  214. Q_strncpy(m_szGameExeDir, pkvHammer->GetString("GameExeDir"), sizeof(m_szGameExeDir));
  215. Q_strncpy(szMapDir, pkvHammer->GetString("MapDir"), sizeof(szMapDir));
  216. Q_strncpy(szBSPDir, pkvHammer->GetString("BSPDir"), sizeof(szBSPDir));
  217. Q_strncpy(m_szPrefabDir, pkvHammer->GetString("PrefabDir"), sizeof(m_szPrefabDir));
  218. SetCordonTexture( pkvHammer->GetString("CordonTexture", "BLACK") );
  219. char szExcludeDir[MAX_PATH];
  220. m_MaterialExcludeCount = pkvHammer->GetInt( "MaterialExcludeCount" );
  221. for ( int i = 0; i < m_MaterialExcludeCount; i++ )
  222. {
  223. sprintf( szExcludeDir, "-MaterialExcludeDir%d", i );
  224. int index = m_MaterialExclusions.AddToTail();
  225. Q_strncpy( m_MaterialExclusions[index].szDirectory, pkvHammer->GetString( szExcludeDir ), sizeof( m_MaterialExclusions[index].szDirectory ) );
  226. Q_StripTrailingSlash( m_MaterialExclusions[index].szDirectory );
  227. m_MaterialExclusions[index].bUserGenerated = true;
  228. }
  229. LoadGDFiles();
  230. return(true);
  231. }
  232. //-----------------------------------------------------------------------------
  233. // Purpose: Saves this config's data into a keyvalues object.
  234. // Output : Returns true on success, false on failure.
  235. //-----------------------------------------------------------------------------
  236. bool CGameConfig::Save(KeyValues *pkv)
  237. {
  238. pkv->SetName(szName);
  239. pkv->SetString("GameDir", m_szModDir);
  240. // Try to get the Hammer settings.
  241. KeyValues *pkvHammer = pkv->FindKey("Hammer");
  242. if (pkvHammer)
  243. {
  244. pkv->RemoveSubKey(pkvHammer);
  245. pkvHammer->deleteThis();
  246. }
  247. pkvHammer = pkv->CreateNewKey();
  248. if (!pkvHammer)
  249. return false;
  250. pkvHammer->SetName("Hammer");
  251. //
  252. // Load the game data filenames from the "GameData0..GameDataN" keys.
  253. //
  254. for (int i = 0; i < nGDFiles; i++)
  255. {
  256. char szKey[MAX_PATH];
  257. sprintf(szKey, "GameData%d", i);
  258. pkvHammer->SetString(szKey, GDFiles.GetAt(i));
  259. }
  260. pkvHammer->SetInt("TextureFormat", textureformat);
  261. pkvHammer->SetInt("MapFormat", mapformat);
  262. pkvHammer->SetFloat("DefaultTextureScale", m_fDefaultTextureScale);
  263. pkvHammer->SetInt("DefaultLightmapScale", m_nDefaultLightmapScale);
  264. pkvHammer->SetString("GameExe", szExecutable);
  265. pkvHammer->SetString("DefaultSolidEntity", szDefaultSolid);
  266. pkvHammer->SetString("DefaultPointEntity", szDefaultPoint);
  267. pkvHammer->SetString("BSP", szBSP);
  268. pkvHammer->SetString("Vis", szVIS);
  269. pkvHammer->SetString("Light", szLIGHT);
  270. pkvHammer->SetString("GameExeDir", m_szGameExeDir);
  271. pkvHammer->SetString("MapDir", szMapDir);
  272. pkvHammer->SetString("BSPDir", szBSPDir);
  273. pkvHammer->SetString("PrefabDir", m_szPrefabDir);
  274. pkvHammer->SetString("CordonTexture", m_szCordonTexture);
  275. char szExcludeDir[MAX_PATH];
  276. pkvHammer->SetInt("MaterialExcludeCount", m_MaterialExcludeCount);
  277. for (int i = 0; i < m_MaterialExcludeCount; i++)
  278. {
  279. sprintf(szExcludeDir, "-MaterialExcludeDir%d", i );
  280. pkvHammer->SetString(szExcludeDir, m_MaterialExclusions[i].szDirectory);
  281. }
  282. return true;
  283. }
  284. //-----------------------------------------------------------------------------
  285. // Purpose:
  286. // Input : file -
  287. //-----------------------------------------------------------------------------
  288. void CGameConfig::Save(std::fstream &file)
  289. {
  290. file.write(szName, sizeof szName);
  291. file.write((char*)&nGDFiles, sizeof nGDFiles);
  292. file.write((char*)&textureformat, sizeof textureformat);
  293. file.write((char*)&mapformat, sizeof mapformat);
  294. file.write(szExecutable, sizeof szExecutable);
  295. file.write(szDefaultSolid, sizeof szDefaultSolid);
  296. file.write(szDefaultPoint, sizeof szDefaultPoint);
  297. // 1.2
  298. file.write(szBSP, sizeof szBSP);
  299. file.write(szLIGHT, sizeof szLIGHT);
  300. file.write(szVIS, sizeof szVIS);
  301. file.write(m_szGameExeDir, sizeof(m_szGameExeDir));
  302. file.write(szMapDir, sizeof szMapDir);
  303. // 1.3
  304. file.write(szBSPDir, sizeof szBSPDir);
  305. // 1.4
  306. char tempCSG[128] = "";
  307. file.write(tempCSG, sizeof(tempCSG));
  308. file.write(m_szModDir, sizeof(m_szModDir));
  309. char tempGameDir[128] = "";
  310. file.write(tempGameDir, sizeof(tempGameDir));
  311. // write game data files
  312. char szBuf[128];
  313. for(int i = 0; i < nGDFiles; i++)
  314. {
  315. strcpy(szBuf, GDFiles[i]);
  316. file.write(szBuf, sizeof szBuf);
  317. }
  318. }
  319. //-----------------------------------------------------------------------------
  320. // Purpose:
  321. // Input : *pConfig -
  322. //-----------------------------------------------------------------------------
  323. void CGameConfig::CopyFrom(CGameConfig *pConfig)
  324. {
  325. nGDFiles = pConfig->nGDFiles;
  326. GDFiles.RemoveAll();
  327. GDFiles.Append(pConfig->GDFiles);
  328. strcpy(szName, pConfig->szName);
  329. strcpy(szExecutable, pConfig->szExecutable);
  330. strcpy(szDefaultPoint, pConfig->szDefaultPoint);
  331. strcpy(szDefaultSolid, pConfig->szDefaultSolid);
  332. strcpy(szBSP, pConfig->szBSP);
  333. strcpy(szLIGHT, pConfig->szLIGHT);
  334. strcpy(szVIS, pConfig->szVIS);
  335. strcpy(szMapDir, pConfig->szMapDir);
  336. strcpy(m_szGameExeDir, pConfig->m_szGameExeDir);
  337. strcpy(szBSPDir, pConfig->szBSPDir);
  338. strcpy(m_szModDir, pConfig->m_szModDir);
  339. pConfig->m_MaterialExcludeCount = m_MaterialExcludeCount;
  340. for( int i = 0; i < m_MaterialExcludeCount; i++ )
  341. {
  342. strcpy( m_MaterialExclusions[i].szDirectory, pConfig->m_MaterialExclusions[i].szDirectory );
  343. }
  344. }
  345. //-----------------------------------------------------------------------------
  346. // Purpose:
  347. // Input : pEntity -
  348. // pGD -
  349. // Output : Returns TRUE to keep enumerating.
  350. //-----------------------------------------------------------------------------
  351. static BOOL UpdateClassPointer(CMapEntity *pEntity, GameData *pGD)
  352. {
  353. GDclass *pClass = pGD->ClassForName(pEntity->GetClassName());
  354. pEntity->SetClass(pClass);
  355. return(TRUE);
  356. }
  357. //-----------------------------------------------------------------------------
  358. // Purpose:
  359. //-----------------------------------------------------------------------------
  360. void CGameConfig::LoadGDFiles(void)
  361. {
  362. GD.ClearData();
  363. // Save the old working directory
  364. char szOldDir[MAX_PATH];
  365. _getcwd( szOldDir, sizeof(szOldDir) );
  366. // Set our working directory properly
  367. char szAppDir[MAX_PATH];
  368. APP()->GetDirectory( DIR_PROGRAM, szAppDir );
  369. _chdir( szAppDir );
  370. for (int i = 0; i < nGDFiles; i++)
  371. {
  372. GD.Load(GDFiles[i]);
  373. }
  374. // Reset our old working directory
  375. _chdir( szOldDir );
  376. // All the class pointers have changed - now we have to
  377. // reset all the class pointers in each map doc that
  378. // uses this game.
  379. for ( int i=0; i<CMapDoc::GetDocumentCount(); i++ )
  380. {
  381. CMapDoc *pDoc = CMapDoc::GetDocument(i);
  382. if (pDoc->GetGame() == this)
  383. {
  384. CMapWorld *pWorld = pDoc->GetMapWorld();
  385. pWorld->SetClass(GD.ClassForName(pWorld->GetClassName()));
  386. pWorld->EnumChildren((ENUMMAPCHILDRENPROC)UpdateClassPointer, (DWORD)&GD, MAPCLASS_TYPE(CMapEntity));
  387. }
  388. }
  389. }
  390. //-----------------------------------------------------------------------------
  391. // Purpose: Searches for the given filename, starting in szStartDir and looking
  392. // up the directory tree.
  393. // Input: szFile - the name of the file to search for.
  394. // szStartDir - the folder to start searching from, towards the root.
  395. // szFoundPath - receives the full path of the FOLDER where szFile was found.
  396. // Output : Returns true if the file was found, false if not. If the file was
  397. // found the full path (not including the filename) is returned in szFoundPath.
  398. //-----------------------------------------------------------------------------
  399. bool FindFileInTree(const char *szFile, const char *szStartDir, char *szFoundPath)
  400. {
  401. if ((szFile == NULL) || (szStartDir == NULL) || (szFoundPath == NULL))
  402. {
  403. return false;
  404. }
  405. char szRoot[MAX_PATH];
  406. strcpy(szRoot, szStartDir);
  407. Q_AppendSlash(szRoot, sizeof(szRoot));
  408. char szTemp[MAX_PATH];
  409. do
  410. {
  411. strcpy(szTemp, szRoot);
  412. strcat(szTemp, szFile);
  413. if (!_access(szTemp, 0))
  414. {
  415. strcpy(szFoundPath, szRoot);
  416. Q_StripTrailingSlash(szFoundPath);
  417. return true;
  418. }
  419. } while (Q_StripLastDir(szRoot, sizeof(szRoot)));
  420. return false;
  421. }
  422. //-----------------------------------------------------------------------------
  423. // Purpose:
  424. // Input : *szDir -
  425. // *szSteamDir -
  426. // *szSteamUserDir -
  427. // Output : Returns true on success, false on failure.
  428. //-----------------------------------------------------------------------------
  429. bool FindSteamUserDir(const char *szAppDir, const char *szSteamDir, char *szSteamUserDir)
  430. {
  431. if ((szAppDir == NULL) || (szSteamDir == NULL) || (szSteamUserDir == NULL))
  432. {
  433. return false;
  434. }
  435. // If the szAppDir was run from within the steam tree, we should be able to find the steam user dir.
  436. int nSteamDirLen = strlen(szSteamDir);
  437. if (!Q_strnicmp(szAppDir, szSteamDir, nSteamDirLen ) && (szAppDir[nSteamDirLen] == '\\'))
  438. {
  439. strcpy(szSteamUserDir, szAppDir);
  440. char *pszSlash = strchr(&szSteamUserDir[nSteamDirLen + 1], '\\');
  441. if (pszSlash)
  442. {
  443. pszSlash++;
  444. pszSlash = strchr(pszSlash, '\\');
  445. if (pszSlash)
  446. {
  447. *pszSlash = '\0';
  448. return true;
  449. }
  450. }
  451. }
  452. szSteamUserDir[0] = '\0';
  453. return false;
  454. }
  455. // memdbgon must be the last include file in a .cpp file!!!
  456. #include "tier0/memdbgoff.h"
  457. //-----------------------------------------------------------------------------
  458. // Purpose: Loads the settings from <mod dir>\gameinfo.txt into data members.
  459. //-----------------------------------------------------------------------------
  460. void CGameConfig::ParseGameInfo()
  461. {
  462. KeyValues *pkv = new KeyValues("gameinfo.txt");
  463. if (!pkv->LoadFromFile(g_pFileSystem, "gameinfo.txt", "GAME"))
  464. {
  465. pkv->deleteThis();
  466. return;
  467. }
  468. KeyValues *pKey = pkv->FindKey("FileSystem");
  469. if (pKey)
  470. {
  471. strcpy(m_szSteamAppID, pKey->GetString("SteamAppId", ""));
  472. }
  473. const char *InstancePath = pkv->GetString( "InstancePath", NULL );
  474. if ( InstancePath )
  475. {
  476. CMapInstance::SetInstancePath( InstancePath );
  477. }
  478. pkv->deleteThis();
  479. char szAppDir[MAX_PATH];
  480. APP()->GetDirectory(DIR_PROGRAM, szAppDir);
  481. if (!FindFileInTree("steam.exe", szAppDir, m_szSteamDir))
  482. {
  483. // Couldn't find steam.exe in the hammer tree
  484. m_szSteamDir[0] = '\0';
  485. }
  486. if (!FindSteamUserDir(szAppDir, m_szSteamDir, m_szSteamUserDir))
  487. {
  488. m_szSteamUserDir[0] = '\0';
  489. }
  490. }
  491. //-----------------------------------------------------------------------------
  492. // Accessor methods to get at the mod + the game (*not* full paths)
  493. //-----------------------------------------------------------------------------
  494. const char *CGameConfig::GetMod()
  495. {
  496. // Strip path from modDir
  497. char szModPath[MAX_PATH];
  498. static char szMod[MAX_PATH];
  499. Q_strncpy( szModPath, m_szModDir, MAX_PATH );
  500. Q_StripTrailingSlash( szModPath );
  501. if ( !szModPath[0] )
  502. {
  503. Q_strcpy( szModPath, "hl2" );
  504. }
  505. Q_FileBase( szModPath, szMod, MAX_PATH );
  506. return szMod;
  507. }
  508. const char *CGameConfig::GetGame()
  509. {
  510. return "hl2";
  511. // // Strip path from modDir
  512. // char szGamePath[MAX_PATH];
  513. // static char szGame[MAX_PATH];
  514. // Q_strncpy( szGamePath, m_szGameDir, MAX_PATH );
  515. // Q_StripTrailingSlash( szGamePath );
  516. // Q_FileBase( szGamePath, szGame, MAX_PATH );
  517. // return szGame;
  518. }