diff options
Diffstat (limited to 'NorthstarDedicatedTest')
-rw-r--r-- | NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj | 2 | ||||
-rw-r--r-- | NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters | 12 | ||||
-rw-r--r-- | NorthstarDedicatedTest/clientchathooks.cpp | 4 | ||||
-rw-r--r-- | NorthstarDedicatedTest/clientvideooverrides.cpp | 42 | ||||
-rw-r--r-- | NorthstarDedicatedTest/clientvideooverrides.h | 2 | ||||
-rw-r--r-- | NorthstarDedicatedTest/dedicated.cpp | 5 | ||||
-rw-r--r-- | NorthstarDedicatedTest/dllmain.cpp | 3 | ||||
-rw-r--r-- | NorthstarDedicatedTest/filesystem.cpp | 20 | ||||
-rw-r--r-- | NorthstarDedicatedTest/gameutils.cpp | 15 | ||||
-rw-r--r-- | NorthstarDedicatedTest/gameutils.h | 8 | ||||
-rw-r--r-- | NorthstarDedicatedTest/logging.cpp | 2 | ||||
-rw-r--r-- | NorthstarDedicatedTest/modmanager.cpp | 90 | ||||
-rw-r--r-- | NorthstarDedicatedTest/modmanager.h | 21 | ||||
-rw-r--r-- | NorthstarDedicatedTest/plugins.cpp | 38 | ||||
-rw-r--r-- | NorthstarDedicatedTest/rpakfilesystem.cpp | 77 | ||||
-rw-r--r-- | NorthstarDedicatedTest/rpakfilesystem.h | 10 | ||||
-rw-r--r-- | NorthstarDedicatedTest/securitypatches.cpp | 1 | ||||
-rw-r--r-- | NorthstarDedicatedTest/serverauthentication.cpp | 5 |
18 files changed, 295 insertions, 62 deletions
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj index 083ae51f..6074e41f 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="clientvideooverrides.h" /> <ClInclude Include="localchatwriter.h" /> <ClInclude Include="plugins.h" /> <ClInclude Include="plugin_abi.h" /> @@ -584,6 +585,7 @@ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader> </ClCompile> + <ClCompile Include="clientvideooverrides.cpp" /> <ClCompile Include="concommand.cpp" /> <ClCompile Include="configurables.cpp" /> <ClCompile Include="context.cpp" /> diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters index 38428d12..b2e901fd 100644 --- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters +++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters @@ -1471,8 +1471,8 @@ <Filter>Header Files\Client</Filter> </ClInclude> <ClInclude Include="localchatwriter.h"> - <Filter>Header Files\Client</Filter> - </ClInclude> + <Filter>Header Files\Client</Filter> + </ClInclude> <ClInclude Include="scriptservertoclientstringcommand.h"> <Filter>Header Files\Client</Filter> </ClInclude> @@ -1518,6 +1518,9 @@ <ClInclude Include="host_state.h"> <Filter>Header Files\Shared</Filter> </ClInclude> + <ClInclude Include="clientvideooverrides.h"> + <Filter>Header Files\Client</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="dllmain.cpp"> @@ -1665,7 +1668,7 @@ <Filter>Source Files\Client</Filter> </ClCompile> <ClCompile Include="localchatwriter.cpp"> - <Filter>Source Files\Client</Filter> + <Filter>Source Files\Client</Filter> </ClCompile> <ClCompile Include="scriptservertoclientstringcommand.cpp"> <Filter>Source Files\Client</Filter> @@ -1703,6 +1706,9 @@ <ClCompile Include="host_state.cpp"> <Filter>Source Files\Shared</Filter> </ClCompile> + <ClCompile Include="clientvideooverrides.cpp"> + <Filter>Source Files\Client</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <MASM Include="audio_asm.asm"> diff --git a/NorthstarDedicatedTest/clientchathooks.cpp b/NorthstarDedicatedTest/clientchathooks.cpp index 74418c06..ca20b0dc 100644 --- a/NorthstarDedicatedTest/clientchathooks.cpp +++ b/NorthstarDedicatedTest/clientchathooks.cpp @@ -2,6 +2,7 @@ #include "clientchathooks.h" #include <rapidjson/document.h> #include "squirrel.h" +#include "dedicated.h" #include "serverchathooks.h" #include "localchatwriter.h" @@ -86,6 +87,9 @@ static SQRESULT SQ_ChatWriteLine(void* sqvm) void InitialiseClientChatHooks(HMODULE baseAddress) { + if (IsDedicated()) + return; + HookEnabler hook; ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x22E580, &CHudChat__AddGameLineHook, reinterpret_cast<LPVOID*>(&CHudChat__AddGameLine)); diff --git a/NorthstarDedicatedTest/clientvideooverrides.cpp b/NorthstarDedicatedTest/clientvideooverrides.cpp new file mode 100644 index 00000000..3a63c181 --- /dev/null +++ b/NorthstarDedicatedTest/clientvideooverrides.cpp @@ -0,0 +1,42 @@ +#include "pch.h" +#include "clientvideooverrides.h" +#include "modmanager.h" +#include "dedicated.h" + +typedef void*(*BinkOpenType)(const char* path, uint32_t flags); +BinkOpenType BinkOpen; + +void* BinkOpenHook(const char* path, uint32_t flags) +{ + std::string filename(fs::path(path).filename().string()); + spdlog::info("BinkOpen {}", filename); + + // figure out which mod is handling the bink + Mod* fileOwner = nullptr; + for (Mod& mod : g_ModManager->m_loadedMods) + { + if (!mod.Enabled) + continue; + + if (std::find(mod.BinkVideos.begin(), mod.BinkVideos.end(), filename) != mod.BinkVideos.end()) + fileOwner = &mod; + } + + if (fileOwner) + { + // create new path + fs::path binkPath(fileOwner->ModDirectory / "media" / filename); + return BinkOpen(binkPath.string().c_str(), flags); + } + else + return BinkOpen(path, flags); +} + +void InitialiseClientVideoOverrides(HMODULE baseAddress) +{ + if (IsDedicated()) + return; + + HookEnabler hook; + ENABLER_CREATEHOOK(hook, GetProcAddress(GetModuleHandleA("bink2w64.dll"), "BinkOpen"), &BinkOpenHook, reinterpret_cast<LPVOID*>(&BinkOpen)); +}
\ No newline at end of file diff --git a/NorthstarDedicatedTest/clientvideooverrides.h b/NorthstarDedicatedTest/clientvideooverrides.h new file mode 100644 index 00000000..8819e404 --- /dev/null +++ b/NorthstarDedicatedTest/clientvideooverrides.h @@ -0,0 +1,2 @@ +#pragma once +void InitialiseClientVideoOverrides(HMODULE baseAddress);
\ No newline at end of file diff --git a/NorthstarDedicatedTest/dedicated.cpp b/NorthstarDedicatedTest/dedicated.cpp index 920484da..f4f24466 100644 --- a/NorthstarDedicatedTest/dedicated.cpp +++ b/NorthstarDedicatedTest/dedicated.cpp @@ -44,7 +44,7 @@ void RunServer(CDedicatedExports* dedicated) // add +map if not present // don't manually execute this from cbuf as users may have it in their startup args anyway, easier just to run from stuffcmds if present if (!CommandLine()->CheckParm("+map")) - CommandLine()->AppendParm("+map", Cvar_match_defaultMap->GetString()); + CommandLine()->AppendParm("+map", g_pCVar->FindVar("match_defaultMap")->GetString()); // run server autoexec and re-run commandline Cbuf_AddText(Cbuf_GetCurrentPlayer(), "exec autoexec_ns_server", cmd_source_t::kCommandSrcCode); @@ -57,6 +57,9 @@ void RunServer(CDedicatedExports* dedicated) // note: we no longer manually set map and hoststate to start server in g_pHostState, we just use +map which seems to initialise stuff // better + // get tickinterval + ConVar* Cvar_base_tickinterval_mp = g_pCVar->FindVar("base_tickinterval_mp"); + // main loop double frameTitle = 0; while (g_pEngine->m_nQuitting == EngineQuitState::QUIT_NOTQUITTING) diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp index 53e8d59f..e81d70c9 100644 --- a/NorthstarDedicatedTest/dllmain.cpp +++ b/NorthstarDedicatedTest/dllmain.cpp @@ -42,7 +42,7 @@ #include "plugins.h" #include "host_state.h" #include "rcon_shared.h" - +#include "clientvideooverrides.h" #include "rapidjson/document.h" #include "rapidjson/stringbuffer.h" #include "rapidjson/writer.h" @@ -241,6 +241,7 @@ bool InitialiseNorthstar() AddDllLoadCallback("client.dll", InitialiseClientChatHooks); AddDllLoadCallback("client.dll", InitialiseLocalChatWriter); AddDllLoadCallback("client.dll", InitialiseScriptServerToClientStringCommands); + AddDllLoadCallback("client.dll", InitialiseClientVideoOverrides); } AddDllLoadCallback("engine.dll", InitialiseEngineSpewFuncHooks); diff --git a/NorthstarDedicatedTest/filesystem.cpp b/NorthstarDedicatedTest/filesystem.cpp index 951198af..702141bb 100644 --- a/NorthstarDedicatedTest/filesystem.cpp +++ b/NorthstarDedicatedTest/filesystem.cpp @@ -33,7 +33,6 @@ VPKData* MountVPKHook(IFileSystem* fileSystem, const char* vpkPath); bool readingOriginalFile; std::string currentModPath; SourceInterface<IFileSystem>* g_Filesystem; -void* g_pVGuiLocalize; void InitialiseFilesystem(HMODULE baseAddress) { @@ -175,11 +174,22 @@ VPKData* MountVPKHook(IFileSystem* fileSystem, const char* vpkPath) if (!mod.Enabled) continue; - for (std::string& vpkPath : mod.Vpks) + for (ModVPKEntry& vpkEntry : mod.Vpks) { - // note: could potentially not mount these if they're already mounted? - spdlog::info("MountVPK {}", vpkPath); - spdlog::info((void*)mountVPK(fileSystem, vpkPath.c_str())); + // if we're autoloading, just load no matter what + if (!vpkEntry.m_bAutoLoad) + { + // resolve vpk name and try to load one with the same name + // todo: we should be unloading these on map unload manually + std::string mapName(fs::path(vpkPath).filename().string()); + std::string modMapName(fs::path(vpkEntry.m_sVpkPath.c_str()).filename().string()); + if (mapName.compare(modMapName)) + continue; + } + + VPKData* loaded = mountVPK(fileSystem, vpkEntry.m_sVpkPath.c_str()); + if (!ret) // this is primarily for map vpks and stuff, so the map's vpk is what gets returned from here + ret = loaded; } } diff --git a/NorthstarDedicatedTest/gameutils.cpp b/NorthstarDedicatedTest/gameutils.cpp index c4fba491..9c0878d1 100644 --- a/NorthstarDedicatedTest/gameutils.cpp +++ b/NorthstarDedicatedTest/gameutils.cpp @@ -1,10 +1,10 @@ #include "pch.h" -#include "gameutils.h" #include "convar.h" #include "concommand.h" #include "sv_rcon.h" #include "cl_rcon.h" #include "dedicated.h" +#include "gameutils.h" // memory IMemAlloc* g_pMemAllocSingleton; @@ -22,7 +22,6 @@ server_state_t* sv_m_State; // network stuff ConVar* Cvar_hostport; -ConVar* Cvar_net_datablock_enabled; // playlist stuff GetCurrentPlaylistType GetCurrentPlaylistName; @@ -33,17 +32,11 @@ GetCurrentPlaylistVarType GetCurrentPlaylistVar; // server entity stuff Server_GetEntityByIndexType Server_GetEntityByIndex; -// server tickrate stuff -ConVar* Cvar_base_tickinterval_mp; -ConVar* Cvar_base_tickinterval_sp; - // auth char* g_LocalPlayerUserID; char* g_LocalPlayerOriginToken; // misc stuff -ConVar* Cvar_match_defaultMap; -ConVar* Cvar_communities_hostname; ErrorType Error; CommandLineType CommandLine; Plat_FloatTimeType Plat_FloatTime; @@ -83,17 +76,13 @@ void InitialiseEngineGameUtilFunctions(HMODULE baseAddress) g_pAllConVars.push_back(pConVar); } }*/ + Cvar_hostport = (ConVar*)((char*)baseAddress + 0x13FA6070); - Cvar_net_datablock_enabled = (ConVar*)((char*)baseAddress + 0x12A4F6D0); - Cvar_match_defaultMap = (ConVar*)((char*)baseAddress + 0x8AB530); - Cvar_communities_hostname = (ConVar*)((char*)baseAddress + 0x13157E50); } void InitialiseServerGameUtilFunctions(HMODULE baseAddress) { Server_GetEntityByIndex = (Server_GetEntityByIndexType)((char*)baseAddress + 0xFB820); - Cvar_base_tickinterval_mp = (ConVar*)((char*)baseAddress + 0xBFC360); - Cvar_base_tickinterval_sp = (ConVar*)((char*)baseAddress + 0xBFBEA0); } void InitialiseTier0GameUtilFunctions(HMODULE baseAddress) diff --git a/NorthstarDedicatedTest/gameutils.h b/NorthstarDedicatedTest/gameutils.h index fd8521b7..1fb0f284 100644 --- a/NorthstarDedicatedTest/gameutils.h +++ b/NorthstarDedicatedTest/gameutils.h @@ -165,7 +165,6 @@ extern server_state_t* sv_m_State; // network stuff extern ConVar* Cvar_hostport; -extern ConVar* Cvar_net_datablock_enabled; // playlist stuff typedef const char* (*GetCurrentPlaylistType)(); @@ -184,18 +183,11 @@ extern GetCurrentPlaylistVarType GetCurrentPlaylistVar; typedef void* (*Server_GetEntityByIndexType)(int index); extern Server_GetEntityByIndexType Server_GetEntityByIndex; -// server tickrate stuff -extern ConVar* Cvar_base_tickinterval_mp; -extern ConVar* Cvar_base_tickinterval_sp; - // auth extern char* g_LocalPlayerUserID; extern char* g_LocalPlayerOriginToken; // misc stuff -extern ConVar* Cvar_match_defaultMap; -extern ConVar* Cvar_communities_hostname; - typedef void (*ErrorType)(const char* fmt, ...); extern ErrorType Error; diff --git a/NorthstarDedicatedTest/logging.cpp b/NorthstarDedicatedTest/logging.cpp index 96ccac21..941ae52d 100644 --- a/NorthstarDedicatedTest/logging.cpp +++ b/NorthstarDedicatedTest/logging.cpp @@ -3,7 +3,7 @@ #include "sourceconsole.h" #include "spdlog/sinks/basic_file_sink.h" #include "hookutils.h" -#include "gameutils.h" +#include "convar.h" #include "dedicated.h" #include <iomanip> #include <sstream> diff --git a/NorthstarDedicatedTest/modmanager.cpp b/NorthstarDedicatedTest/modmanager.cpp index 4f2bb416..79529c99 100644 --- a/NorthstarDedicatedTest/modmanager.cpp +++ b/NorthstarDedicatedTest/modmanager.cpp @@ -14,6 +14,7 @@ #include <sstream> #include <vector> #include "filesystem.h" +#include "rpakfilesystem.h" #include "configurables.h" ModManager* g_ModManager; @@ -289,6 +290,26 @@ void ModManager::LoadMods() // read vpk paths if (fs::exists(mod.ModDirectory / "vpk")) { + // read vpk cfg + std::ifstream vpkJsonStream(mod.ModDirectory / "vpk/vpk.json"); + std::stringstream vpkJsonStringStream; + + bool bUseVPKJson = false; + rapidjson::Document dVpkJson; + + if (!vpkJsonStream.fail()) + { + while (vpkJsonStream.peek() != EOF) + vpkJsonStringStream << (char)vpkJsonStream.get(); + + vpkJsonStream.close(); + dVpkJson.Parse<rapidjson::ParseFlag::kParseCommentsFlag | rapidjson::ParseFlag::kParseTrailingCommasFlag>( + vpkJsonStringStream.str().c_str()); + + bUseVPKJson = + !dVpkJson.HasParseError() && dVpkJson.IsObject(); + } + for (fs::directory_entry file : fs::directory_iterator(mod.ModDirectory / "vpk")) { // a bunch of checks to make sure we're only adding dir vpks and their paths are good @@ -302,14 +323,71 @@ void ModManager::LoadMods() // this really fucking sucks but it'll work std::string vpkName = (file.path().parent_path() / formattedPath.substr(strlen("english"), formattedPath.find(".bsp") - 3)).string(); - mod.Vpks.push_back(vpkName); - if (m_hasLoadedMods) + 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; + + if (m_hasLoadedMods && modVpk.m_bAutoLoad) (*g_Filesystem)->m_vtable->MountVPK(*g_Filesystem, vpkName.c_str()); } } } + // read rpak paths + if (fs::exists(mod.ModDirectory / "paks")) + { + // read rpak cfg + std::ifstream rpakJsonStream(mod.ModDirectory / "paks/rpak.json"); + std::stringstream rpakJsonStringStream; + + bool bUseRpakJson = false; + rapidjson::Document dRpakJson; + + if (!rpakJsonStream.fail()) + { + while (rpakJsonStream.peek() != EOF) + rpakJsonStringStream << (char)rpakJsonStream.get(); + + rpakJsonStream.close(); + dRpakJson.Parse<rapidjson::ParseFlag::kParseCommentsFlag | rapidjson::ParseFlag::kParseTrailingCommasFlag>( + rpakJsonStringStream.str().c_str()); + + bUseRpakJson = + !dRpakJson.HasParseError() && dRpakJson.IsObject(); + } + + // read pak aliases + if (bUseRpakJson && dRpakJson.HasMember("Aliases") && dRpakJson["Aliases"].IsObject()) + { + for (rapidjson::Value::ConstMemberIterator iterator = dRpakJson["Aliases"].MemberBegin(); + iterator != dRpakJson["Aliases"].MemberEnd(); iterator++) + { + if (!iterator->name.IsString() || !iterator->value.IsString()) + continue; + + mod.RpakAliases.insert(std::make_pair(iterator->name.GetString(), iterator->value.GetString())); + } + } + + for (fs::directory_entry file : fs::directory_iterator(mod.ModDirectory / "paks")) + { + // ensure we're only loading rpaks + if (fs::is_regular_file(file) && file.path().extension() == ".rpak") + { + std::string pakName(file.path().filename().string()); + + ModRpakEntry& modPak = mod.Rpaks.emplace_back(); + modPak.m_bAutoLoad = !bUseRpakJson || (dRpakJson.HasMember("Preload") && dRpakJson["Preload"].IsObject() && dRpakJson["Preload"].HasMember(pakName) && dRpakJson["Preload"][pakName].IsTrue()); + modPak.m_sPakPath = pakName; + + // not using atm because we need to resolve path to rpak + //if (m_hasLoadedMods && modPak.m_bAutoLoad) + // g_PakLoadManager->LoadPakAsync(pakName.c_str()); + } + } + } + // read keyvalues paths if (fs::exists(mod.ModDirectory / "keyvalues")) { @@ -340,6 +418,14 @@ void ModManager::LoadMods() } } + // read bink video paths + if (fs::exists(mod.ModDirectory / "media")) + { + for (fs::directory_entry file : fs::recursive_directory_iterator(mod.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")) { diff --git a/NorthstarDedicatedTest/modmanager.h b/NorthstarDedicatedTest/modmanager.h index 07e5bffb..c79c507d 100644 --- a/NorthstarDedicatedTest/modmanager.h +++ b/NorthstarDedicatedTest/modmanager.h @@ -44,6 +44,21 @@ struct ModScript std::vector<ModScriptCallback> Callbacks; }; +// these are pretty much identical, could refactor to use the same stuff? +struct ModVPKEntry +{ + public: + bool m_bAutoLoad; + std::string m_sVpkPath; +}; + +struct ModRpakEntry +{ + public: + bool m_bAutoLoad; + std::string m_sPakPath; +}; + class Mod { public: @@ -76,10 +91,14 @@ class Mod // other files: - std::vector<std::string> Vpks; + std::vector<ModVPKEntry> Vpks; std::unordered_map<size_t, std::string> KeyValues; + std::vector<std::string> BinkVideos; std::string Pdiff; // only need one per mod + std::vector<ModRpakEntry> Rpaks; + std::unordered_map<std::string, std::string> RpakAliases; // paks we alias to other rpaks, e.g. to load sp_crashsite paks on the map mp_crashsite + // other stuff bool wasReadSuccessfully = false; diff --git a/NorthstarDedicatedTest/plugins.cpp b/NorthstarDedicatedTest/plugins.cpp index 383555cf..b725a5a8 100644 --- a/NorthstarDedicatedTest/plugins.cpp +++ b/NorthstarDedicatedTest/plugins.cpp @@ -390,21 +390,25 @@ void InitialisePluginCommands(HMODULE baseAddress) // i swear there's a way to make this not have be run in 2 contexts but i can't figure it out // some funcs i need are just not available in UI or CLIENT - g_UISquirrelManager->AddFuncRegistration( - "void", "NSUpdateGameStateUI", "string gamemode, string gamemodeName, string map, string mapName, bool connected, bool loading", "", - SQ_UpdateGameStateUI); - g_ClientSquirrelManager->AddFuncRegistration( - "void", "NSUpdateGameStateClient", - "int playerCount, int outScore, int secondHighestScore, int highestScore, bool roundBased, int scoreLimit", "", - SQ_UpdateGameStateClient); - g_UISquirrelManager->AddFuncRegistration( - "void", "NSUpdateServerInfo", - "string id, string name, string password, int players, int maxPlayers, string map, string mapDisplayName, string playlist, string " - "playlistDisplayName", - "", SQ_UpdateServerInfo); - g_ClientSquirrelManager->AddFuncRegistration( - "void", "NSUpdateServerInfoReload", "int maxPlayers", "", SQ_UpdateServerInfoBetweenRounds); - g_ClientSquirrelManager->AddFuncRegistration("void", "NSUpdateTimeInfo", "float timeInFuture", "", SQ_UpdateTimeInfo); - g_UISquirrelManager->AddFuncRegistration("void", "NSSetLoading", "bool loading", "", SQ_SetConnected); - g_UISquirrelManager->AddFuncRegistration("void", "NSUpdateListenServer", "", "", SQ_UpdateListenServer); + if (g_UISquirrelManager && g_ClientSquirrelManager) + { + g_UISquirrelManager->AddFuncRegistration( + "void", "NSUpdateGameStateUI", "string gamemode, string gamemodeName, string map, string mapName, bool connected, bool loading", + "", SQ_UpdateGameStateUI); + g_ClientSquirrelManager->AddFuncRegistration( + "void", "NSUpdateGameStateClient", + "int playerCount, int outScore, int secondHighestScore, int highestScore, bool roundBased, int scoreLimit", "", + SQ_UpdateGameStateClient); + g_UISquirrelManager->AddFuncRegistration( + "void", "NSUpdateServerInfo", + "string id, string name, string password, int players, int maxPlayers, string map, string mapDisplayName, string playlist, " + "string " + "playlistDisplayName", + "", SQ_UpdateServerInfo); + g_ClientSquirrelManager->AddFuncRegistration( + "void", "NSUpdateServerInfoReload", "int maxPlayers", "", SQ_UpdateServerInfoBetweenRounds); + g_ClientSquirrelManager->AddFuncRegistration("void", "NSUpdateTimeInfo", "float timeInFuture", "", SQ_UpdateTimeInfo); + g_UISquirrelManager->AddFuncRegistration("void", "NSSetLoading", "bool loading", "", SQ_SetConnected); + g_UISquirrelManager->AddFuncRegistration("void", "NSUpdateListenServer", "", "", SQ_UpdateListenServer); + } } diff --git a/NorthstarDedicatedTest/rpakfilesystem.cpp b/NorthstarDedicatedTest/rpakfilesystem.cpp index 4da22b56..a4c4fada 100644 --- a/NorthstarDedicatedTest/rpakfilesystem.cpp +++ b/NorthstarDedicatedTest/rpakfilesystem.cpp @@ -13,29 +13,88 @@ typedef void* (*LoadPakAsyncType)(const char* path, void* unknownSingleton, int struct PakLoadFuncs { void* unknown[2]; - LoadPakSyncType func2; + LoadPakSyncType LoadPakSync; LoadPakAsyncType LoadPakAsync; }; PakLoadFuncs* g_pakLoadApi; void** pUnknownPakLoadSingleton; -void LoadPakAsync(const char* path) { g_pakLoadApi->LoadPakAsync(path, *pUnknownPakLoadSingleton, 2, nullptr, nullptr); } +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 LoadCommonPaksForMapHook(char* map) +void HandlePakAliases(char** map) { - LoadCommonPaksForMap(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_ModManager->m_loadedMods.size() - 1; i > -1; i--) + { + Mod* mod = &g_ModManager->m_loadedMods[i]; + if (!mod->Enabled) + continue; - // for sp => mp conversions, load the sp rpaks - if (!strcmp(map, "mp_skyway_v1") || !strcmp(map, "mp_crashsite") || !strcmp(map, "mp_hub_timeshift")) - map[0] = 's'; + if (mod->RpakAliases.find(*map) != mod->RpakAliases.end()) + { + *map = &mod->RpakAliases[*map][0]; + return; + } + } +} + +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) + { + if (!mod.Enabled) + continue; + + // need to get a relative path of mod to mod folder + fs::path modPakPath("./" / mod.ModDirectory / "paks"); + + for (ModRpakEntry& pak : mod.Rpaks) + if (pak.m_bAutoLoad) + g_PakLoadManager->LoadPakAsync((modPakPath / pak.m_sPakPath).string().c_str()); + } + + bShouldPreload = true; +} + +LoadPakSyncType LoadPakSyncOriginal; +void* LoadPakSyncHook(char* path, void* unknownSingleton, int flags) +{ + HandlePakAliases(&path); + // 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(); + + spdlog::info("LoadPakSync {}", path); + return LoadPakSyncOriginal(path, unknownSingleton, flags); +} + +LoadPakAsyncType LoadPakAsyncOriginal; +void* LoadPakAsyncHook(char* path, void* unknownSingleton, int flags, void* callback0, void* callback1) +{ + HandlePakAliases(&path); + + if (bShouldPreload) + LoadPreloadPaks(); + + spdlog::info("LoadPakAsync {}", path); + return LoadPakAsyncOriginal(path, unknownSingleton, flags, callback0, callback1); } void InitialiseEngineRpakFilesystem(HMODULE baseAddress) { - g_pakLoadApi = (PakLoadFuncs*)((char*)baseAddress + 0x5BED78); + g_PakLoadManager = new PakLoadManager; + + g_pakLoadApi = *(PakLoadFuncs**)((char*)baseAddress + 0x5BED78); pUnknownPakLoadSingleton = (void**)((char*)baseAddress + 0x7C5E20); HookEnabler hook; - ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x15AD20, &LoadCommonPaksForMapHook, reinterpret_cast<LPVOID*>(&LoadCommonPaksForMap)); + ENABLER_CREATEHOOK(hook, g_pakLoadApi->LoadPakSync, &LoadPakSyncHook, reinterpret_cast<LPVOID*>(&LoadPakSyncOriginal)); + ENABLER_CREATEHOOK(hook, g_pakLoadApi->LoadPakAsync, &LoadPakAsyncHook, reinterpret_cast<LPVOID*>(&LoadPakAsyncOriginal)); }
\ No newline at end of file diff --git a/NorthstarDedicatedTest/rpakfilesystem.h b/NorthstarDedicatedTest/rpakfilesystem.h index a9cc9a93..334104a9 100644 --- a/NorthstarDedicatedTest/rpakfilesystem.h +++ b/NorthstarDedicatedTest/rpakfilesystem.h @@ -1,4 +1,12 @@ #pragma once void InitialiseEngineRpakFilesystem(HMODULE baseAddress); -void LoadPakAsync(char* path);
\ No newline at end of file + +class PakLoadManager +{ + public: + void LoadPakSync(const char* path); + void LoadPakAsync(const char* path); +}; + +extern PakLoadManager* g_PakLoadManager;
\ No newline at end of file diff --git a/NorthstarDedicatedTest/securitypatches.cpp b/NorthstarDedicatedTest/securitypatches.cpp index 3531ffa5..e684738e 100644 --- a/NorthstarDedicatedTest/securitypatches.cpp +++ b/NorthstarDedicatedTest/securitypatches.cpp @@ -4,6 +4,7 @@ #include "concommand.h" #include "dedicated.h" #include "gameutils.h" +#include "convar.h" typedef bool (*IsValveModType)(); IsValveModType IsValveMod; diff --git a/NorthstarDedicatedTest/serverauthentication.cpp b/NorthstarDedicatedTest/serverauthentication.cpp index d766514d..03c3e765 100644 --- a/NorthstarDedicatedTest/serverauthentication.cpp +++ b/NorthstarDedicatedTest/serverauthentication.cpp @@ -1,5 +1,6 @@ #include "pch.h" #include "serverauthentication.h" +#include "cvar.h" #include "convar.h" #include "hookutils.h" #include "masterserver.h" @@ -61,6 +62,8 @@ ConVar* Cvar_net_chan_limit_msec_per_sec; ConVar* Cvar_sv_querylimit_per_sec; ConVar* Cvar_sv_max_chat_messages_per_sec; +ConVar* Cvar_net_datablock_enabled; + void ServerAuthenticationManager::StartPlayerAuthServer() { if (m_runningPlayerAuthThread) @@ -594,6 +597,8 @@ void InitialiseServerAuthentication(HMODULE baseAddress) Cvar_sv_querylimit_per_sec = new ConVar("sv_querylimit_per_sec", "15", FCVAR_GAMEDLL, ""); Cvar_sv_max_chat_messages_per_sec = new ConVar("sv_max_chat_messages_per_sec", "5", FCVAR_GAMEDLL, ""); + Cvar_net_datablock_enabled = g_pCVar->FindVar("net_datablock_enabled"); + RegisterConCommand("ns_resetpersistence", ResetPdataCommand, "resets your pdata when you next enter the lobby", FCVAR_NONE); HookEnabler hook; |