diff options
author | BobTheBob <32057864+BobTheBob9@users.noreply.github.com> | 2022-10-17 23:26:07 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-17 23:26:07 +0100 |
commit | 841881af9ea6ec73b1d505d5a8f7c1f766273724 (patch) | |
tree | 91feb40fe810984b59d2d2da440e289370b0a137 /NorthstarDLL/modmanager.cpp | |
parent | dc0934d29caacc8da1e7df8b775d24b4e99c381c (diff) | |
download | NorthstarLauncher-841881af9ea6ec73b1d505d5a8f7c1f766273724.tar.gz NorthstarLauncher-841881af9ea6ec73b1d505d5a8f7c1f766273724.zip |
big refactor (#171)v1.10.0-rc1
* use in-file macros rather than global funcs for registering dll load callbacks
* move more things to macros
* fix debug crashes
* move sqvm funcs to sq managers
* get rid of context file
* refactor some squirrel stuff and ingame compilation error message
* move tier0 and playlist funcs to namespaces
* uiscript_reset concommand: don't loop forever if compilation fails
* improve showing console for ui script compile errors
* standardise concommand func naming in c++
* use lambdas for dll load callbacks so intellisense shits itself less
* use cvar change callbacks for unescaping ns_server_name and ns_server_desc
* add proper helpstrings to masterserver cvars
* add cvar help and find
* allow parsing of convar flags from string
* normalise mod fs paths to be lowercase
* move hoststate to its own file and add host_init hooks
* better IsFlagSet def
* replace files in ReadFromCache
* rename g_ModManager to g_pModManager
* formatting changes
* make cvar print work on dedi, move demo fix stuff, add findflags
* add proper map autocompletes and maps command
* formatting changes
* separate gameutils into multiple r2 headers
* Update keyvalues.cpp
* move sqvm funcs into wrappers in the manager class
* remove unnecessary header files
* lots of cleanup and starting moving to new hooking macros
* update more stuff to new hook macros
* rename project folder (:tf: commit log)
* fix up postbuild commands to use relative dir
* almost fully replaced hooking lib
* completely remove old hooking
* add nsprefix because i forgot to include it
* move exploit prevention and limits code out of serverauthentication, and have actual defs for CBasePlayer
* use modular ServerPresence system for registering servers
* add new memory lib
* accidentally pushed broke code oops
* lots of stuff idk
* implement some more prs
* improve rpakfilesystem
* fix line endings on vcxproj
* Revert "fix line endings on vcxproj"
This reverts commit 4ff7d022d2602c2dba37beba8b8df735cf5cd7d9.
* add more prs
* i swear i committed these how are they not there
* Add ability to load Datatables from files (#238)
* first version of kinda working custom datatables
* Fix copy error
* Finish custom datatables
* Fix Merge
* Fix line endings
* Add fallback to rpak when ns_prefere_datatable_from_disk is true
* fix typo
* Bug fixess
* Fix Function Registration hook
* Set convar value
* Fix Client and Ui VM
* enable server auth with ms agian
* Add Filters
* FIx unused import
* Merge remote-tracking branch 'upsteam/bobs-big-refactor-pr' into datatables
Co-authored-by: RoyalBlue1 <realEmail@veryRealURL.com>
* Add some changes from main to refactor (#243)
* Add PR template
* Update CI folder location
* Delete startup args txt files
* Fix line endings (hopefully) (#244)
* Fix line endings (hopefully)
* Fix more line endings
* Update refactor (#250)
* Add PR template
* Update CI folder location
* Delete startup args txt files
* Add editorconfig file (#246)
* Add editorconfig file
It's a cross-editor compatible config file that defines certain editor
behaviour (e.g. adding/removing newline at end of file)
It is supported by major editors like Visual Studio (Code) and by
version control providers like GitHub.
Should end the constant adding/removing of final newline in PRs
* More settings
- unicode by default
- trim newlines
- use tabs for indentation (ugh)
* Ignore folder rename (#245)
* Hot reload banlist on player join (#233)
* added banlist hotreload
* fix formatting
* didnt append, cleared whole file oopsie
* unfuckedunban not rewriting file
* fixed not checking for new line
Co-authored-by: ScureX <47725553+ScureX@users.noreply.github.com>
* Refactor cleanup (#256)
* Fix indentation
* Fix path in clang-format command in readme
* Refactor cleanup (some formatting fixes) (#257)
* Fix some formatting
* More formatting fixes
* add scriptdatatable.cpp rewrite
* Some formatting fixes (#260)
* More formatting stuff (#261)
* various formatting changes and fixes
* Fix changed icon (#264)
* clang format, fix issues with server registration and rpak loading
* fix more formatting
* update postbuild step
* set launcher directory and error on fail creating log files
* change some stuff in exploitfixes
* only unrestrict dev commands when commandline flag is present
* fix issues with cvar flag commit
* fixup command flags better and reformat
* bring up to date with main
* fixup formatting
* improve cvar flag fixup and remove temp thing from findflags
* set serverfilter better
* avoid ptr decay when setting auth token
* add more entity functions
* Fix the MS server registration issues. (#285)
* Port ms presence reporter to std::async
* Fix crash due to std::optional being assigned nullptr.
* Fix formatting.
* Wait 20 seconds if MS returns DUPLICATE_SERVER.
* Change PERSISTENCE_MAX_SIZE to fix player authentication (#287)
The size check added in the refactor was incorrect:
- 56306: expected pdata size based on the pdef
- 512: allowance for trailing junk (r2 adds 137 bytes of trailing junk)
- 100: for some wiggle room
Co-Authored-By: pg9182 <96569817+pg9182@users.noreply.github.com>
* change miscserverscript to use actual entity arguments rather than
player index jank
* Fix token clearing hook (#290)
A certain someone forgot to put an `0x` in front of their hex number, meaning the offset is wrong.
This would cause token to be leaked again
Co-authored-by: Maya <malte.hoermeyer@web.de>
Co-authored-by: RoyalBlue1 <realEmail@veryRealURL.com>
Co-authored-by: GeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com>
Co-authored-by: ScureX <47725553+ScureX@users.noreply.github.com>
Co-authored-by: Erlite <ys.aameziane@gmail.com>
Co-authored-by: Emma Miler <emma.pi@protonmail.com>
Co-authored-by: pg9182 <96569817+pg9182@users.noreply.github.com>
Diffstat (limited to 'NorthstarDLL/modmanager.cpp')
-rw-r--r-- | NorthstarDLL/modmanager.cpp | 236 |
1 files changed, 146 insertions, 90 deletions
diff --git a/NorthstarDLL/modmanager.cpp b/NorthstarDLL/modmanager.cpp index 2223109f..05060902 100644 --- a/NorthstarDLL/modmanager.cpp +++ b/NorthstarDLL/modmanager.cpp @@ -4,6 +4,10 @@ #include "concommand.h" #include "audio.h" #include "masterserver.h" +#include "filesystem.h" +#include "rpakfilesystem.h" +#include "nsprefix.h" + #include "rapidjson/error/en.h" #include "rapidjson/document.h" #include "rapidjson/ostreamwrapper.h" @@ -13,17 +17,14 @@ #include <string> #include <sstream> #include <vector> -#include "filesystem.h" -#include "rpakfilesystem.h" -#include "nsprefix.h" -ModManager* g_ModManager; +ModManager* g_pModManager; Mod::Mod(fs::path modDir, char* jsonBuf) { - wasReadSuccessfully = false; + m_bWasReadSuccessfully = false; - ModDirectory = modDir; + m_ModDirectory = modDir; rapidjson_document modJson; modJson.Parse<rapidjson::ParseFlag::kParseCommentsFlag | rapidjson::ParseFlag::kParseTrailingCommasFlag>(jsonBuf); @@ -106,11 +107,55 @@ Mod::Mod(fs::path modDir, char* jsonBuf) else convar->HelpString = ""; - // todo: could possibly parse FCVAR names here instead, would be easier + convar->Flags = FCVAR_NONE; + if (convarObj.HasMember("Flags")) - convar->Flags = convarObj["Flags"].GetInt(); - else - convar->Flags = FCVAR_NONE; + { + // read raw integer flags + if (convarObj["Flags"].IsInt()) + convar->Flags = convarObj["Flags"].GetInt(); + else if (convarObj["Flags"].IsString()) + { + // parse cvar flags from string + // example string: ARCHIVE_PLAYERPROFILE | GAMEDLL + + std::string sFlags = convarObj["Flags"].GetString(); + sFlags += '|'; // add additional | so we register the last flag + std::string sCurrentFlag; + + for (int i = 0; i < sFlags.length(); i++) + { + if (isspace(sFlags[i])) + continue; + + // if we encounter a |, add current string as a flag + if (sFlags[i] == '|') + { + bool bHasFlags = false; + int iCurrentFlags; + + for (auto& flagPair : g_PrintCommandFlags) + { + if (!sCurrentFlag.compare(flagPair.second)) + { + iCurrentFlags = flagPair.first; + bHasFlags = true; + break; + } + } + + if (bHasFlags) + convar->Flags |= iCurrentFlags; + else + spdlog::warn("Mod ConVar {} has unknown flag {}", convar->Name, sCurrentFlag); + + sCurrentFlag = ""; + } + else + sCurrentFlag += sFlags[i]; + } + } + } ConVars.push_back(convar); } @@ -127,7 +172,7 @@ Mod::Mod(fs::path modDir, char* jsonBuf) ModScript script; script.Path = scriptObj["Path"].GetString(); - script.RsonRunOn = scriptObj["RunOn"].GetString(); + script.RunOn = scriptObj["RunOn"].GetString(); if (scriptObj.HasMember("ServerCallback") && scriptObj["ServerCallback"].IsObject()) { @@ -206,7 +251,7 @@ Mod::Mod(fs::path modDir, char* jsonBuf) } } - wasReadSuccessfully = true; + m_bWasReadSuccessfully = true; } ModManager::ModManager() @@ -223,7 +268,7 @@ ModManager::ModManager() void ModManager::LoadMods() { - if (m_hasLoadedMods) + if (m_bHasLoadedMods) UnloadMods(); std::vector<fs::path> modDirs; @@ -232,7 +277,7 @@ void ModManager::LoadMods() fs::remove_all(GetCompiledAssetsPath()); fs::create_directories(GetModFolderPath()); - DependencyConstants.clear(); + m_DependencyConstants.clear(); // read enabled mods cfg std::ifstream enabledModsStream(GetNorthstarPrefix() + "/enabledmods.json"); @@ -244,10 +289,10 @@ void ModManager::LoadMods() enabledModsStringStream << (char)enabledModsStream.get(); enabledModsStream.close(); - m_enabledModsCfg.Parse<rapidjson::ParseFlag::kParseCommentsFlag | rapidjson::ParseFlag::kParseTrailingCommasFlag>( + m_EnabledModsCfg.Parse<rapidjson::ParseFlag::kParseCommentsFlag | rapidjson::ParseFlag::kParseTrailingCommasFlag>( enabledModsStringStream.str().c_str()); - m_hasEnabledModsCfg = m_enabledModsCfg.IsObject(); + m_bHasEnabledModsCfg = m_EnabledModsCfg.IsObject(); } // get mod directories @@ -277,41 +322,41 @@ void ModManager::LoadMods() for (auto& pair : mod.DependencyConstants) { - if (DependencyConstants.find(pair.first) != DependencyConstants.end() && DependencyConstants[pair.first] != pair.second) + if (m_DependencyConstants.find(pair.first) != m_DependencyConstants.end() && m_DependencyConstants[pair.first] != pair.second) { spdlog::error("Constant {} in mod {} already exists in another mod.", pair.first, mod.Name); - mod.wasReadSuccessfully = false; + mod.m_bWasReadSuccessfully = false; break; } - if (DependencyConstants.find(pair.first) == DependencyConstants.end()) - DependencyConstants.emplace(pair); + if (m_DependencyConstants.find(pair.first) == m_DependencyConstants.end()) + m_DependencyConstants.emplace(pair); } - if (m_hasEnabledModsCfg && m_enabledModsCfg.HasMember(mod.Name.c_str())) - mod.Enabled = m_enabledModsCfg[mod.Name.c_str()].IsTrue(); + if (m_bHasEnabledModsCfg && m_EnabledModsCfg.HasMember(mod.Name.c_str())) + mod.m_bEnabled = m_EnabledModsCfg[mod.Name.c_str()].IsTrue(); else - mod.Enabled = true; + mod.m_bEnabled = true; - if (mod.wasReadSuccessfully) + if (mod.m_bWasReadSuccessfully) { spdlog::info("Loaded mod {} successfully", mod.Name); - if (mod.Enabled) + if (mod.m_bEnabled) spdlog::info("Mod {} is enabled", mod.Name); else spdlog::info("Mod {} is disabled", mod.Name); - m_loadedMods.push_back(mod); + m_LoadedMods.push_back(mod); } else spdlog::warn("Skipping loading mod file {}", (modDir / "mod.json").string()); } // 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_LoadedMods.begin(), m_LoadedMods.end(), [](Mod& a, Mod& b) { return a.LoadPriority < b.LoadPriority; }); - for (Mod& mod : m_loadedMods) + for (Mod& mod : m_LoadedMods) { - if (!mod.Enabled) + if (!mod.m_bEnabled) continue; // register convars @@ -319,15 +364,15 @@ void ModManager::LoadMods() // 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) - if (!g_pCVar->FindVar(convar->Name.c_str())) // 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())) // make sure convar isn't registered yet, unsure if necessary but idk what + // behaviour is for defining same convar multiple times new ConVar(convar->Name.c_str(), convar->DefaultValue.c_str(), convar->Flags, convar->HelpString.c_str()); // read vpk paths - if (fs::exists(mod.ModDirectory / "vpk")) + if (fs::exists(mod.m_ModDirectory / "vpk")) { // read vpk cfg - std::ifstream vpkJsonStream(mod.ModDirectory / "vpk/vpk.json"); + std::ifstream vpkJsonStream(mod.m_ModDirectory / "vpk/vpk.json"); std::stringstream vpkJsonStringStream; bool bUseVPKJson = false; @@ -345,7 +390,7 @@ void ModManager::LoadMods() bUseVPKJson = !dVpkJson.HasParseError() && dVpkJson.IsObject(); } - for (fs::directory_entry file : fs::directory_iterator(mod.ModDirectory / "vpk")) + for (fs::directory_entry file : fs::directory_iterator(mod.m_ModDirectory / "vpk")) { // a bunch of checks to make sure we're only adding dir vpks and their paths are good // note: the game will literally only load vpks with the english prefix @@ -356,25 +401,24 @@ void ModManager::LoadMods() std::string formattedPath = file.path().filename().string(); // this really fucking sucks but it'll work - std::string vpkName = - (file.path().parent_path() / formattedPath.substr(strlen("english"), formattedPath.find(".bsp") - 3)).string(); + std::string vpkName = formattedPath.substr(strlen("english"), formattedPath.find(".bsp") - 3); ModVPKEntry& modVpk = mod.Vpks.emplace_back(); modVpk.m_bAutoLoad = !bUseVPKJson || (dVpkJson.HasMember("Preload") && dVpkJson["Preload"].IsObject() && dVpkJson["Preload"].HasMember(vpkName) && dVpkJson["Preload"][vpkName].IsTrue()); - modVpk.m_sVpkPath = vpkName; + modVpk.m_sVpkPath = (file.path().parent_path() / vpkName).string(); - if (m_hasLoadedMods && modVpk.m_bAutoLoad) - (*g_Filesystem)->m_vtable->MountVPK(*g_Filesystem, vpkName.c_str()); + if (m_bHasLoadedMods && modVpk.m_bAutoLoad) + (*R2::g_pFilesystem)->m_vtable->MountVPK(*R2::g_pFilesystem, vpkName.c_str()); } } } // read rpak paths - if (fs::exists(mod.ModDirectory / "paks")) + if (fs::exists(mod.m_ModDirectory / "paks")) { // read rpak cfg - std::ifstream rpakJsonStream(mod.ModDirectory / "paks/rpak.json"); + std::ifstream rpakJsonStream(mod.m_ModDirectory / "paks/rpak.json"); std::stringstream rpakJsonStringStream; bool bUseRpakJson = false; @@ -406,7 +450,7 @@ void ModManager::LoadMods() } } - for (fs::directory_entry file : fs::directory_iterator(mod.ModDirectory / "paks")) + for (fs::directory_entry file : fs::directory_iterator(mod.m_ModDirectory / "paks")) { // ensure we're only loading rpaks if (fs::is_regular_file(file) && file.path().extension() == ".rpak") @@ -417,39 +461,39 @@ void ModManager::LoadMods() modPak.m_bAutoLoad = !bUseRpakJson || (dRpakJson.HasMember("Preload") && dRpakJson["Preload"].IsObject() && dRpakJson["Preload"].HasMember(pakName) && dRpakJson["Preload"][pakName].IsTrue()); + // postload things if (!bUseRpakJson || (dRpakJson.HasMember("Postload") && dRpakJson["Postload"].IsObject() && dRpakJson["Postload"].HasMember(pakName))) - { modPak.m_sLoadAfterPak = dRpakJson["Postload"][pakName].GetString(); - } modPak.m_sPakName = pakName; // not using atm because we need to resolve path to rpak // if (m_hasLoadedMods && modPak.m_bAutoLoad) - // g_PakLoadManager->LoadPakAsync(pakName.c_str()); + // g_pPakLoadManager->LoadPakAsync(pakName.c_str()); } } } // read keyvalues paths - if (fs::exists(mod.ModDirectory / "keyvalues")) + if (fs::exists(mod.m_ModDirectory / "keyvalues")) { - for (fs::directory_entry file : fs::recursive_directory_iterator(mod.ModDirectory / "keyvalues")) + for (fs::directory_entry file : fs::recursive_directory_iterator(mod.m_ModDirectory / "keyvalues")) { if (fs::is_regular_file(file)) { - std::string kvStr = file.path().lexically_relative(mod.ModDirectory / "keyvalues").lexically_normal().string(); + std::string kvStr = + g_pModManager->NormaliseModFilePath(file.path().lexically_relative(mod.m_ModDirectory / "keyvalues")); mod.KeyValues.emplace(STR_HASH(kvStr), kvStr); } } } // read pdiff - if (fs::exists(mod.ModDirectory / "mod.pdiff")) + if (fs::exists(mod.m_ModDirectory / "mod.pdiff")) { - std::ifstream pdiffStream(mod.ModDirectory / "mod.pdiff"); + std::ifstream pdiffStream(mod.m_ModDirectory / "mod.pdiff"); if (!pdiffStream.fail()) { @@ -464,17 +508,17 @@ void ModManager::LoadMods() } // read bink video paths - if (fs::exists(mod.ModDirectory / "media")) + if (fs::exists(mod.m_ModDirectory / "media")) { - for (fs::directory_entry file : fs::recursive_directory_iterator(mod.ModDirectory / "media")) + for (fs::directory_entry file : fs::recursive_directory_iterator(mod.m_ModDirectory / "media")) if (fs::is_regular_file(file) && file.path().extension() == ".bik") mod.BinkVideos.push_back(file.path().filename().string()); } // try to load audio - if (fs::exists(mod.ModDirectory / "audio")) + if (fs::exists(mod.m_ModDirectory / "audio")) { - for (fs::directory_entry file : fs::directory_iterator(mod.ModDirectory / "audio")) + for (fs::directory_entry file : fs::directory_iterator(mod.m_ModDirectory / "audio")) { if (fs::is_regular_file(file) && file.path().extension().string() == ".json") { @@ -489,23 +533,23 @@ void ModManager::LoadMods() } // in a seperate loop because we register mod files in reverse order, since mods loaded later should have their files prioritised - for (int64_t i = m_loadedMods.size() - 1; i > -1; i--) + for (int64_t i = m_LoadedMods.size() - 1; i > -1; i--) { - if (!m_loadedMods[i].Enabled) + if (!m_LoadedMods[i].m_bEnabled) continue; - if (fs::exists(m_loadedMods[i].ModDirectory / MOD_OVERRIDE_DIR)) + if (fs::exists(m_LoadedMods[i].m_ModDirectory / MOD_OVERRIDE_DIR)) { - for (fs::directory_entry file : fs::recursive_directory_iterator(m_loadedMods[i].ModDirectory / MOD_OVERRIDE_DIR)) + for (fs::directory_entry file : fs::recursive_directory_iterator(m_LoadedMods[i].m_ModDirectory / MOD_OVERRIDE_DIR)) { - fs::path path = file.path().lexically_relative(m_loadedMods[i].ModDirectory / MOD_OVERRIDE_DIR).lexically_normal(); - - if (file.is_regular_file() && m_modFiles.find(path.string()) == m_modFiles.end()) + std::string path = + g_pModManager->NormaliseModFilePath(file.path().lexically_relative(m_LoadedMods[i].m_ModDirectory / MOD_OVERRIDE_DIR)); + if (file.is_regular_file() && m_ModFiles.find(path) == m_ModFiles.end()) { ModOverrideFile modFile; - modFile.owningMod = &m_loadedMods[i]; - modFile.path = path; - m_modFiles.insert(std::make_pair(path.string(), modFile)); + modFile.m_pOwningMod = &m_LoadedMods[i]; + modFile.m_Path = path; + m_ModFiles.insert(std::make_pair(path, modFile)); } } } @@ -517,9 +561,9 @@ void ModManager::LoadMods() modinfoDoc.AddMember("Mods", rapidjson_document::GenericValue(rapidjson::kArrayType), modinfoDoc.GetAllocator()); int currentModIndex = 0; - for (Mod& mod : m_loadedMods) + for (Mod& mod : m_LoadedMods) { - if (!mod.Enabled || (!mod.RequiredOnClient && !mod.Pdiff.size())) + if (!mod.m_bEnabled || (!mod.RequiredOnClient && !mod.Pdiff.size())) continue; modinfoDoc["Mods"].PushBack(rapidjson_document::GenericValue(rapidjson::kObjectType), modinfoDoc.GetAllocator()); @@ -535,27 +579,27 @@ void ModManager::LoadMods() buffer.Clear(); rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); modinfoDoc.Accept(writer); - g_MasterServerManager->m_sOwnModInfoJson = std::string(buffer.GetString()); + g_pMasterServerManager->m_sOwnModInfoJson = std::string(buffer.GetString()); - m_hasLoadedMods = true; + m_bHasLoadedMods = true; } void ModManager::UnloadMods() { // clean up stuff from mods before we unload - m_modFiles.clear(); + m_ModFiles.clear(); fs::remove_all(GetCompiledAssetsPath()); g_CustomAudioManager.ClearAudioOverrides(); - if (!m_hasEnabledModsCfg) - m_enabledModsCfg.SetObject(); + if (!m_bHasEnabledModsCfg) + m_EnabledModsCfg.SetObject(); - for (Mod& mod : m_loadedMods) + for (Mod& mod : m_LoadedMods) { // remove all built kvs for (std::pair<size_t, std::string> kvPaths : mod.KeyValues) - fs::remove(GetCompiledAssetsPath() / fs::path(kvPaths.second).lexically_relative(mod.ModDirectory)); + fs::remove(GetCompiledAssetsPath() / fs::path(kvPaths.second).lexically_relative(mod.m_ModDirectory)); mod.KeyValues.clear(); @@ -563,27 +607,39 @@ void ModManager::UnloadMods() // 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 // what we wanna do - if (!m_enabledModsCfg.HasMember(mod.Name.c_str())) - m_enabledModsCfg.AddMember( + if (!m_EnabledModsCfg.HasMember(mod.Name.c_str())) + m_EnabledModsCfg.AddMember( rapidjson_document::StringRefType(mod.Name.c_str()), rapidjson_document::GenericValue(false), - m_enabledModsCfg.GetAllocator()); + m_EnabledModsCfg.GetAllocator()); - m_enabledModsCfg[mod.Name.c_str()].SetBool(mod.Enabled); + m_EnabledModsCfg[mod.Name.c_str()].SetBool(mod.m_bEnabled); } std::ofstream writeStream(GetNorthstarPrefix() + "/enabledmods.json"); rapidjson::OStreamWrapper writeStreamWrapper(writeStream); rapidjson::Writer<rapidjson::OStreamWrapper> writer(writeStreamWrapper); - m_enabledModsCfg.Accept(writer); + m_EnabledModsCfg.Accept(writer); // do we need to dealloc individual entries in m_loadedMods? idk, rework - m_loadedMods.clear(); + m_LoadedMods.clear(); +} + +std::string ModManager::NormaliseModFilePath(const fs::path path) +{ + std::string str = path.lexically_normal().string(); + + // force to lowercase + for (char& c : str) + if (c <= 'Z' && c >= 'A') + c = c - ('Z' - 'z'); + + return str; } void ModManager::CompileAssetsForFile(const char* filename) { - size_t fileHash = STR_HASH(fs::path(filename).lexically_normal().string()); + size_t fileHash = STR_HASH(NormaliseModFilePath(fs::path(filename))); if (fileHash == m_hScriptsRsonHash) BuildScriptsRson(); @@ -592,9 +648,9 @@ void ModManager::CompileAssetsForFile(const char* filename) 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 : m_LoadedMods) { - if (!mod.Enabled) + if (!mod.m_bEnabled) continue; if (mod.KeyValues.find(fileHash) != mod.KeyValues.end()) @@ -608,14 +664,7 @@ void ModManager::CompileAssetsForFile(const char* filename) void ConCommand_reload_mods(const CCommand& args) { - g_ModManager->LoadMods(); -} - -void InitialiseModManager(HMODULE baseAddress) -{ - g_ModManager = new ModManager; - - RegisterConCommand("reload_mods", ConCommand_reload_mods, "reloads mods", FCVAR_NONE); + g_pModManager->LoadMods(); } fs::path GetModFolderPath() @@ -626,3 +675,10 @@ fs::path GetCompiledAssetsPath() { return fs::path(GetNorthstarPrefix() + COMPILED_ASSETS_SUFFIX); } + +ON_DLL_LOAD_RELIESON("engine.dll", ModManager, (ConCommand, MasterServer), (CModule module)) +{ + g_pModManager = new ModManager; + + RegisterConCommand("reload_mods", ConCommand_reload_mods, "reloads mods", FCVAR_NONE); +} |