aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <for.oliver.kirkham@gmail.com>2023-02-11 03:08:43 +0000
committerBobTheBob <for.oliver.kirkham@gmail.com>2023-02-22 22:18:56 +0000
commit07e386b12cb1a92c99cd5e3034cb4f94f28fb3eb (patch)
treee1c05c9bb83b8860daa2dd18f96a76bae6c5bff9
parente1c781f317e1d798eff5d34d87f9b5ffa3e538f0 (diff)
downloadNorthstarLauncher-07e386b12cb1a92c99cd5e3034cb4f94f28fb3eb.tar.gz
NorthstarLauncher-07e386b12cb1a92c99cd5e3034cb4f94f28fb3eb.zip
commit for merge
-rw-r--r--NorthstarDLL/NorthstarDLL.vcxproj7
-rw-r--r--NorthstarDLL/NorthstarDLL.vcxproj.filters9
-rw-r--r--NorthstarDLL/client/audio.h2
-rw-r--r--NorthstarDLL/client/clientvideooverrides.cpp10
-rw-r--r--NorthstarDLL/client/modlocalisation.cpp4
-rw-r--r--NorthstarDLL/core/filesystem/filesystem.cpp6
-rw-r--r--NorthstarDLL/core/filesystem/rpakfilesystem.cpp21
-rw-r--r--NorthstarDLL/logging/crashhandler.cpp4
-rw-r--r--NorthstarDLL/mods/compiled/kb_act.cpp8
-rw-r--r--NorthstarDLL/mods/compiled/modkeyvalues.cpp16
-rw-r--r--NorthstarDLL/mods/compiled/modpdef.cpp118
-rw-r--r--NorthstarDLL/mods/compiled/modscriptsrson.cpp8
-rw-r--r--NorthstarDLL/mods/modmanager.cpp132
-rw-r--r--NorthstarDLL/mods/modmanager.h35
-rw-r--r--NorthstarDLL/pch.h2
-rw-r--r--NorthstarDLL/scripts/client/scriptmodmenu.cpp18
-rw-r--r--NorthstarDLL/squirrel/squirrel.cpp8
-rw-r--r--NorthstarDLL/squirrel/squirrel.h8
-rw-r--r--NorthstarDLL/util/printmaps.cpp2
19 files changed, 154 insertions, 264 deletions
diff --git a/NorthstarDLL/NorthstarDLL.vcxproj b/NorthstarDLL/NorthstarDLL.vcxproj
index bb28d575..9bd3d6fa 100644
--- a/NorthstarDLL/NorthstarDLL.vcxproj
+++ b/NorthstarDLL/NorthstarDLL.vcxproj
@@ -449,7 +449,7 @@
<ClInclude Include="squirrel\squirreldatatypes.h" />
<ClInclude Include="util\utils.h" />
<ClInclude Include="util\version.h" />
- <ClInclude Include="util\wininfo.h" />
+ <ClInclude Include="util\wininfo.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\include\spdlog\fmt\bundled\LICENSE.rst" />
@@ -498,7 +498,6 @@
<ClCompile Include="masterserver\masterserver.cpp" />
<ClCompile Include="mods\compiled\kb_act.cpp" />
<ClCompile Include="mods\compiled\modkeyvalues.cpp" />
- <ClCompile Include="mods\compiled\modpdef.cpp" />
<ClCompile Include="mods\compiled\modscriptsrson.cpp" />
<ClCompile Include="mods\modmanager.cpp" />
<ClCompile Include="pch.cpp">
@@ -540,7 +539,7 @@
<ClCompile Include="util\printmaps.cpp" />
<ClCompile Include="util\utils.cpp" />
<ClCompile Include="util\version.cpp" />
- <ClCompile Include="util\wininfo.cpp" />
+ <ClCompile Include="util\wininfo.cpp" />
</ItemGroup>
<ItemGroup>
<MASM Include="audio_asm.asm" />
@@ -549,4 +548,4 @@
<ImportGroup Label="ExtensionTargets">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
</ImportGroup>
-</Project>
+</Project> \ No newline at end of file
diff --git a/NorthstarDLL/NorthstarDLL.vcxproj.filters b/NorthstarDLL/NorthstarDLL.vcxproj.filters
index d8437ba5..e149396f 100644
--- a/NorthstarDLL/NorthstarDLL.vcxproj.filters
+++ b/NorthstarDLL/NorthstarDLL.vcxproj.filters
@@ -1173,8 +1173,8 @@
<ClInclude Include="core\macros.h">
<Filter>Header Files\core</Filter>
</ClInclude>
- <ClInclude Include="util\wininfo.h">
- <Filter>Header Files</Filter>
+ <ClInclude Include="util\wininfo.h">
+ <Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="util\utils.h">
<Filter>Header Files\util</Filter>
@@ -1240,9 +1240,6 @@
<ClCompile Include="mods\compiled\modkeyvalues.cpp">
<Filter>Source Files\mods\compiled</Filter>
</ClCompile>
- <ClCompile Include="mods\compiled\modpdef.cpp">
- <Filter>Source Files\mods\compiled</Filter>
- </ClCompile>
<ClCompile Include="mods\compiled\modscriptsrson.cpp">
<Filter>Source Files\mods\compiled</Filter>
</ClCompile>
@@ -1435,4 +1432,4 @@
<Filter>Source Files</Filter>
</MASM>
</ItemGroup>
-</Project>
+</Project> \ No newline at end of file
diff --git a/NorthstarDLL/client/audio.h b/NorthstarDLL/client/audio.h
index 26cda205..915d52ce 100644
--- a/NorthstarDLL/client/audio.h
+++ b/NorthstarDLL/client/audio.h
@@ -1,7 +1,5 @@
#pragma once
-#include <vector>
-#include <filesystem>
#include <regex>
#include <shared_mutex>
diff --git a/NorthstarDLL/client/clientvideooverrides.cpp b/NorthstarDLL/client/clientvideooverrides.cpp
index d8aa2754..d24dfa14 100644
--- a/NorthstarDLL/client/clientvideooverrides.cpp
+++ b/NorthstarDLL/client/clientvideooverrides.cpp
@@ -11,20 +11,20 @@ void*, __fastcall, (const char* path, uint32_t flags))
spdlog::info("BinkOpen {}", filename);
// figure out which mod is handling the bink
- Mod* fileOwner = nullptr;
- for (Mod& mod : g_pModManager->m_LoadedMods)
+ Mod* pFileOwner = nullptr;
+ for (Mod& mod : g_pModManager->GetMods())
{
if (!mod.m_bEnabled)
continue;
if (std::find(mod.BinkVideos.begin(), mod.BinkVideos.end(), filename) != mod.BinkVideos.end())
- fileOwner = &mod;
+ pFileOwner = &mod;
}
- if (fileOwner)
+ if (pFileOwner)
{
// create new path
- fs::path binkPath(fileOwner->m_ModDirectory / "media" / filename);
+ fs::path binkPath(pFileOwner->m_ModDirectory / "media" / filename);
return BinkOpen(binkPath.string().c_str(), flags);
}
else
diff --git a/NorthstarDLL/client/modlocalisation.cpp b/NorthstarDLL/client/modlocalisation.cpp
index 2b73876b..a2387e64 100644
--- a/NorthstarDLL/client/modlocalisation.cpp
+++ b/NorthstarDLL/client/modlocalisation.cpp
@@ -25,7 +25,7 @@ void, __fastcall, (void* pVguiLocalize))
// clang-format on
{
// load all mod localization manually, so we keep track of all files, not just previously loaded ones
- for (Mod mod : g_pModManager->m_LoadedMods)
+ for (Mod& mod : g_pModManager->GetMods())
if (mod.m_bEnabled)
for (std::string& localisationFile : mod.LocalisationFiles)
CLocalize__AddFile(g_pVguiLocalize, localisationFile.c_str(), nullptr, false);
@@ -43,7 +43,7 @@ void, __fastcall, (void* self))
// previously we did this in CLocalize::AddFile, but for some reason it won't properly overwrite localization from
// files loaded previously if done there, very weird but this works so whatever
- for (Mod mod : g_pModManager->m_LoadedMods)
+ for (Mod& mod : g_pModManager->GetMods())
if (mod.m_bEnabled)
for (std::string& localisationFile : mod.LocalisationFiles)
CLocalize__AddFile(g_pVguiLocalize, localisationFile.c_str(), nullptr, false);
diff --git a/NorthstarDLL/core/filesystem/filesystem.cpp b/NorthstarDLL/core/filesystem/filesystem.cpp
index 88622e5d..3cecc208 100644
--- a/NorthstarDLL/core/filesystem/filesystem.cpp
+++ b/NorthstarDLL/core/filesystem/filesystem.cpp
@@ -94,8 +94,8 @@ bool TryReplaceFile(const char* pPath, bool shouldCompile)
// 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())
+ auto file = g_pModManager->GetModFiles().find(g_pModManager->NormaliseModFilePath(fs::path(pPath)));
+ if (file != g_pModManager->GetModFiles().end())
{
SetNewModSearchPaths(file->second.m_pOwningMod);
return true;
@@ -146,7 +146,7 @@ HOOK(MountVPKHook, MountVPK, VPKData*, , (IFileSystem * fileSystem, const char*
NS::log::fs->info("MountVPK {}", pVpkPath);
VPKData* ret = MountVPK(fileSystem, pVpkPath);
- for (Mod mod : g_pModManager->m_LoadedMods)
+ for (Mod mod : g_pModManager->GetMods())
{
if (!mod.m_bEnabled)
continue;
diff --git a/NorthstarDLL/core/filesystem/rpakfilesystem.cpp b/NorthstarDLL/core/filesystem/rpakfilesystem.cpp
index c863463c..fa71c56f 100644
--- a/NorthstarDLL/core/filesystem/rpakfilesystem.cpp
+++ b/NorthstarDLL/core/filesystem/rpakfilesystem.cpp
@@ -89,15 +89,14 @@ void* PakLoadManager::LoadFile(const char* path)
void HandlePakAliases(char** map)
{
// convert the pak being loaded to it's aliased one, e.g. aliasing mp_hub_timeshift => sp_hub_timeshift
- for (int64_t i = g_pModManager->m_LoadedMods.size() - 1; i > -1; i--)
+ for (Mod& mod : g_pModManager->GetMods() | std::views::reverse)
{
- Mod* mod = &g_pModManager->m_LoadedMods[i];
- if (!mod->m_bEnabled)
+ if (!mod.m_bEnabled)
continue;
- if (mod->RpakAliases.find(*map) != mod->RpakAliases.end())
+ if (mod.RpakAliases.find(*map) != mod.RpakAliases.end())
{
- *map = &mod->RpakAliases[*map][0];
+ *map = &mod.RpakAliases[*map][0];
return;
}
}
@@ -106,7 +105,7 @@ void HandlePakAliases(char** map)
void LoadPreloadPaks()
{
// note, loading from ./ is necessary otherwise paks will load from gamedir/r2/paks
- for (Mod& mod : g_pModManager->m_LoadedMods)
+ for (Mod& mod : g_pModManager->GetMods())
{
if (!mod.m_bEnabled)
continue;
@@ -123,7 +122,7 @@ void LoadPreloadPaks()
void LoadPostloadPaks(const char* pPath)
{
// note, loading from ./ is necessary otherwise paks will load from gamedir/r2/paks
- for (Mod& mod : g_pModManager->m_LoadedMods)
+ for (Mod& mod : g_pModManager->GetMods())
{
if (!mod.m_bEnabled)
continue;
@@ -143,7 +142,7 @@ void LoadCustomMapPaks(char** pakName, bool* bNeedToFreePakName)
bool bHasOriginalPak = fs::exists(fs::path("r2/paks/Win64/") / *pakName);
// note, loading from ./ is necessary otherwise paks will load from gamedir/r2/paks
- for (Mod& mod : g_pModManager->m_LoadedMods)
+ for (Mod& mod : g_pModManager->GetMods())
{
if (!mod.m_bEnabled)
continue;
@@ -272,8 +271,8 @@ void*, __fastcall, (const char* pPath, void* pCallback))
NS::log::rpak->info("LoadStreamBsp: {}", filename.string());
// resolve modded stbsp path so we can load mod stbsps
- auto modFile = g_pModManager->m_ModFiles.find(g_pModManager->NormaliseModFilePath(fs::path("maps" / filename)));
- if (modFile != g_pModManager->m_ModFiles.end())
+ auto modFile = g_pModManager->GetModFiles().find(g_pModManager->NormaliseModFilePath(fs::path("maps" / filename)));
+ if (modFile != g_pModManager->GetModFiles().end())
{
newPath = (modFile->second.m_pOwningMod->m_ModDirectory / "mod" / modFile->second.m_Path).string();
pPath = newPath.c_str();
@@ -304,7 +303,7 @@ void*, __fastcall, (const char* pPath, void* pCallback))
size_t hashed = STR_HASH(starpakPath);
// loop through all loaded mods
- for (Mod& mod : g_pModManager->m_LoadedMods)
+ for (Mod& mod : g_pModManager->GetMods())
{
// ignore non-loaded mods
if (!mod.m_bEnabled)
diff --git a/NorthstarDLL/logging/crashhandler.cpp b/NorthstarDLL/logging/crashhandler.cpp
index 5d120d1f..38d9312f 100644
--- a/NorthstarDLL/logging/crashhandler.cpp
+++ b/NorthstarDLL/logging/crashhandler.cpp
@@ -33,12 +33,10 @@ void PrintExceptionLog(ExceptionLog& exc)
if (g_pModManager)
{
spdlog::error("Loaded mods: ");
- for (const auto& mod : g_pModManager->m_LoadedMods)
+ for (const Mod& mod : g_pModManager->GetMods())
{
if (mod.m_bEnabled)
- {
spdlog::error("{} {}", mod.Name, mod.Version);
- }
}
}
spdlog::error(exc.cause);
diff --git a/NorthstarDLL/mods/compiled/kb_act.cpp b/NorthstarDLL/mods/compiled/kb_act.cpp
index 3fc7ee30..109dc910 100644
--- a/NorthstarDLL/mods/compiled/kb_act.cpp
+++ b/NorthstarDLL/mods/compiled/kb_act.cpp
@@ -16,7 +16,7 @@ void ModManager::BuildKBActionsList()
// write vanilla file's content to compiled file
soCompiledKeys << R2::ReadVPKOriginalFile(KB_ACT_PATH);
- for (Mod& mod : m_LoadedMods)
+ for (Mod& mod : GetMods())
{
if (!mod.m_bEnabled)
continue;
@@ -37,8 +37,8 @@ void ModManager::BuildKBActionsList()
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));
+ if (GetModFiles().find(KB_ACT_PATH) == GetModFiles().end())
+ GetModFiles().insert(std::make_pair(KB_ACT_PATH, overrideFile));
else
- m_ModFiles[KB_ACT_PATH] = overrideFile;
+ GetModFiles()[KB_ACT_PATH] = overrideFile;
}
diff --git a/NorthstarDLL/mods/compiled/modkeyvalues.cpp b/NorthstarDLL/mods/compiled/modkeyvalues.cpp
index fe262a60..ff2fafc1 100644
--- a/NorthstarDLL/mods/compiled/modkeyvalues.cpp
+++ b/NorthstarDLL/mods/compiled/modkeyvalues.cpp
@@ -24,14 +24,14 @@ void ModManager::TryBuildKeyValues(const char* filename)
// copy over patch kv files, and add #bases to new file, last mods' patches should be applied first
// note: #include should be identical but it's actually just broken, thanks respawn
- for (int64_t i = m_LoadedMods.size() - 1; i > -1; i--)
+ for (Mod& mod : GetMods() | std::views::reverse)
{
- if (!m_LoadedMods[i].m_bEnabled)
+ if (mod.m_bEnabled)
continue;
size_t fileHash = STR_HASH(normalisedPath);
- auto modKv = m_LoadedMods[i].KeyValues.find(fileHash);
- if (modKv != m_LoadedMods[i].KeyValues.end())
+ auto modKv = mod.KeyValues.find(fileHash);
+ if (modKv != mod.KeyValues.end())
{
// should result in smth along the lines of #include "mod_patch_5_mp_weapon_car.txt"
@@ -46,7 +46,7 @@ void ModManager::TryBuildKeyValues(const char* filename)
fs::remove(compiledDir / patchFilePath);
- fs::copy_file(m_LoadedMods[i].m_ModDirectory / "keyvalues" / filename, compiledDir / patchFilePath);
+ fs::copy_file(mod.m_ModDirectory / "keyvalues" / filename, compiledDir / patchFilePath);
}
}
@@ -99,8 +99,8 @@ void ModManager::TryBuildKeyValues(const char* filename)
overrideFile.m_pOwningMod = nullptr;
overrideFile.m_Path = normalisedPath;
- if (m_ModFiles.find(normalisedPath) == m_ModFiles.end())
- m_ModFiles.insert(std::make_pair(normalisedPath, overrideFile));
+ if (GetModFiles().find(normalisedPath) == GetModFiles().end())
+ GetModFiles().insert(std::make_pair(normalisedPath, overrideFile));
else
- m_ModFiles[normalisedPath] = overrideFile;
+ GetModFiles()[normalisedPath] = overrideFile;
}
diff --git a/NorthstarDLL/mods/compiled/modpdef.cpp b/NorthstarDLL/mods/compiled/modpdef.cpp
deleted file mode 100644
index 4b1b12b7..00000000
--- a/NorthstarDLL/mods/compiled/modpdef.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-#include "mods/modmanager.h"
-#include "core/filesystem/filesystem.h"
-
-#include <map>
-#include <sstream>
-#include <fstream>
-
-const fs::path MOD_PDEF_SUFFIX = "cfg/server/persistent_player_data_version_231.pdef";
-const char* VPK_PDEF_PATH = "cfg/server/persistent_player_data_version_231.pdef";
-
-void ModManager::BuildPdef()
-{
- spdlog::info("Building persistent_player_data_version_231.pdef...");
-
- fs::path MOD_PDEF_PATH = fs::path(GetCompiledAssetsPath() / MOD_PDEF_SUFFIX);
-
- fs::remove(MOD_PDEF_PATH);
- std::string pdef = R2::ReadVPKOriginalFile(VPK_PDEF_PATH);
-
- for (Mod& mod : m_LoadedMods)
- {
- if (!mod.m_bEnabled || !mod.Pdiff.size())
- continue;
-
- // this code probably isn't going to be pretty lol
- // refer to shared/pjson.js for an actual okish parser of the pdiff format
- // but pretty much, $ENUM_ADD blocks define members added to preexisting enums
- // $PROP_START ends the custom stuff, and from there it's just normal props we append to the pdef
-
- std::map<std::string, std::vector<std::string>> enumAdds;
-
- // read pdiff
- bool inEnum = false;
- bool inProp = false;
- std::string currentEnum;
- std::string currentLine;
- std::istringstream pdiffStream(mod.Pdiff);
-
- while (std::getline(pdiffStream, currentLine))
- {
- if (inProp)
- {
- // just append to pdef here
- pdef += currentLine;
- pdef += '\n';
- continue;
- }
-
- // trim leading whitespace
- size_t start = currentLine.find_first_not_of(" \n\r\t\f\v");
- size_t end = currentLine.find("//");
- if (end == std::string::npos)
- end = currentLine.size() - 1; // last char
-
- if (!currentLine.size() || !currentLine.compare(start, 2, "//"))
- continue;
-
- if (inEnum)
- {
- if (!currentLine.compare(start, 9, "$ENUM_END"))
- inEnum = false;
- else
- enumAdds[currentEnum].push_back(currentLine); // only need to push_back current line, if there's syntax errors then game
- // pdef parser will handle them
- }
- else if (!currentLine.compare(start, 9, "$ENUM_ADD"))
- {
- inEnum = true;
- currentEnum = currentLine.substr(start + 10 /*$ENUM_ADD + 1*/, currentLine.size() - end - (start + 10));
- enumAdds.insert(std::make_pair(currentEnum, std::vector<std::string>()));
- }
- else if (!currentLine.compare(start, 11, "$PROP_START"))
- {
- inProp = true;
- pdef += "\n// $PROP_START ";
- pdef += mod.Name;
- pdef += "\n";
- }
- }
-
- // add new members to preexisting enums
- // note: this code could 100% be messed up if people put //$ENUM_START comments and the like
- // could make it protect against this, but honestly not worth atm
- for (auto enumAdd : enumAdds)
- {
- std::string addStr;
- for (std::string enumMember : enumAdd.second)
- {
- addStr += enumMember;
- addStr += '\n';
- }
-
- // start of enum we're adding to
- std::string startStr = "$ENUM_START ";
- startStr += enumAdd.first;
-
- // insert enum values into enum
- size_t insertIdx = pdef.find("$ENUM_END", pdef.find(startStr));
- pdef.reserve(addStr.size());
- pdef.insert(insertIdx, addStr);
- }
- }
-
- fs::create_directories(MOD_PDEF_PATH.parent_path());
-
- std::ofstream writeStream(MOD_PDEF_PATH, std::ios::binary);
- 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;
-}
diff --git a/NorthstarDLL/mods/compiled/modscriptsrson.cpp b/NorthstarDLL/mods/compiled/modscriptsrson.cpp
index cbe26651..292e9c99 100644
--- a/NorthstarDLL/mods/compiled/modscriptsrson.cpp
+++ b/NorthstarDLL/mods/compiled/modscriptsrson.cpp
@@ -16,7 +16,7 @@ void ModManager::BuildScriptsRson()
std::string scriptsRson = R2::ReadVPKOriginalFile(VPK_SCRIPTS_RSON_PATH);
scriptsRson += "\n\n// START MODDED SCRIPT CONTENT\n\n"; // newline before we start custom stuff
- for (Mod& mod : m_LoadedMods)
+ for (Mod& mod : GetMods())
{
if (!mod.m_bEnabled)
continue;
@@ -55,10 +55,10 @@ void ModManager::BuildScriptsRson()
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));
+ if (GetModFiles().find(VPK_SCRIPTS_RSON_PATH) == GetModFiles().end())
+ GetModFiles().insert(std::make_pair(VPK_SCRIPTS_RSON_PATH, overrideFile));
else
- m_ModFiles[VPK_SCRIPTS_RSON_PATH] = overrideFile;
+ GetModFiles()[VPK_SCRIPTS_RSON_PATH] = overrideFile;
// 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
diff --git a/NorthstarDLL/mods/modmanager.cpp b/NorthstarDLL/mods/modmanager.cpp
index 4e5380cf..04484fad 100644
--- a/NorthstarDLL/mods/modmanager.cpp
+++ b/NorthstarDLL/mods/modmanager.cpp
@@ -97,27 +97,27 @@ Mod::Mod(fs::path modDir, char* jsonBuf)
// have to allocate this manually, otherwise convar registration will break
// unfortunately this causes us to leak memory on reload, unsure of a way around this rn
- ModConVar* convar = new ModConVar;
- convar->Name = convarObj["Name"].GetString();
- convar->DefaultValue = convarObj["DefaultValue"].GetString();
+ ModConVar convar;
+ convar.Name = convarObj["Name"].GetString();
+ convar.DefaultValue = convarObj["DefaultValue"].GetString();
if (convarObj.HasMember("HelpString"))
- convar->HelpString = convarObj["HelpString"].GetString();
+ convar.HelpString = convarObj["HelpString"].GetString();
else
- convar->HelpString = "";
+ convar.HelpString = "";
- convar->Flags = FCVAR_NONE;
+ convar.Flags = FCVAR_NONE;
if (convarObj.HasMember("Flags"))
{
// read raw integer flags
if (convarObj["Flags"].IsInt())
- convar->Flags = convarObj["Flags"].GetInt();
+ convar.Flags = convarObj["Flags"].GetInt();
else if (convarObj["Flags"].IsString())
{
// parse cvar flags from string
// example string: ARCHIVE_PLAYERPROFILE | GAMEDLL
- convar->Flags |= ParseConVarFlagsString(convar->Name, convarObj["Flags"].GetString());
+ convar.Flags |= ParseConVarFlagsString(convar.Name, convarObj["Flags"].GetString());
}
}
@@ -125,6 +125,7 @@ Mod::Mod(fs::path modDir, char* jsonBuf)
}
}
+ // mod commands
if (modJson.HasMember("ConCommands") && modJson["ConCommands"].IsArray())
{
for (auto& concommandObj : modJson["ConCommands"].GetArray())
@@ -137,35 +138,35 @@ Mod::Mod(fs::path modDir, char* jsonBuf)
// have to allocate this manually, otherwise concommand registration will break
// unfortunately this causes us to leak memory on reload, unsure of a way around this rn
- ModConCommand* concommand = new ModConCommand;
- concommand->Name = concommandObj["Name"].GetString();
- concommand->Function = concommandObj["Function"].GetString();
- concommand->Context = ScriptContextFromString(concommandObj["Context"].GetString());
- if (concommand->Context == ScriptContext::INVALID)
+ ModConCommand concommand;
+ concommand.Name = concommandObj["Name"].GetString();
+ concommand.Function = concommandObj["Function"].GetString();
+ concommand.Context = ScriptContextFromString(concommandObj["Context"].GetString());
+ if (concommand.Context == ScriptContext::INVALID)
{
- spdlog::warn("Mod ConCommand {} has invalid context {}", concommand->Name, concommandObj["Context"].GetString());
+ spdlog::warn("Mod ConCommand {} has invalid context {}", concommand.Name, concommandObj["Context"].GetString());
continue;
}
if (concommandObj.HasMember("HelpString"))
- concommand->HelpString = concommandObj["HelpString"].GetString();
+ concommand.HelpString = concommandObj["HelpString"].GetString();
else
- concommand->HelpString = "";
+ concommand.HelpString = "";
- concommand->Flags = FCVAR_NONE;
+ concommand.Flags = FCVAR_NONE;
if (concommandObj.HasMember("Flags"))
{
// read raw integer flags
if (concommandObj["Flags"].IsInt())
{
- concommand->Flags = concommandObj["Flags"].GetInt();
+ concommand.Flags = concommandObj["Flags"].GetInt();
}
else if (concommandObj["Flags"].IsString())
{
// parse cvar flags from string
// example string: ARCHIVE_PLAYERPROFILE | GAMEDLL
- concommand->Flags |= ParseConVarFlagsString(concommand->Name, concommandObj["Flags"].GetString());
+ concommand.Flags |= ParseConVarFlagsString(concommand.Name, concommandObj["Flags"].GetString());
}
}
@@ -288,66 +289,54 @@ ModManager::ModManager()
LoadMods();
}
-struct Test
-{
- std::string funcName;
- ScriptContext context;
-};
-
template <ScriptContext context> auto ModConCommandCallback_Internal(std::string name, const CCommand& command)
{
- if (g_pSquirrel<context>->m_pSQVM && g_pSquirrel<context>->m_pSQVM)
+ if (g_pSquirrel<context>->m_pSQVM && g_pSquirrel<context>->m_pSQVM->sqvm)
{
- std::vector<std::string> args;
- args.reserve(command.ArgC());
+ std::vector<std::string> vArgs;
+ vArgs.reserve(command.ArgC());
for (int i = 1; i < command.ArgC(); i++)
- args.push_back(command.Arg(i));
- g_pSquirrel<context>->AsyncCall(name, args);
+ vArgs.push_back(command.Arg(i));
+
+ g_pSquirrel<context>->AsyncCall(name, vArgs);
}
else
- {
- spdlog::warn("ConCommand `{}` was called while the associated Squirrel VM `{}` was unloaded", name, GetContextName(context));
- }
+ spdlog::warn("ConCommand \"{}\" was called while the associated Squirrel VM \"{}\" was unloaded", name, GetContextName(context));
}
auto ModConCommandCallback(const CCommand& command)
{
- ModConCommand* found = nullptr;
- auto commandString = std::string(command.GetCommandString());
-
- // Finding the first space to remove the command's name
- auto firstSpace = commandString.find(' ');
- if (firstSpace)
- {
- commandString = commandString.substr(0, firstSpace);
- }
+ ModConCommand* pFoundCommand = nullptr;
+ std::string sCommandName = command.Arg(0);
// Find the mod this command belongs to
- for (auto& mod : g_pModManager->m_LoadedMods)
+ for (Mod& mod : g_pModManager->GetMods())
{
auto res = std::find_if(
mod.ConCommands.begin(),
mod.ConCommands.end(),
- [&commandString](const ModConCommand* other) { return other->Name == commandString; });
+ [&sCommandName](const ModConCommand* other) { return other->Name == sCommandName; });
+
if (res != mod.ConCommands.end())
{
- found = *res;
+ pFoundCommand = &*res;
break;
}
}
- if (!found)
+
+ if (!pFoundCommand)
return;
- switch (found->Context)
+ switch (pFoundCommand->Context)
{
case ScriptContext::CLIENT:
- ModConCommandCallback_Internal<ScriptContext::CLIENT>(found->Function, command);
+ ModConCommandCallback_Internal<ScriptContext::CLIENT>(pFoundCommand->Function, command);
break;
case ScriptContext::SERVER:
- ModConCommandCallback_Internal<ScriptContext::SERVER>(found->Function, command);
+ ModConCommandCallback_Internal<ScriptContext::SERVER>(pFoundCommand->Function, command);
break;
case ScriptContext::UI:
- ModConCommandCallback_Internal<ScriptContext::UI>(found->Function, command);
+ ModConCommandCallback_Internal<ScriptContext::UI>(pFoundCommand->Function, command);
break;
};
}
@@ -443,7 +432,10 @@ void ModManager::LoadMods()
}
// sort by load prio, lowest-highest
- std::sort(m_LoadedMods.begin(), m_LoadedMods.end(), [](Mod& a, Mod& b) { return a.LoadPriority < b.LoadPriority; });
+ std::sort(
+ m_ModLoadState.m_LoadedMods.begin(),
+ m_ModLoadState.m_LoadedMods.end(),
+ [](Mod& a, Mod& b) { return a.LoadPriority < b.LoadPriority; });
for (Mod& mod : m_LoadedMods)
{
@@ -451,47 +443,47 @@ void ModManager::LoadMods()
continue;
// register convars
- for (ModConVar* convar : mod.ConVars)
+ for (ModConVar convar : mod.ConVars)
{
- ConVar* pVar = R2::g_pCVar->FindVar(convar->Name.c_str());
+ ConVar* pVar = R2::g_pCVar->FindVar(convar.Name.c_str());
// make sure convar isn't registered yet, if it is then modify its flags, helpstring etc
if (!pVar)
- new ConVar(convar->Name.c_str(), convar->DefaultValue.c_str(), convar->Flags, convar->HelpString.c_str());
+ new ConVar(convar.Name.c_str(), convar.DefaultValue.c_str(), convar.Flags, convar.HelpString.c_str());
else
{
// TODO: should probably make sure this is actually a mod convar we're messing with
- pVar->m_ConCommandBase.m_nFlags = convar->Flags;
+ pVar->m_ConCommandBase.m_nFlags = convar.Flags;
// unfortunately this leaks memory and we can't really not leak memory because we don't know who allocated this
// so we can't delete it without risking a crash
- if (convar->HelpString.compare(pVar->GetHelpText()))
+ if (convar.HelpString.compare(pVar->GetHelpText()))
{
- int nHelpSize = convar->HelpString.size();
+ int nHelpSize = convar.HelpString.size();
char* pNewHelpString = new char[nHelpSize + 1];
- strncpy_s(pNewHelpString, nHelpSize + 1, convar->HelpString.c_str(), convar->HelpString.size());
+ strncpy_s(pNewHelpString, nHelpSize + 1, convar.HelpString.c_str(), convar.HelpString.size());
pVar->m_ConCommandBase.m_pszHelpString = pNewHelpString;
}
- if (convar->DefaultValue.compare(pVar->m_pszDefaultValue))
+ if (convar.DefaultValue.compare(pVar->m_pszDefaultValue))
{
- int nDefaultValueSize = convar->DefaultValue.size();
+ int nDefaultValueSize = convar.DefaultValue.size();
char* pNewDefaultValueString = new char[nDefaultValueSize + 1];
- strncpy_s(pNewDefaultValueString, nDefaultValueSize + 1, convar->DefaultValue.c_str(), convar->DefaultValue.size());
+ strncpy_s(pNewDefaultValueString, nDefaultValueSize + 1, convar.DefaultValue.c_str(), convar.DefaultValue.size());
pVar->m_pszDefaultValue = pNewDefaultValueString;
pVar->SetValue(pNewDefaultValueString);
}
}
}
- for (ModConCommand* command : mod.ConCommands)
+ for (ModConCommand command : mod.ConCommands)
{
// make sure command isnt't registered multiple times.
- if (!R2::g_pCVar->FindCommand(command->Name.c_str()))
+ if (!R2::g_pCVar->FindCommand(command.Name.c_str()))
{
- std::string funcName = command->Function;
- RegisterConCommand(command->Name.c_str(), ModConCommandCallback, command->HelpString.c_str(), command->Flags);
+ std::string funcName = command.Function;
+ RegisterConCommand(command.Name.c_str(), ModConCommandCallback, command.HelpString.c_str(), command.Flags);
}
}
@@ -754,6 +746,8 @@ void ModManager::LoadMods()
void ModManager::UnloadMods()
{
+ m_LastModLoadState = m_ModLoadState;
+
// clean up stuff from mods before we unload
m_ModFiles.clear();
fs::remove_all(GetCompiledAssetsPath());
@@ -769,8 +763,6 @@ void ModManager::UnloadMods()
for (std::pair<size_t, std::string> kvPaths : mod.KeyValues)
fs::remove(GetCompiledAssetsPath() / fs::path(kvPaths.second).lexically_relative(mod.m_ModDirectory));
- mod.KeyValues.clear();
-
// write to m_enabledModsCfg
// should we be doing this here or should scripts be doing this manually?
// main issue with doing this here is when we reload mods for connecting to a server, we write enabled mods, which isn't necessarily
@@ -809,13 +801,15 @@ void ModManager::CompileAssetsForFile(const char* filename)
if (fileHash == m_hScriptsRsonHash)
BuildScriptsRson();
else if (fileHash == m_hPdefHash)
- BuildPdef();
+ {
+ // BuildPdef(); todo
+ }
else if (fileHash == m_hKBActHash)
BuildKBActionsList();
else
{
// check if we should build keyvalues, depending on whether any of our mods have patch kvs for this file
- for (Mod& mod : m_LoadedMods)
+ for (Mod& mod : GetMods())
{
if (!mod.m_bEnabled)
continue;
diff --git a/NorthstarDLL/mods/modmanager.h b/NorthstarDLL/mods/modmanager.h
index 369eb07b..d44a202f 100644
--- a/NorthstarDLL/mods/modmanager.h
+++ b/NorthstarDLL/mods/modmanager.h
@@ -98,9 +98,9 @@ class Mod
// custom scripts used by the mod
std::vector<ModScript> Scripts;
// convars created by the mod
- std::vector<ModConVar*> ConVars;
+ std::vector<ModConVar> ConVars;
// concommands created by the mod
- std::vector<ModConCommand*> ConCommands;
+ std::vector<ModConCommand> ConCommands;
// custom localisation files created by the mod
std::vector<std::string> LocalisationFiles;
@@ -127,10 +127,18 @@ class Mod
struct ModOverrideFile
{
public:
- Mod* m_pOwningMod;
+ Mod* m_pOwningMod; // don't need to explicitly clean this up
fs::path m_Path;
};
+class ModLoadState
+{
+ public:
+ std::vector<Mod> m_LoadedMods;
+ std::unordered_map<std::string, ModOverrideFile> m_ModFiles;
+ std::unordered_map<std::string, std::string> m_DependencyConstants;
+};
+
class ModManager
{
private:
@@ -144,9 +152,8 @@ class ModManager
size_t m_hKBActHash;
public:
- std::vector<Mod> m_LoadedMods;
- std::unordered_map<std::string, ModOverrideFile> m_ModFiles;
- std::unordered_map<std::string, std::string> m_DependencyConstants;
+ ModLoadState m_LastModLoadState;
+ ModLoadState m_ModLoadState;
public:
ModManager();
@@ -155,6 +162,22 @@ class ModManager
std::string NormaliseModFilePath(const fs::path path);
void CompileAssetsForFile(const char* filename);
+ // getters
+ inline std::vector<Mod>& GetMods()
+ {
+ return m_ModLoadState.m_LoadedMods;
+ };
+
+ inline std::unordered_map<std::string, ModOverrideFile>& GetModFiles()
+ {
+ return m_ModLoadState.m_ModFiles;
+ };
+
+ inline std::unordered_map<std::string, std::string>& GetDependencyConstants()
+ {
+ return m_ModLoadState.m_DependencyConstants;
+ };
+
// compile asset type stuff, these are done in files under runtime/compiled/
void BuildScriptsRson();
void TryBuildKeyValues(const char* filename);
diff --git a/NorthstarDLL/pch.h b/NorthstarDLL/pch.h
index 55ebba8b..433030b6 100644
--- a/NorthstarDLL/pch.h
+++ b/NorthstarDLL/pch.h
@@ -17,6 +17,8 @@
#include <map>
#include <filesystem>
#include <sstream>
+#include <ranges>
+#include <vector>
namespace fs = std::filesystem;
diff --git a/NorthstarDLL/scripts/client/scriptmodmenu.cpp b/NorthstarDLL/scripts/client/scriptmodmenu.cpp
index a88478fb..c6c53c7f 100644
--- a/NorthstarDLL/scripts/client/scriptmodmenu.cpp
+++ b/NorthstarDLL/scripts/client/scriptmodmenu.cpp
@@ -5,7 +5,7 @@ ADD_SQFUNC("array<string>", NSGetModNames, "", "", ScriptContext::SERVER | Scrip
{
g_pSquirrel<context>->newarray(sqvm, 0);
- for (Mod& mod : g_pModManager->m_LoadedMods)
+ for (Mod& mod : g_pModManager->GetMods())
{
g_pSquirrel<context>->pushstring(sqvm, mod.Name.c_str());
g_pSquirrel<context>->arrayappend(sqvm, -2);
@@ -19,7 +19,7 @@ ADD_SQFUNC("bool", NSIsModEnabled, "string modName", "", ScriptContext::SERVER |
const SQChar* modName = g_pSquirrel<context>->getstring(sqvm, 1);
// manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_pModManager->m_LoadedMods)
+ for (Mod& mod : g_pModManager->GetMods())
{
if (!mod.Name.compare(modName))
{
@@ -37,7 +37,7 @@ ADD_SQFUNC("void", NSSetModEnabled, "string modName, bool enabled", "", ScriptCo
const SQBool enabled = g_pSquirrel<context>->getbool(sqvm, 2);
// manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_pModManager->m_LoadedMods)
+ for (Mod& mod : g_pModManager->GetMods())
{
if (!mod.Name.compare(modName))
{
@@ -54,7 +54,7 @@ ADD_SQFUNC("string", NSGetModDescriptionByModName, "string modName", "", ScriptC
const SQChar* modName = g_pSquirrel<context>->getstring(sqvm, 1);
// manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_pModManager->m_LoadedMods)
+ for (Mod& mod : g_pModManager->GetMods())
{
if (!mod.Name.compare(modName))
{
@@ -71,7 +71,7 @@ ADD_SQFUNC("string", NSGetModVersionByModName, "string modName", "", ScriptConte
const SQChar* modName = g_pSquirrel<context>->getstring(sqvm, 1);
// manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_pModManager->m_LoadedMods)
+ for (Mod& mod : g_pModManager->GetMods())
{
if (!mod.Name.compare(modName))
{
@@ -88,7 +88,7 @@ ADD_SQFUNC("string", NSGetModDownloadLinkByModName, "string modName", "", Script
const SQChar* modName = g_pSquirrel<context>->getstring(sqvm, 1);
// manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_pModManager->m_LoadedMods)
+ for (Mod& mod : g_pModManager->GetMods())
{
if (!mod.Name.compare(modName))
{
@@ -105,7 +105,7 @@ ADD_SQFUNC("int", NSGetModLoadPriority, "string modName", "", ScriptContext::SER
const SQChar* modName = g_pSquirrel<context>->getstring(sqvm, 1);
// manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_pModManager->m_LoadedMods)
+ for (Mod& mod : g_pModManager->GetMods())
{
if (!mod.Name.compare(modName))
{
@@ -122,7 +122,7 @@ ADD_SQFUNC("bool", NSIsModRequiredOnClient, "string modName", "", ScriptContext:
const SQChar* modName = g_pSquirrel<context>->getstring(sqvm, 1);
// manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_pModManager->m_LoadedMods)
+ for (Mod& mod : g_pModManager->GetMods())
{
if (!mod.Name.compare(modName))
{
@@ -141,7 +141,7 @@ ADD_SQFUNC(
g_pSquirrel<context>->newarray(sqvm, 0);
// manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_pModManager->m_LoadedMods)
+ for (Mod& mod : g_pModManager->GetMods())
{
if (!mod.Name.compare(modName))
{
diff --git a/NorthstarDLL/squirrel/squirrel.cpp b/NorthstarDLL/squirrel/squirrel.cpp
index 4cf342db..4e64aecc 100644
--- a/NorthstarDLL/squirrel/squirrel.cpp
+++ b/NorthstarDLL/squirrel/squirrel.cpp
@@ -189,11 +189,11 @@ template <ScriptContext context> void SquirrelManager<context>::VMCreated(CSquir
RegisterSquirrelFunc(m_pSQVM, funcReg, 1);
}
- for (auto& pair : g_pModManager->m_DependencyConstants)
+ for (auto& pair : g_pModManager->GetDependencyConstants())
{
bool bWasFound = false;
- for (Mod& dependency : g_pModManager->m_LoadedMods)
+ for (Mod& dependency : g_pModManager->GetMods())
{
if (!dependency.m_bEnabled)
continue;
@@ -471,7 +471,7 @@ template <ScriptContext context> bool __fastcall CallScriptInitCallbackHook(void
if (bShouldCallCustomCallbacks)
{
- for (Mod mod : g_pModManager->m_LoadedMods)
+ for (Mod& mod : g_pModManager->GetMods())
{
if (!mod.m_bEnabled)
continue;
@@ -498,7 +498,7 @@ template <ScriptContext context> bool __fastcall CallScriptInitCallbackHook(void
// run after callbacks
if (bShouldCallCustomCallbacks)
{
- for (Mod mod : g_pModManager->m_LoadedMods)
+ for (Mod& mod : g_pModManager->GetMods())
{
if (!mod.m_bEnabled)
continue;
diff --git a/NorthstarDLL/squirrel/squirrel.h b/NorthstarDLL/squirrel/squirrel.h
index ce758d7c..65bda7e3 100644
--- a/NorthstarDLL/squirrel/squirrel.h
+++ b/NorthstarDLL/squirrel/squirrel.h
@@ -239,17 +239,15 @@ class SquirrelManagerBase
{
SQStackInfos stackInfo {};
if (1 + depth >= sqvm->_callstacksize)
- {
return nullptr;
- }
+
sq_stackinfos(sqvm, 1 + depth, stackInfo);
std::string sourceName = stackInfo._sourceName;
std::replace(sourceName.begin(), sourceName.end(), '/', '\\');
std::string filename = "scripts\\vscripts\\" + sourceName;
- if (auto res = g_pModManager->m_ModFiles.find(filename); res != g_pModManager->m_ModFiles.end())
- {
+ if (auto res = g_pModManager->GetModFiles().find(filename); res != g_pModManager->GetModFiles().end())
return res->second.m_pOwningMod;
- }
+
return nullptr;
}
template <typename T> inline SQRESULT getuserdata(HSquirrelVM* sqvm, const SQInteger stackpos, T* data, uint64_t* typeId)
diff --git a/NorthstarDLL/util/printmaps.cpp b/NorthstarDLL/util/printmaps.cpp
index 99bda23c..449aa351 100644
--- a/NorthstarDLL/util/printmaps.cpp
+++ b/NorthstarDLL/util/printmaps.cpp
@@ -36,7 +36,7 @@ void RefreshMapList()
// get modded maps
// TODO: could probably check mod vpks to get mapnames from there too?
- for (auto& modFilePair : g_pModManager->m_ModFiles)
+ for (auto& modFilePair : g_pModManager->GetModFiles())
{
ModOverrideFile file = modFilePair.second;
if (file.m_Path.extension() == ".bsp" && file.m_Path.parent_path().string() == "maps") // only allow mod maps actually in /maps atm