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.
922 lines
27 KiB
922 lines
27 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#include <windows.h> |
|
#include "interface.h" |
|
#include "tier0/icommandline.h" |
|
#include "filesystem_tools.h" |
|
#include "KeyValues.h" |
|
#include "tier1/utlbuffer.h" |
|
#include <io.h> |
|
#include <fcntl.h> |
|
#include <sys/types.h> |
|
#include <sys/stat.h> |
|
#include <stdio.h> |
|
#include "ConfigManager.h" |
|
#include "SourceAppInfo.h" |
|
#include "steam/steam_api.h" |
|
|
|
extern CSteamAPIContext *steamapicontext; |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include <tier0/memdbgon.h> |
|
|
|
#define GAME_CONFIG_FILENAME "GameConfig.txt" |
|
#define TOKEN_SDK_VERSION "SDKVersion" |
|
|
|
// Version history: |
|
// 0 - Initial release |
|
// 1 - Versioning added, DoD configuration added |
|
// 2 - Ep1 added |
|
// 3 - Ep2, TF2, and Portal added |
|
// 4 - TF2 moved to its own engine |
|
|
|
#define SDK_LAUNCHER_VERSION 5 |
|
|
|
// Half-Life 2 |
|
defaultConfigInfo_t HL2Info = |
|
{ |
|
"Half-Life 2", |
|
"hl2", |
|
"halflife2.fgd", |
|
"info_player_start", |
|
"hl2.exe", |
|
GetAppSteamAppId( k_App_HL2 ) |
|
}; |
|
|
|
// Counter-Strike: Source |
|
defaultConfigInfo_t CStrikeInfo = |
|
{ |
|
"Counter-Strike: Source", |
|
"cstrike", |
|
"cstrike.fgd", |
|
"info_player_terrorist", |
|
"hl2.exe", |
|
GetAppSteamAppId( k_App_CSS ) |
|
}; |
|
|
|
//Half-Life 2: Deathmatch |
|
defaultConfigInfo_t HL2DMInfo = |
|
{ |
|
"Half-Life 2: Deathmatch", |
|
"hl2mp", |
|
"hl2mp.fgd", |
|
"info_player_deathmatch", |
|
"hl2.exe", |
|
GetAppSteamAppId( k_App_HL2MP ) |
|
}; |
|
|
|
// Day of Defeat: Source |
|
defaultConfigInfo_t DODInfo = |
|
{ |
|
"Day of Defeat: Source", |
|
"dod", |
|
"dod.fgd", |
|
"info_player_allies", |
|
"hl2.exe", |
|
GetAppSteamAppId( k_App_DODS ) |
|
}; |
|
|
|
// Half-Life 2 Episode 1 |
|
defaultConfigInfo_t Episode1Info = |
|
{ |
|
"Half-Life 2: Episode One", |
|
"episodic", |
|
"halflife2.fgd", |
|
"info_player_start", |
|
"hl2.exe", |
|
GetAppSteamAppId( k_App_HL2_EP1 ) |
|
}; |
|
|
|
// Half-Life 2 Episode 2 |
|
defaultConfigInfo_t Episode2Info = |
|
{ |
|
"Half-Life 2: Episode Two", |
|
"ep2", |
|
"halflife2.fgd", |
|
"info_player_start", |
|
"hl2.exe", |
|
GetAppSteamAppId( k_App_HL2_EP2 ) |
|
}; |
|
|
|
// Team Fortress 2 |
|
defaultConfigInfo_t TF2Info = |
|
{ |
|
"Team Fortress 2", |
|
"tf", |
|
"tf.fgd", |
|
"info_player_teamspawn", |
|
"hl2.exe", |
|
GetAppSteamAppId( k_App_TF2 ) |
|
}; |
|
|
|
// Portal |
|
defaultConfigInfo_t PortalInfo = |
|
{ |
|
"Portal", |
|
"portal", |
|
"portal.fgd", |
|
"info_player_start", |
|
"hl2.exe", |
|
GetAppSteamAppId( k_App_PORTAL ) |
|
}; |
|
|
|
// Portal |
|
defaultConfigInfo_t SourceTestInfo = |
|
{ |
|
"SourceTest", |
|
"sourcetest", |
|
"halflife2.fgd", |
|
"info_player_start", |
|
"hl2.exe", |
|
243730 |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Constructor |
|
//----------------------------------------------------------------------------- |
|
CGameConfigManager::CGameConfigManager( void ) : m_pData( NULL ), m_LoadStatus( LOADSTATUS_NONE ) |
|
{ |
|
// Start with default directory |
|
GetModuleFileName( ( HINSTANCE )GetModuleHandle( NULL ), m_szBaseDirectory, sizeof( m_szBaseDirectory ) ); |
|
Q_StripLastDir( m_szBaseDirectory, sizeof( m_szBaseDirectory ) ); // Get rid of the filename. |
|
Q_StripTrailingSlash( m_szBaseDirectory ); |
|
m_eSDKEpoch = (eSDKEpochs) SDK_LAUNCHER_VERSION; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Destructor |
|
//----------------------------------------------------------------------------- |
|
CGameConfigManager::~CGameConfigManager( void ) |
|
{ |
|
// Release the keyvalues |
|
if ( m_pData != NULL ) |
|
{ |
|
m_pData->deleteThis(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Config loading interface |
|
// Input : *baseDir - base directory for our file |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CGameConfigManager::LoadConfigs( const char *baseDir ) |
|
{ |
|
return LoadConfigsInternal( baseDir, false ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Loads a file into the given utlbuffer. |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool ReadUtlBufferFromFile( CUtlBuffer &buffer, const char *szPath ) |
|
{ |
|
struct _stat fileInfo; |
|
if ( _stat( szPath, &fileInfo ) == -1 ) |
|
{ |
|
return false; |
|
} |
|
|
|
buffer.EnsureCapacity( fileInfo.st_size ); |
|
|
|
int nFile = _open( szPath, _O_BINARY | _O_RDONLY ); |
|
if ( nFile == -1 ) |
|
{ |
|
return false; |
|
} |
|
|
|
if ( _read( nFile, buffer.Base(), fileInfo.st_size ) != fileInfo.st_size ) |
|
{ |
|
_close( nFile ); |
|
return false; |
|
} |
|
|
|
_close( nFile ); |
|
buffer.SeekPut( CUtlBuffer::SEEK_HEAD, fileInfo.st_size ); |
|
return true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Loads a file into the given utlbuffer. |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool SaveUtlBufferToFile( CUtlBuffer &buffer, const char *szPath ) |
|
{ |
|
int nFile = _open( szPath, _O_TEXT | _O_CREAT | _O_TRUNC | _O_RDWR, _S_IWRITE ); |
|
if ( nFile == -1 ) |
|
{ |
|
return false; |
|
} |
|
|
|
int nSize = buffer.TellMaxPut(); |
|
|
|
if ( _write( nFile, buffer.Base(), nSize ) < nSize ) |
|
{ |
|
_close( nFile ); |
|
return false; |
|
} |
|
|
|
_close( nFile ); |
|
return true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Load a game configuration file (with fail-safes) |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CGameConfigManager::LoadConfigsInternal( const char *baseDir, bool bRecursiveCall ) |
|
{ |
|
// Init the config if it doesn't exist |
|
if ( !IsLoaded() ) |
|
{ |
|
m_pData = new KeyValues( GAME_CONFIG_FILENAME ); |
|
|
|
if ( !IsLoaded() ) |
|
{ |
|
m_LoadStatus = LOADSTATUS_ERROR; |
|
return false; |
|
} |
|
} |
|
|
|
// Clear it out |
|
m_pData->Clear(); |
|
|
|
// Build our default directory |
|
if ( baseDir != NULL && baseDir[0] != NULL ) |
|
{ |
|
SetBaseDirectory( baseDir ); |
|
} |
|
|
|
// Make a full path name |
|
char szPath[MAX_PATH]; |
|
Q_snprintf( szPath, sizeof( szPath ), "%s\\%s", GetBaseDirectory(), GAME_CONFIG_FILENAME ); |
|
|
|
bool bLoaded = false; |
|
|
|
CUtlBuffer buffer( 0, 0, CUtlBuffer::TEXT_BUFFER ); |
|
if ( ReadUtlBufferFromFile( buffer, szPath ) ) |
|
{ |
|
bLoaded = m_pData->LoadFromBuffer( szPath, buffer, NULL, NULL ); |
|
} |
|
|
|
if ( !bLoaded ) |
|
{ |
|
// Attempt to re-create the configs |
|
if ( CreateAllDefaultConfigs() ) |
|
{ |
|
// Only allow this once |
|
if ( !bRecursiveCall ) |
|
return LoadConfigsInternal( baseDir, true ); |
|
|
|
// Version the config. |
|
VersionConfig(); |
|
} |
|
|
|
m_LoadStatus = LOADSTATUS_ERROR; |
|
return false; |
|
} |
|
else |
|
{ |
|
// Check to see if the gameconfig.txt is up to date. |
|
UpdateConfigsInternal(); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Add to the current config. |
|
//----------------------------------------------------------------------------- |
|
void CGameConfigManager::UpdateConfigsInternal( void ) |
|
{ |
|
// Check to a valid gameconfig.txt file buffer. |
|
if ( !IsLoaded() ) |
|
return; |
|
|
|
// Check for version first. If the version is up to date, it is assumed to be accurate |
|
if ( IsConfigCurrent() ) |
|
return; |
|
|
|
KeyValues *pGameBlock = GetGameBlock(); |
|
if ( !pGameBlock ) |
|
{ |
|
// If we don't have a game block, reset the config file. |
|
ResetConfigs(); |
|
return; |
|
} |
|
|
|
KeyValues *pDefaultBlock = new KeyValues( "DefaultConfigs" ); |
|
if ( pDefaultBlock != NULL ) |
|
{ |
|
// Compile our default configurations |
|
GetDefaultGameBlock( pDefaultBlock ); |
|
|
|
// Compare our default block to our current configs |
|
KeyValues *pNextSubKey = pDefaultBlock->GetFirstTrueSubKey(); |
|
while ( pNextSubKey != NULL ) |
|
{ |
|
// If we already have the name, we don't care about it |
|
if ( pGameBlock->FindKey( pNextSubKey->GetName() ) ) |
|
{ |
|
// Advance by one key |
|
pNextSubKey = pNextSubKey->GetNextTrueSubKey(); |
|
continue; |
|
} |
|
|
|
// Copy the data through to our game block |
|
KeyValues *pKeyCopy = pNextSubKey->MakeCopy(); |
|
pGameBlock->AddSubKey( pKeyCopy ); |
|
|
|
// Advance by one key |
|
pNextSubKey = pNextSubKey->GetNextTrueSubKey(); |
|
} |
|
|
|
// All done |
|
pDefaultBlock->deleteThis(); |
|
} |
|
|
|
// Save the new config. |
|
SaveConfigs(); |
|
|
|
// Add the new version as we have been updated. |
|
VersionConfig(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Update the gameconfig.txt version number. |
|
//----------------------------------------------------------------------------- |
|
void CGameConfigManager::VersionConfig( void ) |
|
{ |
|
// Check to a valid gameconfig.txt file buffer. |
|
if ( !IsLoaded() ) |
|
return; |
|
|
|
// Look for the a version key value pair and update it. |
|
KeyValues *pKeyVersion = m_pData->FindKey( TOKEN_SDK_VERSION ); |
|
|
|
// Update the already existing version key value pair. |
|
if ( pKeyVersion ) |
|
{ |
|
if ( pKeyVersion->GetInt() == m_eSDKEpoch ) |
|
return; |
|
|
|
m_pData->SetInt( TOKEN_SDK_VERSION, m_eSDKEpoch ); |
|
} |
|
// Create a new version key value pair. |
|
else |
|
{ |
|
m_pData->SetInt( TOKEN_SDK_VERSION, m_eSDKEpoch ); |
|
} |
|
|
|
// Save the configuration. |
|
SaveConfigs(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Check to see if the version of the gameconfig.txt is up to date. |
|
//----------------------------------------------------------------------------- |
|
bool CGameConfigManager::IsConfigCurrent( void ) |
|
{ |
|
// Check to a valid gameconfig.txt file buffer. |
|
if ( !IsLoaded() ) |
|
return false; |
|
|
|
KeyValues *pKeyValue = m_pData->FindKey( TOKEN_SDK_VERSION ); |
|
if ( !pKeyValue ) |
|
return false; |
|
|
|
int nVersion = pKeyValue->GetInt(); |
|
if ( nVersion == m_eSDKEpoch ) |
|
return true; |
|
|
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Get the base path for a default config's install (handling steam's paths) |
|
//----------------------------------------------------------------------------- |
|
void CGameConfigManager::GetRootGameDirectory( char *out, size_t outLen, const char *rootDir ) |
|
{ |
|
Q_strncpy( out, rootDir, outLen ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Get the base path for a default config's content sources (handling steam's paths) |
|
//----------------------------------------------------------------------------- |
|
void CGameConfigManager::GetRootContentDirectory( char *out, size_t outLen, const char *rootDir ) |
|
{ |
|
// Steam install is different |
|
if ( g_pFullFileSystem ) |
|
{ |
|
Q_snprintf( out, outLen, "%s\\sourcesdk_content", rootDir ); |
|
} |
|
else |
|
{ |
|
Q_snprintf( out, outLen, "%s\\content", rootDir ); |
|
} |
|
} |
|
|
|
// Default game configuration template |
|
const char szDefaultConfigText[] = |
|
"\"%gamename%\"\ |
|
{\ |
|
\"GameDir\" \"%gamedir%\"\ |
|
\"Hammer\"\ |
|
{\ |
|
\"TextureFormat\" \"5\"\ |
|
\"MapFormat\" \"4\"\ |
|
\"DefaultTextureScale\" \"0.250000\"\ |
|
\"DefaultLightmapScale\" \"16\"\ |
|
\"DefaultSolidEntity\" \"func_detail\"\ |
|
\"DefaultPointEntity\" \"%defaultpointentity%\"\ |
|
\"GameExeDir\" \"%gameexe%\"\ |
|
\"MapDir\" \"%gamemaps%\"\ |
|
\"CordonTexture\" \"tools\\toolsskybox\"\ |
|
\"MaterialExcludeCount\" \"0\"\ |
|
\"GameExe\" \"%gameEXE%\"\ |
|
\"BSP\" \"%bspdir%\"\ |
|
\"Vis\" \"%visdir%\"\ |
|
\"Light\" \"%lightdir%\"\ |
|
}}"; |
|
|
|
// NOTE: This function could use some re-write, it can't handle non-retail paths well |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Add a templated default configuration with proper paths |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CGameConfigManager::AddDefaultConfig( const defaultConfigInfo_t &info, KeyValues *out, const char *rootDirectory, const char *gameExeDir ) |
|
{ |
|
// NOTE: Freed by head keyvalue |
|
KeyValues *newConfig = new KeyValues( info.gameName ); |
|
if ( newConfig->LoadFromBuffer( "defaultcfg.txt", szDefaultConfigText ) == false ) |
|
return false; |
|
|
|
newConfig->SetName( info.gameName ); |
|
|
|
// Game's root directory (with special steam name handling) |
|
char rootGameDir[MAX_PATH]; |
|
GetRootGameDirectory( rootGameDir, sizeof( rootGameDir ), rootDirectory ); |
|
|
|
// Game's content directory |
|
char contentRootDir[MAX_PATH]; |
|
GetRootContentDirectory( contentRootDir, sizeof( contentRootDir ), rootDirectory ); |
|
|
|
char szPath[MAX_PATH]; |
|
|
|
// Game directory |
|
Q_snprintf( szPath, sizeof( szPath ), "%s\\%s", rootGameDir, info.gameDir ); |
|
|
|
if ( !g_pFullFileSystem->IsDirectory( szPath ) ) |
|
return false; |
|
|
|
newConfig->SetString( "GameDir", szPath ); |
|
|
|
// Create the Hammer portion of this block |
|
KeyValues *hammerBlock = newConfig->FindKey( "Hammer" ); |
|
|
|
if ( hammerBlock == NULL ) |
|
return false; |
|
|
|
hammerBlock->SetString( "GameExeDir", gameExeDir ); |
|
|
|
// Fill in the proper default point entity |
|
hammerBlock->SetString( "DefaultPointEntity", info.defaultPointEntity ); |
|
|
|
// Fill in the default VMF directory |
|
char contentMapDir[MAX_PATH]; |
|
Q_snprintf( contentMapDir, sizeof( contentMapDir ), "%s\\%s\\mapsrc", contentRootDir, info.gameDir ); |
|
hammerBlock->SetString( "MapDir", contentMapDir ); |
|
|
|
Q_snprintf( szPath, sizeof( szPath ), "%s\\%s\\maps", rootGameDir, info.gameDir ); |
|
hammerBlock->SetString( "BSPDir", szPath ); |
|
|
|
// Fill in the game executable |
|
Q_snprintf( szPath, sizeof( szPath ), "%s\\%s", gameExeDir, info.exeName ); |
|
hammerBlock->SetString( "GameEXE", szPath ); |
|
|
|
//Fill in game FGDs |
|
if ( info.FGD[0] != '\0' ) |
|
{ |
|
Q_snprintf( szPath, sizeof( szPath ), "%s\\%s", GetBaseDirectory(), info.FGD ); |
|
hammerBlock->SetString( "GameData0", szPath ); |
|
} |
|
|
|
// Fill in the tools path |
|
Q_snprintf( szPath, sizeof( szPath ), "%s\\vbsp.exe", GetBaseDirectory() ); |
|
hammerBlock->SetString( "BSP", szPath ); |
|
|
|
Q_snprintf( szPath, sizeof( szPath ), "%s\\vvis.exe", GetBaseDirectory() ); |
|
hammerBlock->SetString( "Vis", szPath ); |
|
|
|
Q_snprintf( szPath, sizeof( szPath ), "%s\\vrad.exe", GetBaseDirectory() ); |
|
hammerBlock->SetString( "Light", szPath ); |
|
|
|
// Get our insertion point |
|
KeyValues *insertSpot = out->GetFirstTrueSubKey(); |
|
|
|
// Set this as the sub key if there's nothing already there |
|
if ( insertSpot == NULL ) |
|
{ |
|
out->AddSubKey( newConfig ); |
|
} |
|
else |
|
{ |
|
// Find the last subkey |
|
while ( insertSpot->GetNextTrueSubKey() ) |
|
{ |
|
insertSpot = insertSpot->GetNextTrueSubKey(); |
|
} |
|
|
|
// Become a peer to it |
|
insertSpot->SetNextKey( newConfig ); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Determines whether the requested appID is installed on this computer |
|
// Input : nAppID - ID to verify |
|
// Output : Returns true if installed, false if not. |
|
//----------------------------------------------------------------------------- |
|
bool CGameConfigManager::IsAppSubscribed( int nAppID ) |
|
{ |
|
bool bIsSubscribed = false; |
|
|
|
if ( steamapicontext && steamapicontext->SteamApps() ) |
|
{ |
|
// See if specified app is installed |
|
bIsSubscribed = steamapicontext->SteamApps()->BIsSubscribedApp( nAppID ); |
|
} |
|
else |
|
{ |
|
// If we aren't running FileSystem Steam then we must be doing internal development. Give everything. |
|
bIsSubscribed = true; |
|
} |
|
|
|
return bIsSubscribed; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Create default configurations for all Valve retail applications |
|
//----------------------------------------------------------------------------- |
|
bool CGameConfigManager::CreateAllDefaultConfigs( void ) |
|
{ |
|
bool bRetVal = true; |
|
|
|
// Start our new block |
|
KeyValues *configBlock = new KeyValues( "Configs" ); |
|
KeyValues *gameBlock = configBlock->CreateNewKey(); |
|
gameBlock->SetName( "Games" ); |
|
|
|
GetDefaultGameBlock( gameBlock ); |
|
|
|
bRetVal = !gameBlock->IsEmpty(); |
|
|
|
// Make a full path name |
|
char szPath[MAX_PATH]; |
|
Q_snprintf( szPath, sizeof( szPath ), "%s\\%s", GetBaseDirectory(), GAME_CONFIG_FILENAME ); |
|
|
|
CUtlBuffer buffer; |
|
configBlock->RecursiveSaveToFile( buffer, 0 ); |
|
SaveUtlBufferToFile( buffer, szPath ); |
|
|
|
configBlock->deleteThis(); |
|
|
|
m_LoadStatus = LOADSTATUS_CREATED; |
|
|
|
return bRetVal; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Load game information from an INI file |
|
//----------------------------------------------------------------------------- |
|
bool CGameConfigManager::ConvertGameConfigsINI( void ) |
|
{ |
|
const char *iniFilePath = GetIniFilePath(); |
|
|
|
// Load our INI file |
|
int nNumConfigs = GetPrivateProfileInt( "Configs", "NumConfigs", 0, iniFilePath ); |
|
if ( nNumConfigs <= 0 ) |
|
return false; |
|
|
|
// Build a new keyvalue file |
|
KeyValues *headBlock = new KeyValues( "Configs" ); |
|
|
|
// Create the block for games |
|
KeyValues *gamesBlock = headBlock->CreateNewKey( ); |
|
gamesBlock->SetName( "Games" ); |
|
|
|
int i; |
|
int nStrlen; |
|
char szSectionName[MAX_PATH]; |
|
char textBuffer[MAX_PATH]; |
|
|
|
// Parse all the configs |
|
for ( int nConfig = 0; nConfig < nNumConfigs; nConfig++ ) |
|
{ |
|
// Each came configuration is stored in a different section, named "GameConfig0..GameConfigN". |
|
// If the "Name" key exists in this section, try to load the configuration from this section. |
|
sprintf(szSectionName, "GameConfig%d", nConfig); |
|
|
|
int nCount = GetPrivateProfileString(szSectionName, "Name", "", textBuffer, sizeof(textBuffer), iniFilePath); |
|
if (nCount > 0) |
|
{ |
|
// Make a new section |
|
KeyValues *subGame = gamesBlock->CreateNewKey(); |
|
subGame->SetName( textBuffer ); |
|
|
|
GetPrivateProfileString( szSectionName, "ModDir", "", textBuffer, sizeof(textBuffer), iniFilePath); |
|
|
|
// Add the mod dir |
|
subGame->SetString( "GameDir", textBuffer ); |
|
|
|
// Start a block for Hammer settings |
|
KeyValues *hammerBlock = subGame->CreateNewKey(); |
|
hammerBlock->SetName( "Hammer" ); |
|
|
|
i = 0; |
|
|
|
// Get all FGDs |
|
do |
|
{ |
|
char szGameData[MAX_PATH]; |
|
|
|
sprintf( szGameData, "GameData%d", i ); |
|
nStrlen = GetPrivateProfileString( szSectionName, szGameData, "", textBuffer, sizeof(textBuffer), iniFilePath ); |
|
|
|
if ( nStrlen > 0 ) |
|
{ |
|
hammerBlock->SetString( szGameData, textBuffer ); |
|
i++; |
|
} |
|
} while ( nStrlen > 0 ); |
|
|
|
hammerBlock->SetInt( "TextureFormat", GetPrivateProfileInt( szSectionName, "TextureFormat", 5 /*FIXME: tfVMT*/, iniFilePath ) ); |
|
hammerBlock->SetInt( "MapFormat", GetPrivateProfileInt( szSectionName, "MapFormat", 4 /*FIXME: mfHalfLife2*/, iniFilePath ) ); |
|
|
|
// Default texture scale |
|
GetPrivateProfileString( szSectionName, "DefaultTextureScale", "1", textBuffer, sizeof(textBuffer), iniFilePath ); |
|
float defaultTextureScale = (float) atof( textBuffer ); |
|
if ( defaultTextureScale == 0 ) |
|
{ |
|
defaultTextureScale = 1.0f; |
|
} |
|
|
|
hammerBlock->SetFloat( "DefaultTextureScale", defaultTextureScale ); |
|
|
|
hammerBlock->SetInt( "DefaultLightmapScale", GetPrivateProfileInt( szSectionName, "DefaultLightmapScale", 16 /*FIXME: DEFAULT_LIGHTMAP_SCALE*/, iniFilePath ) ); |
|
|
|
GetPrivateProfileString( szSectionName, "GameExe", "", textBuffer, sizeof(textBuffer), iniFilePath ); |
|
hammerBlock->SetString( "GameExe", textBuffer ); |
|
|
|
GetPrivateProfileString( szSectionName, "DefaultSolidEntity", "", textBuffer, sizeof(textBuffer), iniFilePath ); |
|
hammerBlock->SetString( "DefaultSolidEntity", textBuffer ); |
|
|
|
GetPrivateProfileString( szSectionName, "DefaultPointEntity", "", textBuffer, sizeof(textBuffer), iniFilePath ); |
|
hammerBlock->SetString( "DefaultPointEntity", textBuffer ); |
|
|
|
GetPrivateProfileString( szSectionName, "BSP", "", textBuffer, sizeof(textBuffer), iniFilePath ); |
|
hammerBlock->SetString( "BSP", textBuffer ); |
|
|
|
GetPrivateProfileString( szSectionName, "Vis", "", textBuffer, sizeof(textBuffer), iniFilePath ); |
|
hammerBlock->SetString( "Vis", textBuffer ); |
|
|
|
GetPrivateProfileString( szSectionName, "Light", "", textBuffer, sizeof(textBuffer), iniFilePath ); |
|
hammerBlock->SetString( "Light", textBuffer ); |
|
|
|
GetPrivateProfileString( szSectionName, "GameExeDir", "", textBuffer, sizeof(textBuffer), iniFilePath ); |
|
hammerBlock->SetString( "GameExeDir", textBuffer ); |
|
|
|
GetPrivateProfileString( szSectionName, "MapDir", "", textBuffer, sizeof(textBuffer), iniFilePath ); |
|
hammerBlock->SetString( "MapDir", textBuffer ); |
|
|
|
GetPrivateProfileString( szSectionName, "BSPDir", "", textBuffer, sizeof(textBuffer), iniFilePath ); |
|
hammerBlock->SetString( "BSPDir", textBuffer ); |
|
|
|
GetPrivateProfileString( szSectionName, "CordonTexture", "", textBuffer, sizeof(textBuffer), iniFilePath ); |
|
hammerBlock->SetString( "CordonTexture", textBuffer ); |
|
|
|
GetPrivateProfileString( szSectionName, "MaterialExcludeCount", "0", textBuffer, sizeof(textBuffer), iniFilePath ); |
|
int materialExcludeCount = atoi( textBuffer ); |
|
hammerBlock->SetInt( "MaterialExcludeCount", materialExcludeCount ); |
|
|
|
char excludeDir[MAX_PATH]; |
|
|
|
// Write out all excluded directories |
|
for( i = 0; i < materialExcludeCount; i++ ) |
|
{ |
|
sprintf( &excludeDir[0], "-MaterialExcludeDir%d", i ); |
|
GetPrivateProfileString( szSectionName, excludeDir, "", textBuffer, sizeof( textBuffer ), iniFilePath ); |
|
hammerBlock->SetString( excludeDir, textBuffer ); |
|
} |
|
} |
|
} |
|
// Make a full path name |
|
char szPath[MAX_PATH]; |
|
Q_snprintf( szPath, sizeof( szPath ), "%s\\%s", GetBaseDirectory(), GAME_CONFIG_FILENAME ); |
|
|
|
CUtlBuffer buffer; |
|
headBlock->RecursiveSaveToFile( buffer, 0 ); |
|
SaveUtlBufferToFile( buffer, szPath ); |
|
|
|
// Rename the old INI file |
|
char newFilePath[MAX_PATH]; |
|
Q_snprintf( newFilePath, sizeof( newFilePath ), "%s.OLD", iniFilePath ); |
|
|
|
rename( iniFilePath, newFilePath ); |
|
|
|
// Notify that we were converted |
|
m_LoadStatus = LOADSTATUS_CONVERTED; |
|
|
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Write out a game configuration file |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CGameConfigManager::SaveConfigs( const char *baseDir ) |
|
{ |
|
if ( !IsLoaded() ) |
|
return false; |
|
|
|
// Build our default directory |
|
if ( baseDir != NULL && baseDir[0] != NULL ) |
|
{ |
|
SetBaseDirectory( baseDir ); |
|
} |
|
|
|
// Make a full path name |
|
char szPath[MAX_PATH]; |
|
Q_strncpy( szPath, GetBaseDirectory(), sizeof(szPath) ); |
|
Q_AppendSlash( szPath, sizeof(szPath) ); |
|
Q_strncat( szPath, GAME_CONFIG_FILENAME, sizeof( szPath ), COPY_ALL_CHARACTERS ); |
|
|
|
CUtlBuffer buffer; |
|
m_pData->RecursiveSaveToFile( buffer, 0 ); |
|
|
|
return SaveUtlBufferToFile( buffer, szPath ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Find the directory our .exe is based out of |
|
//----------------------------------------------------------------------------- |
|
const char *CGameConfigManager::GetBaseDirectory( void ) |
|
{ |
|
return m_szBaseDirectory; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Find the root directory |
|
//----------------------------------------------------------------------------- |
|
const char *CGameConfigManager::GetRootDirectory( void ) |
|
{ |
|
static char path[MAX_PATH] = {0}; |
|
if ( path[0] == 0 ) |
|
{ |
|
Q_strncpy( path, GetBaseDirectory(), sizeof( path ) ); |
|
Q_StripLastDir( path, sizeof( path ) ); // Get rid of the 'bin' directory |
|
Q_StripTrailingSlash( path ); |
|
} |
|
return path; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Returns the game configuation block |
|
//----------------------------------------------------------------------------- |
|
KeyValues *CGameConfigManager::GetGameBlock( void ) |
|
{ |
|
if ( !IsLoaded() ) |
|
return NULL; |
|
|
|
return ( m_pData->FindKey( TOKEN_GAMES, true ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Returns a piece of the game configuation block of the given name |
|
// Input : *keyName - name of the block to return |
|
//----------------------------------------------------------------------------- |
|
KeyValues *CGameConfigManager::GetGameSubBlock( const char *keyName ) |
|
{ |
|
if ( !IsLoaded() ) |
|
return NULL; |
|
|
|
KeyValues *pGameBlock = GetGameBlock(); |
|
if ( pGameBlock == NULL ) |
|
return NULL; |
|
|
|
// Return the data |
|
KeyValues *pSubBlock = pGameBlock->FindKey( keyName ); |
|
|
|
return pSubBlock; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Get the gamecfg.ini file for conversion |
|
//----------------------------------------------------------------------------- |
|
const char *CGameConfigManager::GetIniFilePath( void ) |
|
{ |
|
static char iniFilePath[MAX_PATH] = {0}; |
|
if ( iniFilePath[0] == 0 ) |
|
{ |
|
Q_strncpy( iniFilePath, GetBaseDirectory(), sizeof( iniFilePath ) ); |
|
Q_strncat( iniFilePath, "\\gamecfg.ini", sizeof( iniFilePath ), COPY_ALL_CHARACTERS ); |
|
} |
|
|
|
return iniFilePath; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Deletes the current config and recreates it with default values |
|
//----------------------------------------------------------------------------- |
|
bool CGameConfigManager::ResetConfigs( const char *baseDir /*= NULL*/ ) |
|
{ |
|
// Build our default directory |
|
if ( baseDir != NULL && baseDir[0] != NULL ) |
|
{ |
|
SetBaseDirectory( baseDir ); |
|
} |
|
|
|
// Make a full path name |
|
char szPath[MAX_PATH]; |
|
Q_snprintf( szPath, sizeof( szPath ), "%s\\%s", GetBaseDirectory(), GAME_CONFIG_FILENAME ); |
|
|
|
// Delete the file |
|
if ( unlink( szPath ) ) |
|
return false; |
|
|
|
// Load the file again (causes defaults to be created) |
|
if ( LoadConfigsInternal( baseDir, false ) == false ) |
|
return false; |
|
|
|
// Save it out |
|
return SaveConfigs( baseDir ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CGameConfigManager::SetBaseDirectory( const char *pDirectory ) |
|
{ |
|
// Clear it |
|
if ( pDirectory == NULL || pDirectory[0] == '\0' ) |
|
{ |
|
m_szBaseDirectory[0] = '\0'; |
|
return; |
|
} |
|
|
|
// Copy it |
|
Q_strncpy( m_szBaseDirectory, pDirectory, sizeof( m_szBaseDirectory ) ); |
|
Q_StripTrailingSlash( m_szBaseDirectory ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Create a block of keyvalues containing our default configurations |
|
// Output : A block of keyvalues |
|
//----------------------------------------------------------------------------- |
|
bool CGameConfigManager::GetDefaultGameBlock( KeyValues *pIn ) |
|
{ |
|
CUtlVector<defaultConfigInfo_t> defaultConfigs; |
|
|
|
// Add HL2 games to list |
|
defaultConfigs.AddToTail( HL2DMInfo ); |
|
defaultConfigs.AddToTail( HL2Info ); |
|
defaultConfigs.AddToTail( Episode1Info ); |
|
defaultConfigs.AddToTail( Episode2Info ); |
|
defaultConfigs.AddToTail( PortalInfo ); |
|
defaultConfigs.AddToTail( SourceTestInfo ); |
|
|
|
// Add TF2 games to list |
|
defaultConfigs.AddToTail( TF2Info ); |
|
defaultConfigs.AddToTail( DODInfo ); |
|
defaultConfigs.AddToTail( CStrikeInfo ); |
|
|
|
if ( pIn == NULL ) |
|
return false; |
|
|
|
char szPath[MAX_PATH]; |
|
|
|
// Add all default configs |
|
int nNumConfigs = defaultConfigs.Count(); |
|
for ( int i = 0; i < nNumConfigs; i++ ) |
|
{ |
|
// If it's installed, add it |
|
if ( IsAppSubscribed( defaultConfigs[i].steamAppID ) ) |
|
{ |
|
GetRootGameDirectory( szPath, sizeof( szPath ), GetRootDirectory() ); |
|
AddDefaultConfig( defaultConfigs[i], pIn, GetRootDirectory(), szPath ); |
|
} |
|
} |
|
|
|
return true; |
|
}
|
|
|