aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2021-07-23 02:32:18 +0100
committerBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2021-07-23 02:32:18 +0100
commit23a1dafcde70822a9899e9aab190f36521c1aedd (patch)
tree58292b4d3abfa22742c9d8e8fcff208c9c6b2475
parent8564c36b49f5f0451be5036371e421a44425b02e (diff)
downloadNorthstarLauncher-23a1dafcde70822a9899e9aab190f36521c1aedd.tar.gz
NorthstarLauncher-23a1dafcde70822a9899e9aab190f36521c1aedd.zip
add basic vpk file replacement
-rw-r--r--NorthstarDedicatedTest/convar.cpp1
-rw-r--r--NorthstarDedicatedTest/convar.h8
-rw-r--r--NorthstarDedicatedTest/dedicated.cpp6
-rw-r--r--NorthstarDedicatedTest/dllmain.cpp3
-rw-r--r--NorthstarDedicatedTest/filesystem.cpp26
-rw-r--r--NorthstarDedicatedTest/modmanager.cpp34
-rw-r--r--NorthstarDedicatedTest/modmanager.h25
-rw-r--r--NorthstarDedicatedTest/squirrel.cpp4
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)
{