diff options
author | BobTheBob <32057864+BobTheBob9@users.noreply.github.com> | 2021-07-23 02:32:18 +0100 |
---|---|---|
committer | BobTheBob <32057864+BobTheBob9@users.noreply.github.com> | 2021-07-23 02:32:18 +0100 |
commit | 23a1dafcde70822a9899e9aab190f36521c1aedd (patch) | |
tree | 58292b4d3abfa22742c9d8e8fcff208c9c6b2475 | |
parent | 8564c36b49f5f0451be5036371e421a44425b02e (diff) | |
download | NorthstarLauncher-23a1dafcde70822a9899e9aab190f36521c1aedd.tar.gz NorthstarLauncher-23a1dafcde70822a9899e9aab190f36521c1aedd.zip |
add basic vpk file replacement
-rw-r--r-- | NorthstarDedicatedTest/convar.cpp | 1 | ||||
-rw-r--r-- | NorthstarDedicatedTest/convar.h | 8 | ||||
-rw-r--r-- | NorthstarDedicatedTest/dedicated.cpp | 6 | ||||
-rw-r--r-- | NorthstarDedicatedTest/dllmain.cpp | 3 | ||||
-rw-r--r-- | NorthstarDedicatedTest/filesystem.cpp | 26 | ||||
-rw-r--r-- | NorthstarDedicatedTest/modmanager.cpp | 34 | ||||
-rw-r--r-- | NorthstarDedicatedTest/modmanager.h | 25 | ||||
-rw-r--r-- | NorthstarDedicatedTest/squirrel.cpp | 4 |
8 files changed, 80 insertions, 27 deletions
diff --git a/NorthstarDedicatedTest/convar.cpp b/NorthstarDedicatedTest/convar.cpp index ca5d8ef3..3bb95a95 100644 --- a/NorthstarDedicatedTest/convar.cpp +++ b/NorthstarDedicatedTest/convar.cpp @@ -2,6 +2,7 @@ #include "convar.h" #include <set> +// should this be in modmanager? std::set<std::string> g_CustomConvars; // this is used in modloading code to determine whether we've registered a mod convar already typedef void(*ConVarConstructorType)(ConVar* newVar, const char* name, const char* defaultValue, int flags, const char* helpString); diff --git a/NorthstarDedicatedTest/convar.h b/NorthstarDedicatedTest/convar.h index 014cb823..2c1e21a9 100644 --- a/NorthstarDedicatedTest/convar.h +++ b/NorthstarDedicatedTest/convar.h @@ -66,7 +66,13 @@ class ConVar { private: // if there are ever crashes caused by modifying custom cvars, check this - unsigned char unknown[0x88]; + unsigned char unknown[0x58]; + char* m_pszString; + int64_t m_StringLength; + float m_fValue; + int32_t m_nValue; + unsigned char unknown2[0x10]; + public: virtual void EngineDestructor(void) {} virtual bool IsCommand(void) const { return false; } diff --git a/NorthstarDedicatedTest/dedicated.cpp b/NorthstarDedicatedTest/dedicated.cpp index d526fb1b..80ab4002 100644 --- a/NorthstarDedicatedTest/dedicated.cpp +++ b/NorthstarDedicatedTest/dedicated.cpp @@ -81,7 +81,7 @@ void InitialiseDedicated(HMODULE engineAddress) *ptr = (intptr_t)doublePtr; // extra potential patches: - // nop engine.dll+1c67cd1 and +1c67d8 to skip videomode creategamewindow + // nop engine.dll+1c67d1 and +1c67d8 to skip videomode creategamewindow // also look into launcher.dll+d381, seems to cause renderthread to get made // this crashes HARD if no window which makes sense tbh // also look into materialsystem + 5B344 since it seems to be the base of all the renderthread stuff @@ -108,8 +108,8 @@ void RunServer(CDedicatedExports* dedicated) Sys_Printf(dedicated, (char*)"CDedicatedServerAPI::RunServer(): map mp_lobby"); // allow us to hit CHostState::FrameUpdate - *((int*)((char*)cEnginePtr + 12)) = 2; - *((int*)((char*)cEnginePtr + 16)) = 2; + //*((int*)((char*)cEnginePtr + 12)) = 2; + //*((int*)((char*)cEnginePtr + 16)) = 2; while (true) { diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp index 70462e34..303afcfc 100644 --- a/NorthstarDedicatedTest/dllmain.cpp +++ b/NorthstarDedicatedTest/dllmain.cpp @@ -38,6 +38,7 @@ BOOL APIENTRY DllMain( HMODULE hModule, void InitialiseNorthstar() { InitialiseLogging(); + // apply initial hooks InstallInitialHooks(); InitialiseInterfaceCreationHooks(); @@ -58,6 +59,6 @@ void InitialiseNorthstar() AddDllLoadCallback("filesystem_stdio.dll", InitialiseFilesystem); - // do this after all the other callbacks + // mod manager after everything else AddDllLoadCallback("engine.dll", InitialiseModManager); }
\ No newline at end of file diff --git a/NorthstarDedicatedTest/filesystem.cpp b/NorthstarDedicatedTest/filesystem.cpp index 135201b6..877898ee 100644 --- a/NorthstarDedicatedTest/filesystem.cpp +++ b/NorthstarDedicatedTest/filesystem.cpp @@ -3,6 +3,9 @@ #include "hooks.h" #include "hookutils.h" #include "sourceinterface.h" +#include "modmanager.h" + +#include <iostream> // hook forward declares typedef FileHandle_t(*ReadFileFromVPKType)(VPKData* vpkInfo, __int64* b, const char* filename); @@ -25,8 +28,25 @@ void InitialiseFilesystem(HMODULE baseAddress) ENABLER_CREATEHOOK(hook, (*g_Filesystem)->m_vtable->ReadFromCache, &ReadFromCacheHook, reinterpret_cast<LPVOID*>(&readFromCache)); } -bool ShouldReplaceFile(const char* path) +void SetNewModSearchPaths(Mod* mod) +{ + // put our new path to the head + // in future we should look into manipulating paths at head manually, might be effort tho + (*g_Filesystem)->m_vtable->AddSearchPath(&*(*g_Filesystem), (fs::absolute(mod->ModDirectory) / "mod").string().c_str(), "GAME", PATH_ADD_TO_HEAD); +} + +bool TryReplaceFile(const char* path) { + // is this efficient? no clue + for (ModOverrideFile* modFile : g_ModManager->m_modFiles) + { + if (!modFile->path.compare(fs::path(path).lexically_normal())) + { + SetNewModSearchPaths(modFile->owningMod); + return true; + } + } + return false; } @@ -34,7 +54,7 @@ FileHandle_t ReadFileFromVPKHook(VPKData* vpkInfo, __int64* b, const char* filen { // move this to a convar at some point when we can read them in native //spdlog::info("ReadFileFromVPKHook {} {}", filename, vpkInfo->path); - if (ShouldReplaceFile(filename)) + if (TryReplaceFile(filename)) { *b = -1; return b; @@ -48,6 +68,8 @@ bool ReadFromCacheHook(IFileSystem* filesystem, const char* path, void* result) // move this to a convar at some point when we can read them in native //spdlog::info("ReadFromCacheHook {}", path); + if (TryReplaceFile(path)) + return false; return readFromCache(filesystem, path, result); }
\ No newline at end of file diff --git a/NorthstarDedicatedTest/modmanager.cpp b/NorthstarDedicatedTest/modmanager.cpp index c85c17c8..14182017 100644 --- a/NorthstarDedicatedTest/modmanager.cpp +++ b/NorthstarDedicatedTest/modmanager.cpp @@ -16,6 +16,8 @@ Mod::Mod(fs::path modDir, char* jsonBuf) { wasReadSuccessfully = false; + ModDirectory = modDir; + rapidjson::Document modJson; modJson.Parse<rapidjson::ParseFlag::kParseCommentsFlag | rapidjson::ParseFlag::kParseTrailingCommasFlag>(jsonBuf); @@ -200,7 +202,7 @@ void ModManager::LoadMods() if (mod->wasReadSuccessfully) { spdlog::info("Loaded mod {} successfully", mod->Name); - loadedMods.push_back(mod); + m_loadedMods.push_back(mod); } else { @@ -209,22 +211,38 @@ void ModManager::LoadMods() } } - for (Mod* mod : loadedMods) + // do we need to dealloc individual entries in m_modFiles? idk, rework + m_modFiles.clear(); + + for (Mod* mod : m_loadedMods) { + // 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 - // potentially it might also be good to unregister convars when they get removed on a reload, but unsure if necessary + // potentially it might also be good to unregister convars if they get removed on a reload, but unsure if necessary for (ModConVar* convar : mod->ConVars) if (g_CustomConvars.find(convar->Name) == g_CustomConvars.end()) // make sure convar isn't registered yet, unsure if necessary but idk what behaviour is for defining same convar multiple times RegisterConVar(convar->Name.c_str(), convar->DefaultValue.c_str(), convar->Flags, convar->HelpString.c_str()); + + + // register mod files + if (fs::exists(mod->ModDirectory / "mod")) + { + for (fs::directory_entry file : fs::recursive_directory_iterator(mod->ModDirectory / "mod")) + { + if (file.is_regular_file()) + { + // super temp because it relies hard on load order + ModOverrideFile* modFile = new ModOverrideFile; + modFile->owningMod = mod; + modFile->path = file.path().lexically_relative(mod->ModDirectory / "mod").lexically_normal(); + m_modFiles.push_back(modFile); + } + } + } } } -std::vector<Mod*> ModManager::GetMods() -{ - return loadedMods; -} - void InitialiseModManager(HMODULE baseAddress) { g_ModManager = new ModManager(); diff --git a/NorthstarDedicatedTest/modmanager.h b/NorthstarDedicatedTest/modmanager.h index c5ddb09f..60e51308 100644 --- a/NorthstarDedicatedTest/modmanager.h +++ b/NorthstarDedicatedTest/modmanager.h @@ -7,7 +7,7 @@ namespace fs = std::filesystem; const fs::path MOD_FOLDER_PATH = "R2Northstar/mods"; -class ModConVar +struct ModConVar { public: std::string Name; @@ -16,7 +16,7 @@ public: int Flags; }; -class ModScriptCallback +struct ModScriptCallback { public: // would've liked to make it possible to hook arbitrary codecallbacks, but couldn't find a function that calls some ui ones @@ -30,7 +30,7 @@ public: std::string AfterCallback; }; -class ModScript +struct ModScript { public: std::string Path; @@ -42,6 +42,8 @@ public: class Mod { public: + fs::path ModDirectory; + // mod.json stuff: // the mod's name @@ -74,19 +76,22 @@ public: Mod(fs::path modPath, char* jsonBuf); }; +struct ModOverrideFile +{ +public: + Mod* owningMod; + fs::path path; +}; + class ModManager { -private: - std::vector<Mod*> loadedMods; +public: + std::vector<Mod*> m_loadedMods; + std::vector<ModOverrideFile*> m_modFiles; public: ModManager(); void LoadMods(); - - std::vector<Mod*> GetMods(); - std::vector<Mod*> GetClientMods(); - std::vector<std::string> GetModVpks(); - std::vector<std::string> GetModOverridePaths(); }; void InitialiseModManager(HMODULE baseAddress); diff --git a/NorthstarDedicatedTest/squirrel.cpp b/NorthstarDedicatedTest/squirrel.cpp index 43a45779..4eae96a4 100644 --- a/NorthstarDedicatedTest/squirrel.cpp +++ b/NorthstarDedicatedTest/squirrel.cpp @@ -201,7 +201,7 @@ template<Context context> char CallScriptInitCallbackHook(void* sqvm, const char // run before callbacks if (shouldCallCustomCallbacks) { - for (Mod* mod : g_ModManager->GetMods()) + for (Mod* mod : g_ModManager->m_loadedMods) { for (ModScript* script : mod->Scripts) { @@ -225,7 +225,7 @@ template<Context context> char CallScriptInitCallbackHook(void* sqvm, const char // run after callbacks if (shouldCallCustomCallbacks) { - for (Mod* mod : g_ModManager->GetMods()) + for (Mod* mod : g_ModManager->m_loadedMods) { for (ModScript* script : mod->Scripts) { |