Mounting multiple games: Difference between revisions
(not just 3 or more gcfs; tip on hard-coded mounting) |
TomEdwards (talk | contribs) (simplified code, avoiding weird errors in console but changing the gameinfo.txt format required) |
||
Line 1: | Line 1: | ||
{{toc-right}} | |||
This code extends the Orange Box's [[AdditionalContentId]] system to support '''mounting of multiple [[GCF|Game Cache Files]] via the [[gameinfo.txt]]'''. It can be used with the Ep1 codebase too. | This code extends the Orange Box's [[AdditionalContentId]] system to support '''mounting of multiple [[GCF|Game Cache Files]] via the [[gameinfo.txt]]'''. It can be used with the Ep1 codebase too. | ||
{{warning|Your mod will run regardless of whether or not the user owns the game that you mount content for. If the game isn't owned the content will not be mounted, and error signs will appear everywhere instead!}} | {{warning|Your mod will run regardless of whether or not the user owns the game that you mount content for. If the game isn't owned the content will not be mounted, and error signs will appear everywhere instead!}} | ||
If the content you want to mount is required in order to play your mod properly, you | If the content you want to mount is required in order to play your mod properly, you may want to hard-code the ID instead of relying it to be in the [[gameinfo.txt]]. Remember when doing this that the int you pass to <code>filesystem->MountSteamContent()</code> must be negative! | ||
= | {{note|1=The code below is version 2, and has ditched [http://developer.valvesoftware.com/w/index.php?title=Mounting_multiple_games&oldid=131419 the previous subkey approach]. It is not compatible with the <code>AdditionalContentId { 220,380 }</code> gameinfo.txt scheme.}} | ||
== Client == | |||
'''Search cdll_client_init.cpp for the <code>MountAdditionalContent()</code> function''', and replace it with the code below. | |||
<source lang="cpp">static void MountAdditionalContent() | If you don't already <code>MountAdditionalContent()</code> have, just add this function above <code>CHLClient::Init</code>, then call it right before <code>if ( CommandLine()->FindParm( "-textmode" ) )</code>. | ||
<source lang="cpp"> | |||
static void MountAdditionalContent() | |||
{ | { | ||
KeyValues *pMainFile, * | KeyValues *pMainFile, *pFileSystemInfo; | ||
pMainFile = new KeyValues( "gameinfo.txt" ); | pMainFile = new KeyValues( "gameinfo.txt" ); | ||
if ( pMainFile->LoadFromFile( filesystem, VarArgs("%s/gameinfo.txt", engine->GetGameDirectory()), "MOD" ) ) | if ( pMainFile->LoadFromFile( filesystem, VarArgs("%s/gameinfo.txt", engine->GetGameDirectory()), "MOD" ) ) | ||
{ | { | ||
pFileSystemInfo = pMainFile->FindKey( "FileSystem" ); | |||
if ( | if (pFileSystemInfo) | ||
for ( KeyValues *pKey = pFileSystemInfo->GetFirstSubKey(); pKey; pKey = pKey->GetNextKey() ) | |||
{ | { | ||
if ( strcmp(pKey->GetName(),"AdditionalContentId") == 0 ) | |||
{ | { | ||
int appid = abs(pKey->GetInt()); | |||
if ( | if (appid) | ||
if( filesystem->MountSteamContent(-appid) != FILESYSTEM_MOUNT_OK ) | |||
Warning("Unable to mount extra content with appId: %i\n", appid); | |||
} | } | ||
} | } | ||
} | } | ||
pMainFile->deleteThis(); | pMainFile->deleteThis(); | ||
}</source> | } | ||
</source> | |||
== Server == | |||
'''Search gameinterface.cpp for the <code>MountAdditionalContent()</code> function.''' Replace it with this code. | |||
If you don't have it, just add it right above <code>CServerGameDLL::DLLInit</code> and call before the <code>gpGlobals = pGlobals;</code> line in that func. | |||
<source lang="cpp">static void MountAdditionalContent() | <source lang="cpp"> | ||
static void MountAdditionalContent() | |||
{ | { | ||
KeyValues *pMainFile, * | KeyValues *pMainFile, *pFileSystemInfo; | ||
engine->GetGameDir( gamePath, | char gamePath[MAX_PATH]; | ||
engine->GetGameDir( gamePath, MAX_PATH ); | |||
Q_StripTrailingSlash( gamePath ); | Q_StripTrailingSlash( gamePath ); | ||
pMainFile = new KeyValues( "gameinfo.txt" ); | pMainFile = new KeyValues( "gameinfo.txt" ); | ||
#ifdef _LINUX | #ifdef _LINUX | ||
//On linux because of case sensitivity we need to check for both. | |||
if ( ! | pMainFile->LoadFromFile( filesystem, UTIL_VarArgs("%s/GameInfo.txt", gamePath), "MOD" ); | ||
if (!pMainFile) | |||
#endif | #endif | ||
pMainFile->LoadFromFile( filesystem, UTIL_VarArgs("%s/gameinfo.txt", gamePath), "MOD" ); | |||
if ( | |||
if (pMainFile) | |||
{ | { | ||
pFileSystemInfo = pMainFile->FindKey( "FileSystem" ); | |||
if ( | if (pFileSystemInfo) | ||
for ( KeyValues *pKey = pFileSystemInfo->GetFirstSubKey(); pKey; pKey = pKey->GetNextKey() ) | |||
{ | { | ||
if ( strcmp(pKey->GetName(),"AdditionalContentId") == 0 ) | |||
{ | { | ||
int appid = abs(pKey->GetInt()); | |||
if ( | if (appid) | ||
if( filesystem->MountSteamContent(-appid) != FILESYSTEM_MOUNT_OK ) | |||
Warning("Unable to mount extra content with appId: %i\n", appid); | |||
} | } | ||
} | } | ||
} | |||
} | |||
pMainFile->deleteThis(); | pMainFile->deleteThis(); | ||
}</source> | } | ||
</source> | |||
== Implementing in gameinfo.txt == | == Implementing in gameinfo.txt == | ||
Now you can mount content by adding this after the ToolsAppId: | Now you can mount content by adding something like this after the ToolsAppId: | ||
AdditionalContentId 220 //HL2 | |||
AdditionalContentId 240 //CS Source | |||
AdditionalContentId 280 //HL Source | |||
AdditionalContentId 320 //HL2 Deatmatch | |||
AdditionalContentId 340 //HL2 Lost Coast | |||
AdditionalContentId 360 //HL Deathmatch: Source | |||
AdditionalContentId 380 //Ep1 | |||
AdditionalContentId 400 //Portal | |||
AdditionalContentId 420 //Ep2 | |||
AdditionalContentId 440 //TF2 | |||
AdditionalContentId 500 // L4D - has content incompatibilities! | |||
AdditionalContentId 550 // L4D2 - as above! | |||
Don't forget to add the | Don't forget to add the relevant [[Gameinfo.txt#SearchPaths|SearchPaths]] too. | ||
== Bugs == | == Bugs == | ||
Really big numbers will crash the game with an Error-Dialog by Valve. You could check if the value is within a certain range to stop this from happening, but I think the user will get by himself that this value cannot be mounted. | Really big numbers will crash the game with an Error-Dialog by Valve. You could check if the value is within a certain range to stop this from happening, but I think the user will get by himself that this value cannot be mounted. | ||
{{confirm|filesystem->MountSteamContent returns FILESYSTEM_MOUNT_OK, even if the content is not available. There's nothing you can do about it, apart from poking some guy from Valvesoftware.}} | {{confirm|filesystem->MountSteamContent returns FILESYSTEM_MOUNT_OK, even if the content is not available. There's nothing you can do about it, apart from poking some guy from Valvesoftware.}} | ||
Line 210: | Line 110: | ||
* [[IFileSystem]] | * [[IFileSystem]] | ||
* [[ | * [[Gameinfo.txt]] | ||
* [[ | * [[Steam Application IDs]] | ||
[[Category:Programming]] | [[Category:Programming]] | ||
[[Category:Tutorials]] | [[Category:Tutorials]] |
Revision as of 15:05, 6 November 2010
This code extends the Orange Box's AdditionalContentId system to support mounting of multiple Game Cache Files via the gameinfo.txt. It can be used with the Ep1 codebase too.

If the content you want to mount is required in order to play your mod properly, you may want to hard-code the ID instead of relying it to be in the gameinfo.txt. Remember when doing this that the int you pass to filesystem->MountSteamContent()
must be negative!

AdditionalContentId { 220,380 }
gameinfo.txt scheme.Client
Search cdll_client_init.cpp for the MountAdditionalContent()
function, and replace it with the code below.
If you don't already MountAdditionalContent()
have, just add this function above CHLClient::Init
, then call it right before if ( CommandLine()->FindParm( "-textmode" ) )
.
static void MountAdditionalContent()
{
KeyValues *pMainFile, *pFileSystemInfo;
pMainFile = new KeyValues( "gameinfo.txt" );
if ( pMainFile->LoadFromFile( filesystem, VarArgs("%s/gameinfo.txt", engine->GetGameDirectory()), "MOD" ) )
{
pFileSystemInfo = pMainFile->FindKey( "FileSystem" );
if (pFileSystemInfo)
for ( KeyValues *pKey = pFileSystemInfo->GetFirstSubKey(); pKey; pKey = pKey->GetNextKey() )
{
if ( strcmp(pKey->GetName(),"AdditionalContentId") == 0 )
{
int appid = abs(pKey->GetInt());
if (appid)
if( filesystem->MountSteamContent(-appid) != FILESYSTEM_MOUNT_OK )
Warning("Unable to mount extra content with appId: %i\n", appid);
}
}
}
pMainFile->deleteThis();
}
Server
Search gameinterface.cpp for the MountAdditionalContent()
function. Replace it with this code.
If you don't have it, just add it right above CServerGameDLL::DLLInit
and call before the gpGlobals = pGlobals;
line in that func.
static void MountAdditionalContent()
{
KeyValues *pMainFile, *pFileSystemInfo;
char gamePath[MAX_PATH];
engine->GetGameDir( gamePath, MAX_PATH );
Q_StripTrailingSlash( gamePath );
pMainFile = new KeyValues( "gameinfo.txt" );
#ifdef _LINUX
//On linux because of case sensitivity we need to check for both.
pMainFile->LoadFromFile( filesystem, UTIL_VarArgs("%s/GameInfo.txt", gamePath), "MOD" );
if (!pMainFile)
#endif
pMainFile->LoadFromFile( filesystem, UTIL_VarArgs("%s/gameinfo.txt", gamePath), "MOD" );
if (pMainFile)
{
pFileSystemInfo = pMainFile->FindKey( "FileSystem" );
if (pFileSystemInfo)
for ( KeyValues *pKey = pFileSystemInfo->GetFirstSubKey(); pKey; pKey = pKey->GetNextKey() )
{
if ( strcmp(pKey->GetName(),"AdditionalContentId") == 0 )
{
int appid = abs(pKey->GetInt());
if (appid)
if( filesystem->MountSteamContent(-appid) != FILESYSTEM_MOUNT_OK )
Warning("Unable to mount extra content with appId: %i\n", appid);
}
}
}
pMainFile->deleteThis();
}
Implementing in gameinfo.txt
Now you can mount content by adding something like this after the ToolsAppId:
AdditionalContentId 220 //HL2 AdditionalContentId 240 //CS Source AdditionalContentId 280 //HL Source AdditionalContentId 320 //HL2 Deatmatch AdditionalContentId 340 //HL2 Lost Coast AdditionalContentId 360 //HL Deathmatch: Source AdditionalContentId 380 //Ep1 AdditionalContentId 400 //Portal AdditionalContentId 420 //Ep2 AdditionalContentId 440 //TF2 AdditionalContentId 500 // L4D - has content incompatibilities! AdditionalContentId 550 // L4D2 - as above!
Don't forget to add the relevant SearchPaths too.
Bugs
Really big numbers will crash the game with an Error-Dialog by Valve. You could check if the value is within a certain range to stop this from happening, but I think the user will get by himself that this value cannot be mounted.
