aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKawe Mazidjatari <48657826+Mauler125@users.noreply.github.com>2022-03-15 18:56:48 +0100
committerGitHub <noreply@github.com>2022-03-15 18:56:48 +0100
commitda9e9cf086a62ad48c1afc61ebb0f5cdf48b0b20 (patch)
tree8df74b208368eff46fc8a6d67471f5e967264cd9
parentd6bf4b105aaac9bd061990a8eb455cbfcac25de4 (diff)
parent50e69bde548c5a1af3385f0eff6aa14c088c21c5 (diff)
downloadNorthstarLauncher-da9e9cf086a62ad48c1afc61ebb0f5cdf48b0b20.tar.gz
NorthstarLauncher-da9e9cf086a62ad48c1afc61ebb0f5cdf48b0b20.zip
Merge branch 'main' into NetCon
-rw-r--r--NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj2
-rw-r--r--NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters12
-rw-r--r--NorthstarDedicatedTest/clientchathooks.cpp4
-rw-r--r--NorthstarDedicatedTest/clientvideooverrides.cpp42
-rw-r--r--NorthstarDedicatedTest/clientvideooverrides.h2
-rw-r--r--NorthstarDedicatedTest/dedicated.cpp5
-rw-r--r--NorthstarDedicatedTest/dllmain.cpp3
-rw-r--r--NorthstarDedicatedTest/filesystem.cpp20
-rw-r--r--NorthstarDedicatedTest/gameutils.cpp15
-rw-r--r--NorthstarDedicatedTest/gameutils.h8
-rw-r--r--NorthstarDedicatedTest/logging.cpp2
-rw-r--r--NorthstarDedicatedTest/modmanager.cpp90
-rw-r--r--NorthstarDedicatedTest/modmanager.h21
-rw-r--r--NorthstarDedicatedTest/plugins.cpp38
-rw-r--r--NorthstarDedicatedTest/rpakfilesystem.cpp77
-rw-r--r--NorthstarDedicatedTest/rpakfilesystem.h10
-rw-r--r--NorthstarDedicatedTest/securitypatches.cpp1
-rw-r--r--NorthstarDedicatedTest/serverauthentication.cpp5
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;