mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
* All libraries have been isolated from each other, and build into separate artifacts. * Project has been restructured to support isolating libraries. * CCrashHandler now calls a callback on crash (setup from core/dllmain.cpp, this can be setup in any way for any project. This callback is getting called when the apllication crashes. Useful for flushing buffers before closing handles to logging files for example). * Tier0 'CoreMsgV' function now calls a callback sink, which could be set by the user (currently setup to the SDK's internal logger in core/dllmain.cpp). TODO: * Add a batch file to autogenerate all projects. * Add support for dedicated server. * Add support for client dll. Bugs: * Game crashes on the title screen after the UI script compiler has finished (root cause unknown). * Curl error messages are getting logged twice for the dedicated server due to the removal of all "DEDICATED" preprocessor directives to support isolating projects. This has to be fixed properly!
257 lines
8.1 KiB
C++
257 lines
8.1 KiB
C++
//===== Copyright © 2005-2005, Valve Corporation, All rights reserved. ======//
|
|
//
|
|
// Purpose: Helper methods + classes for file access.
|
|
//
|
|
//===========================================================================//
|
|
#include "tier1/strtools.h"
|
|
#include "tier1/utlbuffer.h"
|
|
#include "tier2/fileutils.h"
|
|
#include "filesystem/filesystem.h"
|
|
|
|
// NOTE: This has to be the last file included!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Builds a directory which is a subdirectory of the current mod.
|
|
// Input : *pSubDir -
|
|
// *pBuf -
|
|
// nBufLen -
|
|
//-----------------------------------------------------------------------------
|
|
void GetModSubdirectory(const char* pSubDir, char* pBuf, size_t nBufLen)
|
|
{
|
|
// Compute starting directory.
|
|
Assert(FileSystem()->GetSearchPath( "MOD", false, NULL, 0) < nBufLen );
|
|
FileSystem()->GetSearchPath( "MOD", false, pBuf, int( nBufLen ) );
|
|
char* pSemi = strchr( pBuf, ';' );
|
|
if ( pSemi )
|
|
{
|
|
*pSemi = 0;
|
|
}
|
|
|
|
V_StripTrailingSlash( pBuf );
|
|
size_t currentLength = strlen( pBuf );
|
|
|
|
if ( pSubDir )
|
|
{
|
|
Q_strncat( pBuf, "\\", nBufLen-currentLength );
|
|
currentLength += 1; // Account for the added '\\' character.
|
|
Q_strncat( pBuf, pSubDir, nBufLen-currentLength );
|
|
}
|
|
|
|
V_FixSlashes( pBuf );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Builds a directory which is a subdirectory of the current mod's *content*.
|
|
// Input : *pSubDir -
|
|
// *pBuf -
|
|
// nBufLen -
|
|
//-----------------------------------------------------------------------------
|
|
void GetModContentSubdirectory( const char *pSubDir, char *pBuf, size_t nBufLen )
|
|
{
|
|
char pTemp[ MAX_PATH ];
|
|
GetModSubdirectory( pSubDir, pTemp, sizeof(pTemp) );
|
|
ComputeModContentFilename( pTemp, pBuf, nBufLen );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Generates a filename under the 'game' subdirectory given a subdirectory of 'content'.
|
|
// Input : *pContentFileName -
|
|
// *pBuf -
|
|
// nBufLen -
|
|
//-----------------------------------------------------------------------------
|
|
void ComputeModFilename( const char *pContentFileName, char *pBuf, size_t nBufLen )
|
|
{
|
|
char pRelativePath[ MAX_PATH ];
|
|
if ( !FileSystem()->FullPathToRelativePath(pContentFileName, pRelativePath, sizeof(pRelativePath)))
|
|
{
|
|
Q_strncpy( pBuf, pContentFileName, nBufLen );
|
|
return;
|
|
}
|
|
|
|
char pGameRoot[ MAX_PATH ];
|
|
FileSystem()->GetSearchPath("GAME", false, pGameRoot, sizeof(pGameRoot));
|
|
char *pSemi = strchr( pGameRoot, ';' );
|
|
if ( pSemi )
|
|
{
|
|
*pSemi = 0;
|
|
}
|
|
|
|
V_ComposeFileName( pGameRoot, pRelativePath, pBuf, nBufLen );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Generates a filename under the 'content' subdirectory given a subdirectory of 'game'.
|
|
// Input : *pGameFileName -
|
|
// *pBuf -
|
|
// nBufLen -
|
|
//-----------------------------------------------------------------------------
|
|
void ComputeModContentFilename( const char *pGameFileName, char *pBuf, size_t nBufLen )
|
|
{
|
|
char pRelativePath[ MAX_PATH ];
|
|
if ( !FileSystem()->FullPathToRelativePath( pGameFileName, pRelativePath, sizeof(pRelativePath) ) )
|
|
{
|
|
Q_strncpy( pBuf, pGameFileName, nBufLen );
|
|
return;
|
|
}
|
|
|
|
char pContentRoot[ MAX_PATH ];
|
|
FileSystem()->GetSearchPath( "CONTENT", false, pContentRoot, sizeof(pContentRoot) );
|
|
char *pSemi = strchr( pContentRoot, ';' );
|
|
if ( pSemi )
|
|
{
|
|
*pSemi = 0;
|
|
}
|
|
|
|
V_ComposeFileName( pContentRoot, pRelativePath, pBuf, nBufLen );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Search start directory, recurse into sub directories collecting all files matching the target name.
|
|
// Input : *outFileList -
|
|
// *szStartDirectory -
|
|
// *szTargetFileName -
|
|
// *pathID -
|
|
//-----------------------------------------------------------------------------
|
|
void RecursiveFindFilesMatchingName( CUtlVector< CUtlString > *pOutFileList, const char* szStartDirectory, const char* szTargetFileName, const char *pPathID )
|
|
{
|
|
char searchString[MAX_PATH];
|
|
Q_snprintf( searchString, sizeof( searchString ), "%s/*.*", szStartDirectory );
|
|
V_FixSlashes( searchString );
|
|
|
|
FileFindHandle_t handle;
|
|
const char* curFile = FileSystem()->FindFirstEx( searchString, pPathID, &handle );
|
|
while ( curFile )
|
|
{
|
|
if ( *curFile != '.' && FileSystem()->FindIsDirectory( handle ) )
|
|
{
|
|
char newSearchPath[MAX_PATH];
|
|
Q_snprintf( newSearchPath, sizeof( newSearchPath ), "%s/%s", szStartDirectory, curFile );
|
|
RecursiveFindFilesMatchingName( pOutFileList, newSearchPath, szTargetFileName, pPathID );
|
|
}
|
|
else if ( V_StringMatchesPattern( curFile, szTargetFileName ) )
|
|
{
|
|
CUtlString outFile;
|
|
outFile.Format( "%s/%s", szStartDirectory, curFile );
|
|
V_FixSlashes( outFile.Get() );
|
|
pOutFileList->AddToTail( outFile );
|
|
}
|
|
|
|
curFile = FileSystem()->FindNext( handle );
|
|
}
|
|
FileSystem()->FindClose( handle );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Builds a list of all files under a directory with a particular extension.
|
|
// Input : &list -
|
|
// *pDirectory -
|
|
// *pPathID -
|
|
// *pExtension -
|
|
//-----------------------------------------------------------------------------
|
|
void AddFilesToList( CUtlVector< CUtlString > &list, const char *pDirectory, const char *pPathID, const char *pExtension )
|
|
{
|
|
char pSearchString[MAX_PATH];
|
|
Q_snprintf( pSearchString, MAX_PATH, "%s\\*", pDirectory );
|
|
|
|
bool bIsAbsolute = V_IsAbsolutePath( pDirectory );
|
|
|
|
// get the list of files.
|
|
FileFindHandle_t hFind;
|
|
const char *pFoundFile = FileSystem()->FindFirstEx( pSearchString, pPathID, &hFind );
|
|
|
|
// add all the items.
|
|
CUtlVector< CUtlString > subDirs;
|
|
for ( ; pFoundFile; pFoundFile = FileSystem()->FindNext( hFind ) )
|
|
{
|
|
char pChildPath[MAX_PATH];
|
|
Q_snprintf( pChildPath, MAX_PATH, "%s\\%s", pDirectory, pFoundFile );
|
|
|
|
if ( FileSystem()->FindIsDirectory( hFind ) )
|
|
{
|
|
if ( Q_strnicmp( pFoundFile, ".", 2 ) && Q_strnicmp( pFoundFile, "..", 3 ) )
|
|
{
|
|
subDirs.AddToTail( pChildPath );
|
|
}
|
|
continue;
|
|
}
|
|
|
|
// Check the extension matches.
|
|
if ( pExtension && Q_stricmp( V_GetFileExtension( pFoundFile ), pExtension ) )
|
|
continue;
|
|
|
|
char pFullPathBuf[MAX_PATH];
|
|
char *pFullPath = pFullPathBuf;
|
|
if ( !bIsAbsolute )
|
|
{
|
|
FileSystem()->RelativePathToFullPath( pChildPath, pPathID, pFullPathBuf, sizeof(pFullPathBuf) );
|
|
}
|
|
else
|
|
{
|
|
pFullPath = pChildPath;
|
|
}
|
|
|
|
V_strlower( pFullPath );
|
|
V_FixSlashes( pFullPath );
|
|
list.AddToTail( pFullPath );
|
|
}
|
|
|
|
FileSystem()->FindClose(hFind);
|
|
|
|
int nCount = subDirs.Count();
|
|
for ( int i = 0; i < nCount; ++i )
|
|
{
|
|
AddFilesToList( list, subDirs[i], pPathID, pExtension );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Returns the search path as a list of paths.
|
|
// Input : &path -
|
|
// *pPathID -
|
|
//-----------------------------------------------------------------------------
|
|
void GetSearchPath(CUtlVector< CUtlString >& path, const char* pPathID)
|
|
{
|
|
int nMaxLen = FileSystem()->GetSearchPath(pPathID, false, NULL, 0);
|
|
char* pBuf = (char*)stackalloc(nMaxLen);
|
|
FileSystem()->GetSearchPath(pPathID, false, pBuf, nMaxLen);
|
|
|
|
char* pSemi;
|
|
while (NULL != (pSemi = strchr(pBuf, ';')))
|
|
{
|
|
*pSemi = 0;
|
|
path.AddToTail(pBuf);
|
|
pBuf = pSemi + 1;
|
|
}
|
|
path.AddToTail(pBuf);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Given file name in the current dir generate a full path to it.
|
|
// Input : *pFileName -
|
|
// *pPathID -
|
|
// *pBuf -
|
|
// nBufLen -
|
|
// Output: True on success, false otherwise.
|
|
//-----------------------------------------------------------------------------
|
|
bool GenerateFullPath(const char* pFileName, char const* pPathID, char* pBuf, size_t nBufLen)
|
|
{
|
|
if (V_IsAbsolutePath(pFileName))
|
|
{
|
|
V_strncpy(pBuf, pFileName, nBufLen);
|
|
return true;
|
|
}
|
|
|
|
const char* pFullPath = FileSystem()->RelativePathToFullPath(pFileName, pPathID, pBuf, int(nBufLen));
|
|
if (pFullPath && V_IsAbsolutePath(pFullPath))
|
|
return true;
|
|
|
|
char pDir[MAX_PATH];
|
|
if (!FileSystem()->GetCurrentDirectory(pDir, sizeof(pDir)))
|
|
return false;
|
|
|
|
V_ComposeFileName(pDir, pFileName, pBuf, nBufLen);
|
|
V_RemoveDotSlashes(pBuf);
|
|
return true;
|
|
}
|