aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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/convar/concommand.h1
-rw-r--r--NorthstarDLL/core/convar/convar.cpp2
-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.cpp119
-rw-r--r--NorthstarDLL/mods/compiled/modscriptsrson.cpp8
-rw-r--r--NorthstarDLL/mods/modmanager.cpp150
-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
21 files changed, 175 insertions, 265 deletions
diff --git a/NorthstarDLL/NorthstarDLL.vcxproj b/NorthstarDLL/NorthstarDLL.vcxproj
index ebbeb375..68b172fa 100644
--- a/NorthstarDLL/NorthstarDLL.vcxproj
+++ b/NorthstarDLL/NorthstarDLL.vcxproj
@@ -447,7 +447,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" />
@@ -496,7 +496,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">
@@ -538,7 +537,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" />
@@ -547,4 +546,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 1a5924c7..ab78b943 100644
--- a/NorthstarDLL/client/clientvideooverrides.cpp
+++ b/NorthstarDLL/client/clientvideooverrides.cpp
@@ -12,20 +12,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 e5afc793..db138315 100644
--- a/NorthstarDLL/client/modlocalisation.cpp
+++ b/NorthstarDLL/client/modlocalisation.cpp
@@ -26,7 +26,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);
@@ -44,7 +44,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/convar/concommand.h b/NorthstarDLL/core/convar/concommand.h
index 89363bc7..c170c6a5 100644
--- a/NorthstarDLL/core/convar/concommand.h
+++ b/NorthstarDLL/core/convar/concommand.h
@@ -97,7 +97,6 @@ class ConCommandBase
bool IsCommand(void) const;
bool IsRegistered(void) const;
bool IsFlagSet(int nFlags) const;
- static bool IsFlagSet(ConCommandBase* pCommandBase, int nFlags); // For hooking to engine's implementation.
int GetFlags(void) const;
ConCommandBase* GetNext(void) const;
diff --git a/NorthstarDLL/core/convar/convar.cpp b/NorthstarDLL/core/convar/convar.cpp
index 11411c0a..81648f53 100644
--- a/NorthstarDLL/core/convar/convar.cpp
+++ b/NorthstarDLL/core/convar/convar.cpp
@@ -527,4 +527,6 @@ int ParseConVarFlagsString(std::string modName, std::string sFlags)
sCurrentFlag += sFlags[i];
}
}
+
+ return FCVAR_NONE;
}
diff --git a/NorthstarDLL/core/filesystem/filesystem.cpp b/NorthstarDLL/core/filesystem/filesystem.cpp
index ac42d00f..bfdfdb19 100644
--- a/NorthstarDLL/core/filesystem/filesystem.cpp
+++ b/NorthstarDLL/core/filesystem/filesystem.cpp
@@ -95,8 +95,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;
@@ -147,7 +147,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 c3463781..2bddd8fe 100644
--- a/NorthstarDLL/core/filesystem/rpakfilesystem.cpp
+++ b/NorthstarDLL/core/filesystem/rpakfilesystem.cpp
@@ -90,15 +90,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;
}
}
@@ -107,7 +106,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;
@@ -124,7 +123,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;
@@ -144,7 +143,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;
@@ -273,8 +272,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();
@@ -305,7 +304,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 1e9bf4b3..3427e10a 100644
--- a/NorthstarDLL/logging/crashhandler.cpp
+++ b/NorthstarDLL/logging/crashhandler.cpp
@@ -34,12 +34,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 4a011dc7..f3ad460f 100644
--- a/NorthstarDLL/mods/compiled/kb_act.cpp
+++ b/NorthstarDLL/mods/compiled/kb_act.cpp
@@ -17,7 +17,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;
@@ -38,8 +38,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 774be0eb..051b193e 100644
--- a/NorthstarDLL/mods/compiled/modkeyvalues.cpp
+++ b/NorthstarDLL/mods/compiled/modkeyvalues.cpp
@@ -25,14 +25,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"
@@ -47,7 +47,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);
}
}
@@ -100,8 +100,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 219c744b..00000000
--- a/NorthstarDLL/mods/compiled/modpdef.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-#include "pch.h"
-#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 15fcdd13..b24aabe9 100644
--- a/NorthstarDLL/mods/compiled/modscriptsrson.cpp
+++ b/NorthstarDLL/mods/compiled/modscriptsrson.cpp
@@ -17,7 +17,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;
@@ -56,10 +56,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 e37df6e5..5011f0fb 100644
--- a/NorthstarDLL/mods/modmanager.cpp
+++ b/NorthstarDLL/mods/modmanager.cpp
@@ -98,27 +98,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());
}
}
@@ -126,6 +126,7 @@ Mod::Mod(fs::path modDir, char* jsonBuf)
}
}
+ // mod commands
if (modJson.HasMember("ConCommands") && modJson["ConCommands"].IsArray())
{
for (auto& concommandObj : modJson["ConCommands"].GetArray())
@@ -138,35 +139,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());
}
}
@@ -289,66 +290,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;
};
}
@@ -444,7 +433,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)
{
@@ -452,27 +444,47 @@ void ModManager::LoadMods()
continue;
// register convars
- // for reloads, this is sorta barebones, when we have a good findconvar method, we could probably reset flags and stuff on
- // preexisting convars note: we don't delete convars if they already exist because they're used for script stuff, unfortunately this
- // causes us to leak memory on reload, but not much, potentially find a way to not do this at some point
- for (ModConVar* convar : mod.ConVars)
+ for (ModConVar convar : mod.ConVars)
{
- // make sure convar isn't registered yet, unsure if necessary but idk what
- // behaviour is for defining same convar multiple times
- if (!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());
+ else
{
- new ConVar(convar->Name.c_str(), convar->DefaultValue.c_str(), convar->Flags, convar->HelpString.c_str());
+ // TODO: should probably make sure this is actually a mod convar we're messing with
+
+ 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()))
+ {
+ int nHelpSize = convar.HelpString.size();
+ char* pNewHelpString = new char[nHelpSize + 1];
+ 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))
+ {
+ int nDefaultValueSize = convar.DefaultValue.size();
+ char* pNewDefaultValueString = new char[nDefaultValueSize + 1];
+ 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()))
{
- ConCommand* newCommand = new ConCommand();
- 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);
}
}
@@ -735,6 +747,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());
@@ -750,8 +764,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
@@ -790,13 +802,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 75d05acc..0beea4f2 100644
--- a/NorthstarDLL/scripts/client/scriptmodmenu.cpp
+++ b/NorthstarDLL/scripts/client/scriptmodmenu.cpp
@@ -6,7 +6,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);
@@ -20,7 +20,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))
{
@@ -38,7 +38,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))
{
@@ -55,7 +55,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))
{
@@ -72,7 +72,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))
{
@@ -89,7 +89,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))
{
@@ -106,7 +106,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))
{
@@ -123,7 +123,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))
{
@@ -142,7 +142,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 25fb90d5..0bbc496f 100644
--- a/NorthstarDLL/squirrel/squirrel.cpp
+++ b/NorthstarDLL/squirrel/squirrel.cpp
@@ -190,11 +190,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;
@@ -472,7 +472,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;
@@ -499,7 +499,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 e0192d69..0b4593de 100644
--- a/NorthstarDLL/util/printmaps.cpp
+++ b/NorthstarDLL/util/printmaps.cpp
@@ -37,7 +37,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