diff options
-rw-r--r-- | LauncherInjector/ns_icon.ico | bin | 128581 -> 1441814 bytes | |||
-rw-r--r-- | NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj | 2 | ||||
-rw-r--r-- | NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters | 6 | ||||
-rw-r--r-- | NorthstarDedicatedTest/audio.cpp | 54 | ||||
-rw-r--r-- | NorthstarDedicatedTest/audio.h | 2 | ||||
-rw-r--r-- | NorthstarDedicatedTest/clientruihooks.cpp | 24 | ||||
-rw-r--r-- | NorthstarDedicatedTest/clientruihooks.h | 2 | ||||
-rw-r--r-- | NorthstarDedicatedTest/convar.h | 2 | ||||
-rw-r--r-- | NorthstarDedicatedTest/dedicated.cpp | 7 | ||||
-rw-r--r-- | NorthstarDedicatedTest/dllmain.cpp | 2 | ||||
-rw-r--r-- | NorthstarDedicatedTest/masterserver.cpp | 6 | ||||
-rw-r--r-- | NorthstarDedicatedTest/modmanager.cpp | 2 | ||||
-rw-r--r-- | NorthstarDedicatedTest/modmanager.h | 2 | ||||
-rw-r--r-- | NorthstarDedicatedTest/rpakfilesystem.cpp | 163 | ||||
-rw-r--r-- | NorthstarDedicatedTest/rpakfilesystem.h | 6 | ||||
-rw-r--r-- | NorthstarDedicatedTest/sourceconsole.cpp | 2 |
16 files changed, 245 insertions, 37 deletions
diff --git a/LauncherInjector/ns_icon.ico b/LauncherInjector/ns_icon.ico Binary files differindex ad7ded80..fc9ad166 100644 --- a/LauncherInjector/ns_icon.ico +++ b/LauncherInjector/ns_icon.ico diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj index 8c417112..4f7c0a9a 100644 --- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj +++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj @@ -118,6 +118,7 @@ <ClInclude Include="cl_rcon.pb.h" /> <ClInclude Include="host_state.h" /> <ClInclude Include="igameserverdata.h" /> + <ClInclude Include="clientruihooks.h" /> <ClInclude Include="clientvideooverrides.h" /> <ClInclude Include="localchatwriter.h" /> <ClInclude Include="plugins.h" /> @@ -588,6 +589,7 @@ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader> </ClCompile> + <ClCompile Include="clientruihooks.cpp" /> <ClCompile Include="clientvideooverrides.cpp" /> <ClCompile Include="concommand.cpp" /> <ClCompile Include="configurables.cpp" /> diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters index 67137947..bf8424e3 100644 --- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters +++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters @@ -1536,6 +1536,9 @@ <ClInclude Include="version.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="clientruihooks.h"> + <Filter>Header Files\Client</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="dllmain.cpp"> @@ -1727,6 +1730,9 @@ <ClCompile Include="version.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="clientruihooks.cpp"> + <Filter>Source Files\Client</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <MASM Include="audio_asm.asm"> diff --git a/NorthstarDedicatedTest/audio.cpp b/NorthstarDedicatedTest/audio.cpp index d3201b89..7a2ae711 100644 --- a/NorthstarDedicatedTest/audio.cpp +++ b/NorthstarDedicatedTest/audio.cpp @@ -25,6 +25,11 @@ EventOverrideData::EventOverrideData() LoadedSuccessfully = false; } +// Empty stereo 48000 WAVE file +unsigned char EMPTY_WAVE[45] = {0x52, 0x49, 0x46, 0x46, 0x25, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6D, 0x74, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x44, 0xAC, 0x00, 0x00, 0x88, 0x58, + 0x01, 0x00, 0x02, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x74, 0x00, 0x00, 0x00, 0x00}; + EventOverrideData::EventOverrideData(const std::string& data, const fs::path& path) { if (data.length() <= 0) @@ -184,8 +189,10 @@ EventOverrideData::EventOverrideData(const std::string& data, const fs::path& pa { if (file.is_regular_file() && file.path().extension().string() == ".wav") { + std::string pathString = file.path().string(); + // Open the file. - std::basic_ifstream<uint8_t> wavStream(file.path().string(), std::ios::binary); + std::basic_ifstream<uint8_t> wavStream(pathString, std::ios::binary); if (wavStream.fail()) { @@ -196,18 +203,40 @@ EventOverrideData::EventOverrideData(const std::string& data, const fs::path& pa // Get file size. wavStream.seekg(0, std::ios::end); size_t fileSize = wavStream.tellg(); - wavStream.seekg(0, std::ios::beg); + wavStream.close(); // Allocate enough memory for the file. + // blank out the memory for now, then read it later uint8_t* data = new uint8_t[fileSize]; - - // Read the file. - wavStream.read(data, fileSize); - + memcpy(data, EMPTY_WAVE, sizeof(EMPTY_WAVE)); Samples.push_back({fileSize, std::unique_ptr<uint8_t[]>(data)}); - // Close the file. - wavStream.close(); + // thread off the file read + // should we spawn one thread per read? or should there be a cap to the number of reads at once? + std::thread readThread( + [pathString, fileSize, data] + { + std::shared_lock lock(g_CustomAudioManager.m_loadingMutex); + std::basic_ifstream<uint8_t> wavStream(pathString, std::ios::binary); + + // would be weird if this got hit, since it would've worked previously + if (wavStream.fail()) + { + spdlog::error("Failed async read of audio sample {}", pathString); + return; + } + + // read from after the header first to preserve the empty header, then read the header last + wavStream.seekg(sizeof(EMPTY_WAVE), std::ios::beg); + wavStream.read(&data[sizeof(EMPTY_WAVE)], fileSize - sizeof(EMPTY_WAVE)); + wavStream.seekg(0, std::ios::beg); + wavStream.read(data, sizeof(EMPTY_WAVE)); + wavStream.close(); + + spdlog::info("Finished async read of audio sample {}", pathString); + }); + + readThread.detach(); } } @@ -289,6 +318,10 @@ void CustomAudioManager::ClearAudioOverrides() // this is cancer but it works Sleep(50); } + + // slightly (very) bad + // wait for all audio reads to complete so we don't kill preexisting audio buffers as we're writing to them + std::unique_lock lock(g_CustomAudioManager.m_loadingMutex); m_loadedAudioOverrides.clear(); m_loadedAudioOverridesRegex.clear(); @@ -297,11 +330,6 @@ void CustomAudioManager::ClearAudioOverrides() typedef bool (*LoadSampleMetadata_Type)(void* sample, void* audioBuffer, unsigned int audioBufferLength, int audioType); LoadSampleMetadata_Type LoadSampleMetadata_Original; -// Empty stereo 48000 WAVE file -unsigned char EMPTY_WAVE[45] = {0x52, 0x49, 0x46, 0x46, 0x25, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6D, 0x74, - 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x44, 0xAC, 0x00, 0x00, 0x88, 0x58, - 0x01, 0x00, 0x02, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x74, 0x00, 0x00, 0x00, 0x00}; - template <typename Iter, typename RandomGenerator> Iter select_randomly(Iter start, Iter end, RandomGenerator& g) { std::uniform_int_distribution<> dis(0, std::distance(start, end) - 1); diff --git a/NorthstarDedicatedTest/audio.h b/NorthstarDedicatedTest/audio.h index 3220d804..6ed3ce57 100644 --- a/NorthstarDedicatedTest/audio.h +++ b/NorthstarDedicatedTest/audio.h @@ -3,6 +3,7 @@ #include <vector> #include <filesystem> #include <regex> +#include <shared_mutex> namespace fs = std::filesystem; @@ -39,6 +40,7 @@ class CustomAudioManager bool TryLoadAudioOverride(const fs::path&); void ClearAudioOverrides(); + std::shared_mutex m_loadingMutex; std::unordered_map<std::string, std::shared_ptr<EventOverrideData>> m_loadedAudioOverrides = {}; std::unordered_map<std::string, std::shared_ptr<EventOverrideData>> m_loadedAudioOverridesRegex = {}; }; diff --git a/NorthstarDedicatedTest/clientruihooks.cpp b/NorthstarDedicatedTest/clientruihooks.cpp new file mode 100644 index 00000000..bc6c7aa7 --- /dev/null +++ b/NorthstarDedicatedTest/clientruihooks.cpp @@ -0,0 +1,24 @@ +#include "pch.h" +#include "clientruihooks.h" +#include "convar.h" + +ConVar* Cvar_rui_drawEnable; + +typedef char (*DrawRUIFuncType)(void* a1, float* a2); +DrawRUIFuncType DrawRUIFunc; + +char DrawRUIFuncHook(void* a1, float* a2) +{ + if (!Cvar_rui_drawEnable->GetBool()) + return 0; + + return DrawRUIFunc(a1, a2); +} + +void InitialiseEngineClientRUIHooks(HMODULE baseAddress) +{ + Cvar_rui_drawEnable = new ConVar("rui_drawEnable", "1", FCVAR_CLIENTDLL, "Controls whether RUI should be drawn"); + + HookEnabler hook; + ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0xFC500, &DrawRUIFuncHook, reinterpret_cast<LPVOID*>(&DrawRUIFunc)); +}
\ No newline at end of file diff --git a/NorthstarDedicatedTest/clientruihooks.h b/NorthstarDedicatedTest/clientruihooks.h new file mode 100644 index 00000000..967ccefe --- /dev/null +++ b/NorthstarDedicatedTest/clientruihooks.h @@ -0,0 +1,2 @@ +#pragma once +void InitialiseEngineClientRUIHooks(HMODULE baseAddress);
\ No newline at end of file diff --git a/NorthstarDedicatedTest/convar.h b/NorthstarDedicatedTest/convar.h index 72dc1d3c..07e7704b 100644 --- a/NorthstarDedicatedTest/convar.h +++ b/NorthstarDedicatedTest/convar.h @@ -129,7 +129,7 @@ class ConVar }; ConCommandBase m_ConCommandBase{}; // 0x0000 - const char* defaultVal{}; // 0x0040 + const char* m_pszDefaultValue{}; // 0x0040 CVValue_t m_Value{}; // 0x0048 bool m_bHasMin{}; // 0x005C float m_fMinVal{}; // 0x0060 diff --git a/NorthstarDedicatedTest/dedicated.cpp b/NorthstarDedicatedTest/dedicated.cpp index 8f4ec78c..2661e918 100644 --- a/NorthstarDedicatedTest/dedicated.cpp +++ b/NorthstarDedicatedTest/dedicated.cpp @@ -185,13 +185,6 @@ void InitialiseDedicated(HMODULE engineAddress) // NSMem::NOP(ea + 0x1C4E07, 5); //} - // not sure if this should be done, not loading ui at least is good, but should everything be gone? - { - // Host_Init - // change the number of rpaks to load from 6 to 1, so we only load common.rpak - NSMem::BytePatch(ea + 0x15653B + 1, "01"); - } - { // Host_Init // remove call to ui loading stuff diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp index 06878b1e..04dfe85a 100644 --- a/NorthstarDedicatedTest/dllmain.cpp +++ b/NorthstarDedicatedTest/dllmain.cpp @@ -42,6 +42,7 @@ #include "host_state.h" #include "rcon_shared.h" #include "clientvideooverrides.h" +#include "clientruihooks.h" #include "rapidjson/document.h" #include "rapidjson/stringbuffer.h" #include "rapidjson/writer.h" @@ -244,6 +245,7 @@ bool InitialiseNorthstar() AddDllLoadCallbackForClient("client.dll", InitialiseLocalChatWriter); AddDllLoadCallbackForClient("client.dll", InitialiseScriptServerToClientStringCommands); AddDllLoadCallbackForClient("client.dll", InitialiseClientVideoOverrides); + AddDllLoadCallbackForClient("engine.dll", InitialiseEngineClientRUIHooks); // audio hooks AddDllLoadCallbackForClient("client.dll", InitialiseMilesAudioHooks); diff --git a/NorthstarDedicatedTest/masterserver.cpp b/NorthstarDedicatedTest/masterserver.cpp index 09fbb0ff..99b74d70 100644 --- a/NorthstarDedicatedTest/masterserver.cpp +++ b/NorthstarDedicatedTest/masterserver.cpp @@ -23,6 +23,8 @@ ConVar* Cvar_ns_server_name; ConVar* Cvar_ns_server_desc; ConVar* Cvar_ns_server_password; +ConVar* Cvar_ns_curl_log_enable; + // Source ConVar ConVar* Cvar_hostname; @@ -167,7 +169,7 @@ RemoteServerInfo::RemoteServerInfo( void MasterServerManager::SetCommonHttpClientOptions(CURL* curl) { curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); - curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(curl, CURLOPT_VERBOSE, Cvar_ns_curl_log_enable->GetBool()); curl_easy_setopt(curl, CURLOPT_USERAGENT, &NSUserAgent); // curl_easy_setopt(curl, CURLOPT_STDERR, stdout); if (CommandLine()->FindParm("-msinsecure")) // TODO: this check doesn't seem to work @@ -1274,6 +1276,8 @@ void InitialiseSharedMasterServer(HMODULE baseAddress) Cvar_ns_report_server_to_masterserver = new ConVar("ns_report_server_to_masterserver", "1", FCVAR_GAMEDLL, ""); Cvar_ns_report_sp_server_to_masterserver = new ConVar("ns_report_sp_server_to_masterserver", "0", FCVAR_GAMEDLL, ""); + Cvar_ns_curl_log_enable = new ConVar("ns_curl_log_enable", "0", FCVAR_NONE, ""); + Cvar_hostname = *(ConVar**)((char*)baseAddress + 0x1315bae8); g_MasterServerManager = new MasterServerManager; diff --git a/NorthstarDedicatedTest/modmanager.cpp b/NorthstarDedicatedTest/modmanager.cpp index 0ac7e4b6..f28f87c6 100644 --- a/NorthstarDedicatedTest/modmanager.cpp +++ b/NorthstarDedicatedTest/modmanager.cpp @@ -380,7 +380,7 @@ void ModManager::LoadMods() modPak.m_bAutoLoad = !bUseRpakJson || (dRpakJson.HasMember("Preload") && dRpakJson["Preload"].IsObject() && dRpakJson["Preload"].HasMember(pakName) && dRpakJson["Preload"][pakName].IsTrue()); - modPak.m_sPakPath = pakName; + modPak.m_sPakName = pakName; // not using atm because we need to resolve path to rpak // if (m_hasLoadedMods && modPak.m_bAutoLoad) diff --git a/NorthstarDedicatedTest/modmanager.h b/NorthstarDedicatedTest/modmanager.h index 7f12559f..798c2306 100644 --- a/NorthstarDedicatedTest/modmanager.h +++ b/NorthstarDedicatedTest/modmanager.h @@ -56,7 +56,7 @@ struct ModRpakEntry { public: bool m_bAutoLoad; - std::string m_sPakPath; + std::string m_sPakName; }; class Mod diff --git a/NorthstarDedicatedTest/rpakfilesystem.cpp b/NorthstarDedicatedTest/rpakfilesystem.cpp index 6853029b..b4ddcd1a 100644 --- a/NorthstarDedicatedTest/rpakfilesystem.cpp +++ b/NorthstarDedicatedTest/rpakfilesystem.cpp @@ -2,19 +2,26 @@ #include "rpakfilesystem.h" #include "hookutils.h" #include "modmanager.h" +#include "dedicated.h" typedef void* (*LoadCommonPaksForMapType)(char* map); LoadCommonPaksForMapType LoadCommonPaksForMap; typedef void* (*LoadPakSyncType)(const char* path, void* unknownSingleton, int flags); typedef int (*LoadPakAsyncType)(const char* path, void* unknownSingleton, int flags, void* callback0, void* callback1); +typedef void* (*UnloadPakType)(int pakHandle, void* callback); +typedef void* (*ReadFullFileFromDiskType)(const char* requestedPath, void* a2); // there are more i'm just too lazy to add struct PakLoadFuncs { - void* unknown[2]; + void* unk0[2]; LoadPakSyncType LoadPakSync; LoadPakAsyncType LoadPakAsync; + void* unk1[2]; + UnloadPakType UnloadPak; + void* unk2[17]; + ReadFullFileFromDiskType ReadFullFileFromDisk; }; PakLoadFuncs* g_pakLoadApi; @@ -22,7 +29,21 @@ void** pUnknownPakLoadSingleton; PakLoadManager* g_PakLoadManager; void PakLoadManager::LoadPakSync(const char* path) { g_pakLoadApi->LoadPakSync(path, *pUnknownPakLoadSingleton, 0); } -void PakLoadManager::LoadPakAsync(const char* path) { g_pakLoadApi->LoadPakAsync(path, *pUnknownPakLoadSingleton, 2, nullptr, nullptr); } +void PakLoadManager::LoadPakAsync(const char* path, bool bMarkForUnload) +{ + int handle = g_pakLoadApi->LoadPakAsync(path, *pUnknownPakLoadSingleton, 2, nullptr, nullptr); + + if (bMarkForUnload) + m_pakHandlesToUnload.push_back(handle); +} + +void PakLoadManager::UnloadPaks() +{ + for (int pakHandle : m_pakHandlesToUnload) + g_pakLoadApi->UnloadPak(pakHandle, nullptr); + + m_pakHandlesToUnload.clear(); +} void HandlePakAliases(char** map) { @@ -41,12 +62,8 @@ void HandlePakAliases(char** map) } } -bool bShouldPreload = true; void LoadPreloadPaks() { - // disable preloading while we're doing this - bShouldPreload = false; - // note, loading from ./ is necessary otherwise paks will load from gamedir/r2/paks for (Mod& mod : g_ModManager->m_loadedMods) { @@ -58,22 +75,75 @@ void LoadPreloadPaks() for (ModRpakEntry& pak : mod.Rpaks) if (pak.m_bAutoLoad) - g_PakLoadManager->LoadPakAsync((modPakPath / pak.m_sPakPath).string().c_str()); + g_PakLoadManager->LoadPakAsync((modPakPath / pak.m_sPakName).string().c_str(), false); } +} + +void LoadCustomMapPaks(char** pakName, bool* bNeedToFreePakName) +{ + // whether the vanilla game has this rpak + 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_ModManager->m_loadedMods) + { + if (!mod.Enabled) + continue; + + // need to get a relative path of mod to mod folder + fs::path modPakPath("./" / mod.ModDirectory / "paks"); - bShouldPreload = true; + for (ModRpakEntry& pak : mod.Rpaks) + { + if (!pak.m_bAutoLoad && !pak.m_sPakName.compare(*pakName)) + { + // if the game doesn't have the original pak, let it handle loading this one as if it was the one it was loading originally + if (!bHasOriginalPak) + { + std::string path = (modPakPath / pak.m_sPakName).string(); + *pakName = new char[path.size() + 1]; + strcpy(*pakName, &path[0]); + (*pakName)[path.size()] = '\0'; + + bHasOriginalPak = true; + *bNeedToFreePakName = + true; // we can't free this memory until we're done with the pak, so let whatever's calling this deal with it + } + else + g_PakLoadManager->LoadPakAsync((modPakPath / pak.m_sPakName).string().c_str(), true); + } + } + } } LoadPakSyncType LoadPakSyncOriginal; void* LoadPakSyncHook(char* path, void* unknownSingleton, int flags) { HandlePakAliases(&path); + + bool bNeedToFreePakName = false; + // note: we don't handle loading any preloaded custom paks synchronously since LoadPakSync is never actually called in retail, just load // them async instead - LoadPreloadPaks(); + static bool bShouldLoadPaks = true; + if (bShouldLoadPaks) + { + // disable preloading while we're doing this + bShouldLoadPaks = false; + + LoadPreloadPaks(); + LoadCustomMapPaks(&path, &bNeedToFreePakName); + + bShouldLoadPaks = true; + } spdlog::info("LoadPakSync {}", path); - return LoadPakSyncOriginal(path, unknownSingleton, flags); + void* ret = LoadPakSyncOriginal(path, unknownSingleton, flags); + + if (bNeedToFreePakName) + delete[] path; + + return ret; } LoadPakAsyncType LoadPakAsyncOriginal; @@ -81,11 +151,79 @@ int LoadPakAsyncHook(char* path, void* unknownSingleton, int flags, void* callba { HandlePakAliases(&path); - if (bShouldPreload) + bool bNeedToFreePakName = false; + + static bool bShouldLoadPaks = true; + if (bShouldLoadPaks) + { + // disable preloading while we're doing this + bShouldLoadPaks = false; + LoadPreloadPaks(); + LoadCustomMapPaks(&path, &bNeedToFreePakName); + + bShouldLoadPaks = true; + + // do this after custom paks load and in bShouldLoadPaks so we only ever call this on the root pakload call + // todo: could probably add some way to flag custom paks to not be loaded on dedicated servers in rpak.json + if (IsDedicated() && strncmp(path, "common", 6)) // dedicated only needs common and common_mp + return -1; + } int ret = LoadPakAsyncOriginal(path, unknownSingleton, flags, callback0, callback1); spdlog::info("LoadPakAsync {} {}", path, ret); + + if (bNeedToFreePakName) + delete[] path; + + return ret; +} + +UnloadPakType UnloadPakOriginal; +void* UnloadPakHook(int pakHandle, void* callback) +{ + static bool bShouldUnloadPaks = true; + if (bShouldUnloadPaks) + { + bShouldUnloadPaks = false; + g_PakLoadManager->UnloadPaks(); + bShouldUnloadPaks = true; + } + + spdlog::info("UnloadPak {}", pakHandle); + return UnloadPakOriginal(pakHandle, callback); +} + +// we hook this exclusively for resolving stbsp paths, but seemingly it's also used for other stuff like vpk and rpak loads +// possibly just async loading all together? +ReadFullFileFromDiskType ReadFullFileFromDiskOriginal; +void* ReadFullFileFromDiskHook(const char* requestedPath, void* a2) +{ + fs::path path(requestedPath); + char* allocatedNewPath = nullptr; + + if (path.extension() == ".stbsp") + { + fs::path filename = path.filename(); + spdlog::info("LoadStreamBsp: {}", filename.string()); + + // resolve modded stbsp path so we can load mod stbsps + auto modFile = g_ModManager->m_modFiles.find(fs::path("maps" / filename).lexically_normal().string()); + if (modFile != g_ModManager->m_modFiles.end()) + { + // need to allocate a new string for this + std::string newPath = (modFile->second.owningMod->ModDirectory / "mod" / modFile->second.path).string(); + allocatedNewPath = new char[newPath.size() + 1]; + strncpy(allocatedNewPath, newPath.c_str(), newPath.size()); + allocatedNewPath[newPath.size()] = '\0'; + requestedPath = allocatedNewPath; + } + } + + void* ret = ReadFullFileFromDiskOriginal(requestedPath, a2); + if (allocatedNewPath) + delete[] allocatedNewPath; + return ret; } @@ -99,4 +237,7 @@ void InitialiseEngineRpakFilesystem(HMODULE baseAddress) HookEnabler hook; ENABLER_CREATEHOOK(hook, g_pakLoadApi->LoadPakSync, &LoadPakSyncHook, reinterpret_cast<LPVOID*>(&LoadPakSyncOriginal)); ENABLER_CREATEHOOK(hook, g_pakLoadApi->LoadPakAsync, &LoadPakAsyncHook, reinterpret_cast<LPVOID*>(&LoadPakAsyncOriginal)); + ENABLER_CREATEHOOK(hook, g_pakLoadApi->UnloadPak, &UnloadPakHook, reinterpret_cast<LPVOID*>(&UnloadPakOriginal)); + ENABLER_CREATEHOOK( + hook, g_pakLoadApi->ReadFullFileFromDisk, &ReadFullFileFromDiskHook, reinterpret_cast<LPVOID*>(&ReadFullFileFromDiskOriginal)); }
\ No newline at end of file diff --git a/NorthstarDedicatedTest/rpakfilesystem.h b/NorthstarDedicatedTest/rpakfilesystem.h index 334104a9..3c104822 100644 --- a/NorthstarDedicatedTest/rpakfilesystem.h +++ b/NorthstarDedicatedTest/rpakfilesystem.h @@ -6,7 +6,11 @@ class PakLoadManager { public: void LoadPakSync(const char* path); - void LoadPakAsync(const char* path); + void LoadPakAsync(const char* path, bool bMarkForUnload); + void UnloadPaks(); + + private: + std::vector<int> m_pakHandlesToUnload; }; extern PakLoadManager* g_PakLoadManager;
\ No newline at end of file diff --git a/NorthstarDedicatedTest/sourceconsole.cpp b/NorthstarDedicatedTest/sourceconsole.cpp index 1e2e2f20..7bc68598 100644 --- a/NorthstarDedicatedTest/sourceconsole.cpp +++ b/NorthstarDedicatedTest/sourceconsole.cpp @@ -48,7 +48,7 @@ void InitialiseConsoleOnInterfaceCreation() void InitialiseSourceConsole(HMODULE baseAddress) { g_SourceGameConsole = new SourceInterface<CGameConsole>("client.dll", "GameConsole004"); - RegisterConCommand("toggleconsole", ConCommand_toggleconsole, "toggles the console", FCVAR_NONE); + RegisterConCommand("toggleconsole", ConCommand_toggleconsole, "toggles the console", FCVAR_DONTRECORD); } // logging stuff |