From 3bf9df6b2785fa6d951086978a3e66f49427166a Mon Sep 17 00:00:00 2001 From: FluorescentCIAAfricanAmerican <0934gj3049fk@protonmail.com> Date: Wed, 22 Apr 2020 12:56:21 -0400 Subject: 1 --- engine/DownloadListGenerator.cpp | 453 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 453 insertions(+) create mode 100644 engine/DownloadListGenerator.cpp (limited to 'engine/DownloadListGenerator.cpp') diff --git a/engine/DownloadListGenerator.cpp b/engine/DownloadListGenerator.cpp new file mode 100644 index 0000000..b5bc317 --- /dev/null +++ b/engine/DownloadListGenerator.cpp @@ -0,0 +1,453 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "mathlib/vector.h" +#include "DownloadListGenerator.h" +#include "filesystem.h" +#include "filesystem_engine.h" +#include "sys.h" +#include "cmd.h" +#include "common.h" +#include "quakedef.h" +#include "vengineserver_impl.h" +#include "tier1/strtools.h" +#include "tier0/icommandline.h" +#include "checksum_engine.h" +#include +#include +#include +#include + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +CDownloadListGenerator g_DownloadListGenerator; +CDownloadListGenerator &DownloadListGenerator() +{ + return g_DownloadListGenerator; +} + +ConVar sv_logdownloadlist( "sv_logdownloadlist", IsX360() ? "0" : "1" ); + +extern int GetSvPureMode(); + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CDownloadListGenerator::CDownloadListGenerator() + : m_AlreadyWrittenFileNames( 0, 0, true ) +{ + m_hReslistFile = FILESYSTEM_INVALID_HANDLE; + m_pStringTable = NULL; + m_mapName[0] = 0; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CDownloadListGenerator::SetStringTable( INetworkStringTable *pStringTable ) +{ + if ( IsX360() ) + { + // not supporting + return; + } + + m_pStringTable = pStringTable; + + // reset the duplication list + m_AlreadyWrittenFileNames.RemoveAll(); + + // add in the bsp file to the list, and its node graph and nav mesh + char path[_MAX_PATH]; + Q_snprintf(path, sizeof(path), "maps\\%s.bsp", m_mapName); + OnResourcePrecached(path); + + bool useNodeGraph = true; + KeyValues *modinfo = new KeyValues("ModInfo"); + if ( modinfo->LoadFromFile( g_pFileSystem, "gameinfo.txt" ) ) + { + useNodeGraph = modinfo->GetInt( "nodegraph", 1 ) != 0; + } + modinfo->deleteThis(); + + if ( useNodeGraph ) + { + Q_snprintf(path, sizeof(path), "maps\\graphs\\%s.ain", m_mapName); + OnResourcePrecached(path); + } + + Q_snprintf(path, sizeof(path), "maps\\%s.nav", m_mapName); + OnResourcePrecached(path); + + char resfilename[MAX_OSPATH]; + KeyValues *resfilekeys = new KeyValues( "resourefiles" ); + + Q_snprintf( resfilename, sizeof( resfilename), "maps/%s.res", m_mapName ); + + if ( resfilekeys->LoadFromFile( g_pFileSystem, resfilename, "GAME" ) ) + { + KeyValues *entry = resfilekeys->GetFirstSubKey(); + while ( entry ) + { + OnResourcePrecached( entry->GetName() ); + entry = entry->GetNextKey(); + } + } + resfilekeys->deleteThis(); +} + +//----------------------------------------------------------------------------- +// Purpose: call to mark level load/end +//----------------------------------------------------------------------------- +void CDownloadListGenerator::OnLevelLoadStart(const char *levelName) +{ + if ( IsX360() ) + { + // not supporting + return; + } + + // close the previous level reslist, if any + if (m_hReslistFile != FILESYSTEM_INVALID_HANDLE) + { + g_pFileSystem->Close(m_hReslistFile); + m_hReslistFile = FILESYSTEM_INVALID_HANDLE; + } + + // reset the duplication list + m_AlreadyWrittenFileNames.RemoveAll(); + + if ( sv_logdownloadlist.GetBool() ) + { + // open the new level reslist + char path[MAX_OSPATH]; + g_pFileSystem->CreateDirHierarchy( "DownloadLists", "MOD" ); + Q_snprintf(path, sizeof(path), "DownloadLists/%s.lst", levelName); + m_hReslistFile = g_pFileSystem->Open(path, "wt", "GAME"); + } + + // add a slash to the end of com_gamedir, so we can only deal with files for this mod + Q_snprintf( m_gameDir, sizeof(m_gameDir), "%s/", com_gamedir ); + Q_FixSlashes( m_gameDir ); + + // save off the map name + Q_snprintf( m_mapName, sizeof( m_mapName ), "%s", levelName ); +} + +//----------------------------------------------------------------------------- +// Purpose: call to mark level load/end +//----------------------------------------------------------------------------- +void CDownloadListGenerator::OnLevelLoadEnd() +{ + if ( IsX360() ) + { + // not supporting + return; + } + + if ( m_hReslistFile != FILESYSTEM_INVALID_HANDLE ) + { + g_pFileSystem->Close(m_hReslistFile); + m_hReslistFile = FILESYSTEM_INVALID_HANDLE; + } + m_pStringTable = NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: logs and handles mdl files being precaches +//----------------------------------------------------------------------------- +void CDownloadListGenerator::OnModelPrecached(const char *relativePathFileName) +{ + if ( IsX360() ) + { + // not supporting + return; + } + + if (Q_strstr(relativePathFileName, ".vmt")) + { + // it's a materials file, make sure that it starts in the materials directory, and we get the .vtf + char file[_MAX_PATH]; + + if (!Q_strnicmp(relativePathFileName, "materials", strlen("materials"))) + { + Q_strncpy(file, relativePathFileName, sizeof(file)); + } + else + { + // prepend the materials directory + Q_snprintf(file, sizeof(file), "materials\\%s", relativePathFileName); + } + + OnResourcePrecached(file); + + // get the matching vtf file + char *ext = Q_strstr(file, ".vmt"); + if (ext) + { + Q_strncpy(ext, ".vtf", 5); + OnResourcePrecached(file); + } + } + else + { + OnResourcePrecached(relativePathFileName); + } +} + +//----------------------------------------------------------------------------- +// Purpose: logs sound file access +//----------------------------------------------------------------------------- +void CDownloadListGenerator::OnSoundPrecached(const char *relativePathFileName) +{ + if ( IsX360() ) + { + // not supporting + return; + } + + // skip any special characters + if (!V_isalnum(relativePathFileName[0])) + { + ++relativePathFileName; + } + + // prepend the sound/ directory if necessary + char file[_MAX_PATH]; + if (!Q_strnicmp(relativePathFileName, "sound", strlen("sound"))) + { + Q_strncpy(file, relativePathFileName, sizeof(file)); + } + else + { + // prepend the materials directory + Q_snprintf(file, sizeof(file), "sound\\%s", relativePathFileName); + } + + OnResourcePrecached(file); +} + +//----------------------------------------------------------------------------- +// Purpose: logs the precache as a file access +//----------------------------------------------------------------------------- +void CDownloadListGenerator::OnResourcePrecached(const char *relativePathFileName) +{ + if ( IsX360() ) + { + // not supporting + return; + } + + // ignore empty string + if (relativePathFileName[0] == 0) + { + return; + } + + // ignore files that start with '*' since they signify special models + if (relativePathFileName[0] == '*') + { + return; + } + + char fullPath[_MAX_PATH]; + if (g_pFileSystem->GetLocalPath(relativePathFileName, fullPath, sizeof(fullPath))) + { + OnResourcePrecachedFullPath( fullPath, relativePathFileName); + } +} + +//----------------------------------------------------------------------------- +// Purpose: marks a precached file as needing a specific CRC on the client +//----------------------------------------------------------------------------- +void CDownloadListGenerator::ForceSimpleMaterial( const char *relativePathFileName ) +{ + if ( IsX360() ) + { + // not supporting + return; + } + + if ( !m_pStringTable ) + return; + + if ( !Q_stristr(relativePathFileName, ".vmt") && !Q_stristr(relativePathFileName, ".vtf")) + { + DevMsg( "Tried to enforce simple material on %s\n", relativePathFileName ); + return; + } + + // it's a materials file, make sure that it starts in the materials directory, and we get the .vtf + char szFixedFilename[_MAX_PATH]; + if (!Q_strnicmp(relativePathFileName, "materials", strlen("materials"))) + { + V_strcpy_safe( szFixedFilename, relativePathFileName ); + } + else + { + // prepend the materials directory + V_sprintf_safe( szFixedFilename, "materials\\%s", relativePathFileName ); + } + V_FixSlashes( szFixedFilename ); + if ( !g_pFullFileSystem->FileExists( szFixedFilename, "game" ) ) + { + DevMsg( "Cannot force simple material on %s; file not found\n", szFixedFilename ); + return; + } + + ExactFileUserData userData; + userData.consistencyType = CONSISTENCY_SIMPLE_MATERIAL; + userData.crc = 0; + + // Only set consistency data if pure, otherwise just create entry in download list + if ( GetSvPureMode() < 0 ) + { + m_pStringTable->AddString( true, szFixedFilename ); + } + else + { + int index = m_pStringTable->FindStringIndex( szFixedFilename ); + if ( index != INVALID_STRING_INDEX ) + { + m_pStringTable->SetStringUserData( index, sizeof( ExactFileUserData ), &userData ); + } + else + { + m_pStringTable->AddString( true, szFixedFilename, sizeof( ExactFileUserData ), &userData ); + } + } +} + + +//----------------------------------------------------------------------------- +// Purpose: marks a precached model as having a maximum size on the client +//----------------------------------------------------------------------------- +void CDownloadListGenerator::ForceModelBounds( const char *relativePathFileName, const Vector &mins, const Vector &maxs ) +{ + if ( IsX360() ) + { + // not supporting + return; + } + + if ( !m_pStringTable ) + return; + + if ( !relativePathFileName ) + relativePathFileName = ""; + + if (!Q_stristr(relativePathFileName, ".mdl")) + { + DevMsg( "Warning - trying to enforce model bounds on %s\n", relativePathFileName ); + return; + } + + char relativeFileName[_MAX_PATH]; + Q_strncpy( relativeFileName, relativePathFileName, sizeof( relativeFileName ) ); + Q_FixSlashes( relativeFileName ); + + // Only set consistency data if pure, otherwise just create entry in download list + if ( GetSvPureMode() < 0 ) + { + m_pStringTable->AddString( true, relativePathFileName ); + } + else + { + ModelBoundsUserData userData; + userData.consistencyType = CONSISTENCY_BOUNDS; + userData.mins = mins; + userData.maxs = maxs; + + int index = m_pStringTable->FindStringIndex( relativeFileName ); + if ( index != INVALID_STRING_INDEX ) + { + m_pStringTable->SetStringUserData( index, sizeof( ModelBoundsUserData ), &userData ); + } + else + { + m_pStringTable->AddString( true, relativeFileName, sizeof( ModelBoundsUserData ), &userData ); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Logs out file access to a file +//----------------------------------------------------------------------------- +void CDownloadListGenerator::OnResourcePrecachedFullPath( char *fullPathFileName, const char *relativeFileName ) +{ + if ( IsX360() ) + { + // not supporting + return; + } + + Q_FixSlashes( fullPathFileName ); + + if ( !g_pFileSystem->FileExists( fullPathFileName ) ) + { + return; // don't allow files for download the server doesn't have + } + + if ( Q_strncasecmp( m_gameDir, fullPathFileName, Q_strlen( m_gameDir ) ) ) + { + return; // the game dir must be part of the full name + } + + // make sure the filename hasn't already been written + UtlSymId_t filename = m_AlreadyWrittenFileNames.Find( fullPathFileName ); + if ( filename != UTL_INVAL_SYMBOL ) + { + return; + } + + // record in list, so we don't write it again + m_AlreadyWrittenFileNames.AddString( fullPathFileName ); + + // add extras for mdl's + if (Q_strstr(relativeFileName, ".mdl")) + { + // it's a model, get it's other files as well + char file[_MAX_PATH]; + Q_strncpy(file, relativeFileName, sizeof(file) - 10); + char *ext = Q_strstr(file, ".mdl"); + + Q_strncpy(ext, ".vvd", 10); + OnResourcePrecached(file); + + Q_strncpy(ext, ".ani", 10); + OnResourcePrecached(file); + + Q_strncpy(ext, ".dx80.vtx", 10); + OnResourcePrecached(file); + + Q_strncpy(ext, ".dx90.vtx", 10); + OnResourcePrecached(file); + + Q_strncpy(ext, ".sw.vtx", 10); + OnResourcePrecached(file); + + Q_strncpy(ext, ".phy", 10); + OnResourcePrecached(file); + + Q_strncpy(ext, ".jpg", 10); + OnResourcePrecached(file); + } + + FileHandle_t handle = m_hReslistFile; + if ( handle != FILESYSTEM_INVALID_HANDLE ) + { + g_pFileSystem->Write("\"", 1, handle); + g_pFileSystem->Write( relativeFileName, Q_strlen(relativeFileName), handle ); + g_pFileSystem->Write("\"\n", 2, handle); + } + if ( m_pStringTable ) + { + m_pStringTable->AddString( true, relativeFileName ); + } +} + + + -- cgit v1.2.3