Keyvalues fix maybe? (#880)

* move compiled files to their own storage

* clear compiled files on mod reload

* allow functions to specify the sources that they wish to look for files in

* formatting
This commit is contained in:
Jack 2025-12-03 23:06:29 +00:00 committed by GitHub
parent 10e615552e
commit 0ba23677d1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 64 additions and 62 deletions

View file

@ -5,7 +5,9 @@
#include <iostream>
#include <sstream>
bool bReadingOriginalFile = false;
// the currently accepted sources for files
int iFileSourceType = FileSourceType_Any;
std::string sCurrentModPath;
ConVar* Cvar_ns_fs_log_reads;
@ -31,13 +33,14 @@ std::string ReadVPKFile(const char* path)
return fileStream.str();
}
std::string ReadVPKOriginalFile(const char* path)
std::string ReadVPKFile(const char* path, int fileSourceType)
{
// todo: should probably set search path to be g_pModName here also
int oldType = iFileSourceType;
iFileSourceType = fileSourceType;
bReadingOriginalFile = true;
std::string ret = ReadVPKFile(path);
bReadingOriginalFile = false;
iFileSourceType = oldType;
return ret;
}
@ -56,38 +59,53 @@ static void __fastcall h_AddSearchPath(IFileSystem* fileSystem, const char* pPat
}
}
void SetNewCompiledSearchPaths()
{
// push compiled to head
o_pAddSearchPath(g_pFilesystem, fs::absolute(GetCompiledAssetsPath()).string().c_str(), "GAME", PATH_ADD_TO_HEAD);
sCurrentModPath = "";
}
void SetNewModSearchPaths(Mod* mod)
{
// put our new path to the head if we need to read from a different mod path
// in the future we could also determine whether the file we're setting paths for needs a mod dir, or compiled assets
if (mod != nullptr)
if (mod == nullptr)
return;
if ((fs::absolute(mod->m_ModDirectory) / MOD_OVERRIDE_DIR).string().compare(sCurrentModPath))
{
if ((fs::absolute(mod->m_ModDirectory) / MOD_OVERRIDE_DIR).string().compare(sCurrentModPath))
{
o_pAddSearchPath(
g_pFilesystem, (fs::absolute(mod->m_ModDirectory) / MOD_OVERRIDE_DIR).string().c_str(), "GAME", PATH_ADD_TO_HEAD);
sCurrentModPath = (fs::absolute(mod->m_ModDirectory) / MOD_OVERRIDE_DIR).string();
}
o_pAddSearchPath(g_pFilesystem, (fs::absolute(mod->m_ModDirectory) / MOD_OVERRIDE_DIR).string().c_str(), "GAME", PATH_ADD_TO_HEAD);
sCurrentModPath = (fs::absolute(mod->m_ModDirectory) / MOD_OVERRIDE_DIR).string();
}
else // push compiled to head
o_pAddSearchPath(g_pFilesystem, fs::absolute(GetCompiledAssetsPath()).string().c_str(), "GAME", PATH_ADD_TO_HEAD);
}
bool TryReplaceFile(const char* pPath, bool shouldCompile)
{
if (bReadingOriginalFile)
return false;
if (shouldCompile)
g_pModManager->CompileAssetsForFile(pPath);
// idk how efficient the lexically normal check is
// can't just set all /s in path to \, since some paths aren't in writeable memory
auto file = g_pModManager->m_ModFiles.find(g_pModManager->NormaliseModFilePath(fs::path(pPath)));
if (file != g_pModManager->m_ModFiles.end())
std::string normalisedPath = g_pModManager->NormaliseModFilePath(fs::path(pPath));
if (iFileSourceType & FileSourceType_Compiled)
{
SetNewModSearchPaths(file->second.m_pOwningMod);
return true;
// only compile assets if we would accept a compiled asset in the first place
if (shouldCompile)
g_pModManager->CompileAssetsForFile(pPath);
if (g_pModManager->m_CompiledFiles.contains(normalisedPath))
{
SetNewCompiledSearchPaths();
return true;
}
}
if (iFileSourceType & FileSourceType_ModOverride)
{
auto file = g_pModManager->m_ModFiles.find(normalisedPath);
if (file != g_pModManager->m_ModFiles.end())
{
SetNewModSearchPaths(file->second.m_pOwningMod);
return true;
}
}
return false;

View file

@ -11,6 +11,16 @@ enum SearchPathAdd_t
PATH_ADD_TO_TAIL, // Last path searched
};
enum FileSourceType_t : int
{
FileSourceType_Original = 1 << 0,
FileSourceType_ModOverride = 1 << 1,
FileSourceType_Compiled = 1 << 2,
FileSourceType_Modded = FileSourceType_ModOverride | FileSourceType_Compiled,
FileSourceType_Any = FileSourceType_Original | FileSourceType_ModOverride | FileSourceType_Compiled,
};
class CSearchPath
{
public:
@ -50,4 +60,4 @@ public:
extern IFileSystem* g_pFilesystem;
std::string ReadVPKFile(const char* path);
std::string ReadVPKOriginalFile(const char* path);
std::string ReadVPKFile(const char* path, int fileSourceFilter);

View file

@ -14,7 +14,7 @@ void ModManager::BuildKBActionsList()
std::ofstream soCompiledKeys(GetCompiledAssetsPath() / KB_ACT_PATH, std::ios::binary);
// write vanilla file's content to compiled file
soCompiledKeys << ReadVPKOriginalFile(KB_ACT_PATH);
soCompiledKeys << ReadVPKFile(KB_ACT_PATH, FileSourceType_Original);
for (Mod& mod : m_LoadedMods)
{
@ -32,13 +32,5 @@ void ModManager::BuildKBActionsList()
soCompiledKeys.close();
// push to overrides
ModOverrideFile overrideFile;
overrideFile.m_pOwningMod = nullptr;
overrideFile.m_Path = KB_ACT_PATH;
if (m_ModFiles.find(KB_ACT_PATH) == m_ModFiles.end())
m_ModFiles.insert(std::make_pair(KB_ACT_PATH, overrideFile));
else
m_ModFiles[KB_ACT_PATH] = overrideFile;
m_CompiledFiles.insert(KB_ACT_PATH);
}

View file

@ -54,7 +54,7 @@ void ModManager::TryBuildKeyValues(const char* filename)
newKvs += "\"\n";
// load original file, so we can parse out the name of the root obj (e.g. WeaponData for weapons)
std::string originalFile = ReadVPKOriginalFile(filename);
std::string originalFile = ReadVPKFile(filename, FileSourceType_ModOverride + FileSourceType_Original);
if (!originalFile.length())
{
@ -93,12 +93,5 @@ void ModManager::TryBuildKeyValues(const char* filename)
writeStream << newKvs;
writeStream.close();
ModOverrideFile overrideFile;
overrideFile.m_pOwningMod = nullptr;
overrideFile.m_Path = normalisedPath;
if (m_ModFiles.find(normalisedPath) == m_ModFiles.end())
m_ModFiles.insert(std::make_pair(normalisedPath, overrideFile));
else
m_ModFiles[normalisedPath] = overrideFile;
m_CompiledFiles.insert(normalisedPath);
}

View file

@ -15,7 +15,7 @@ void ModManager::BuildPdef()
fs::path MOD_PDEF_PATH = fs::path(GetCompiledAssetsPath() / MOD_PDEF_SUFFIX);
fs::remove(MOD_PDEF_PATH);
std::string pdef = ReadVPKOriginalFile(VPK_PDEF_PATH);
std::string pdef = ReadVPKFile(VPK_PDEF_PATH, FileSourceType_Original);
for (Mod& mod : m_LoadedMods)
{
@ -107,12 +107,5 @@ void ModManager::BuildPdef()
writeStream << pdef;
writeStream.close();
ModOverrideFile overrideFile;
overrideFile.m_pOwningMod = nullptr;
overrideFile.m_Path = VPK_PDEF_PATH;
if (m_ModFiles.find(VPK_PDEF_PATH) == m_ModFiles.end())
m_ModFiles.insert(std::make_pair(VPK_PDEF_PATH, overrideFile));
else
m_ModFiles[VPK_PDEF_PATH] = overrideFile;
m_CompiledFiles.insert(VPK_PDEF_PATH);
}

View file

@ -13,7 +13,7 @@ void ModManager::BuildScriptsRson()
fs::path MOD_SCRIPTS_RSON_PATH = fs::path(GetCompiledAssetsPath() / MOD_SCRIPTS_RSON_SUFFIX);
fs::remove(MOD_SCRIPTS_RSON_PATH);
std::string scriptsRson = ReadVPKOriginalFile(VPK_SCRIPTS_RSON_PATH);
std::string scriptsRson = ReadVPKFile(VPK_SCRIPTS_RSON_PATH, FileSourceType_Original);
scriptsRson += "\n\n// START MODDED SCRIPT CONTENT\n\n"; // newline before we start custom stuff
for (Mod& mod : m_LoadedMods)
@ -51,14 +51,7 @@ void ModManager::BuildScriptsRson()
writeStream << scriptsRson;
writeStream.close();
ModOverrideFile overrideFile;
overrideFile.m_pOwningMod = nullptr;
overrideFile.m_Path = VPK_SCRIPTS_RSON_PATH;
if (m_ModFiles.find(VPK_SCRIPTS_RSON_PATH) == m_ModFiles.end())
m_ModFiles.insert(std::make_pair(VPK_SCRIPTS_RSON_PATH, overrideFile));
else
m_ModFiles[VPK_SCRIPTS_RSON_PATH] = overrideFile;
m_CompiledFiles.insert(VPK_SCRIPTS_RSON_PATH);
// todo: for preventing dupe scripts in scripts.rson, we could actually parse when conditions with the squirrel vm, just need a way to
// get a result out of squirrelmanager.ExecuteCode this would probably be the best way to do this, imo

View file

@ -113,6 +113,7 @@ void ModManager::LoadMods()
// Find all mods from disk
DiscoverMods();
m_CompiledFiles.clear();
fs::remove_all(GetCompiledAssetsPath());
for (Mod& mod : m_LoadedMods)
@ -413,6 +414,7 @@ void ModManager::UnloadMods()
m_DependencyConstants.clear();
m_ModFiles.clear();
m_CompiledFiles.clear();
fs::remove_all(GetCompiledAssetsPath());
g_CustomAudioManager.ClearAudioOverrides();

View file

@ -45,6 +45,7 @@ private:
public:
std::vector<Mod> m_LoadedMods;
std::unordered_map<std::string, ModOverrideFile> m_ModFiles;
std::unordered_set<std::string> m_CompiledFiles;
std::unordered_map<std::string, std::string> m_DependencyConstants;
std::unordered_set<std::string> m_PluginDependencyConstants;