aboutsummaryrefslogtreecommitdiff
path: root/NorthstarDLL/playlist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'NorthstarDLL/playlist.cpp')
-rw-r--r--NorthstarDLL/playlist.cpp138
1 files changed, 81 insertions, 57 deletions
diff --git a/NorthstarDLL/playlist.cpp b/NorthstarDLL/playlist.cpp
index f3e17a32..4f34dbb1 100644
--- a/NorthstarDLL/playlist.cpp
+++ b/NorthstarDLL/playlist.cpp
@@ -1,106 +1,130 @@
#include "pch.h"
#include "playlist.h"
-#include "nsmem.h"
#include "concommand.h"
#include "convar.h"
-#include "gameutils.h"
-#include "hookutils.h"
#include "squirrel.h"
+#include "hoststate.h"
+#include "serverpresence.h"
-typedef char (*Onclc_SetPlaylistVarOverrideType)(void* a1, void* a2);
-Onclc_SetPlaylistVarOverrideType Onclc_SetPlaylistVarOverride;
+AUTOHOOK_INIT()
-typedef int (*GetCurrentGamemodeMaxPlayersType)();
-GetCurrentGamemodeMaxPlayersType GetCurrentGamemodeMaxPlayers;
-
-// function type defined in gameutils.h
-SetPlaylistVarOverrideType SetPlaylistVarOverrideOriginal;
-GetCurrentPlaylistVarType GetCurrentPlaylistVarOriginal;
+// use the R2 namespace for game funcs
+namespace R2
+{
+ const char* (*GetCurrentPlaylistName)();
+ void (*SetCurrentPlaylist)(const char* pPlaylistName);
+ void (*SetPlaylistVarOverride)(const char* pVarName, const char* pValue);
+ const char* (*GetCurrentPlaylistVar)(const char* pVarName, bool bUseOverrides);
+} // namespace R2
ConVar* Cvar_ns_use_clc_SetPlaylistVarOverride;
-void ConCommand_playlist(const CCommand& args)
+// clang-format off
+AUTOHOOK(clc_SetPlaylistVarOverride__Process, engine.dll + 0x222180,
+char, __fastcall, (void* a1, void* a2))
+// clang-format on
{
- if (args.ArgC() < 2)
- return;
+ // the private_match playlist on mp_lobby is the only situation where there should be any legitimate sending of this netmessage
+ if (!Cvar_ns_use_clc_SetPlaylistVarOverride->GetBool() || strcmp(R2::GetCurrentPlaylistName(), "private_match") ||
+ strcmp(R2::g_pHostState->m_levelName, "mp_lobby"))
+ return 1;
- SetCurrentPlaylist(args.Arg(1));
+ return clc_SetPlaylistVarOverride__Process(a1, a2);
}
-void ConCommand_setplaylistvaroverride(const CCommand& args)
+// clang-format off
+AUTOHOOK(SetCurrentPlaylist, engine.dll + 0x18EB20,
+bool, __fastcall, (const char* pPlaylistName))
+// clang-format on
{
- if (args.ArgC() < 3)
+ bool bSuccess = SetCurrentPlaylist(pPlaylistName);
+
+ if (bSuccess)
+ {
+ spdlog::info("Set playlist to {}", R2::GetCurrentPlaylistName());
+ g_pServerPresence->SetPlaylist(R2::GetCurrentPlaylistName());
+ }
+
+ return bSuccess;
+}
+
+// clang-format off
+AUTOHOOK(SetPlaylistVarOverride, engine.dll + 0x18ED00,
+void, __fastcall, (const char* pVarName, const char* pValue))
+// clang-format on
+{
+ if (strlen(pValue) >= 64)
return;
- for (int i = 1; i < args.ArgC(); i += 2)
- SetPlaylistVarOverride(args.Arg(i), args.Arg(i + 1));
+ SetPlaylistVarOverride(pVarName, pValue);
}
-char Onclc_SetPlaylistVarOverrideHook(void* a1, void* a2)
+// clang-format off
+AUTOHOOK(GetCurrentPlaylistVar, engine.dll + 0x18C680,
+const char*, __fastcall, (const char* pVarName, bool bUseOverrides))
+// clang-format on
{
- // the private_match playlist is the only situation where there should be any legitimate sending of this netmessage
- // todo: check mp_lobby here too
- if (!Cvar_ns_use_clc_SetPlaylistVarOverride->GetBool() || strcmp(GetCurrentPlaylistName(), "private_match"))
- return 1;
+ if (!bUseOverrides && !strcmp(pVarName, "max_players"))
+ bUseOverrides = true;
- return Onclc_SetPlaylistVarOverride(a1, a2);
+ return GetCurrentPlaylistVar(pVarName, bUseOverrides);
}
-void SetPlaylistVarOverrideHook(const char* varName, const char* value)
+// clang-format off
+AUTOHOOK(GetCurrentGamemodeMaxPlayers, engine.dll + 0x18C430,
+int, __fastcall, ())
+// clang-format on
{
- if (strlen(value) >= 64)
- return;
+ const char* pMaxPlayers = R2::GetCurrentPlaylistVar("max_players", 0);
+ if (!pMaxPlayers)
+ return GetCurrentGamemodeMaxPlayers();
- SetPlaylistVarOverrideOriginal(varName, value);
+ int iMaxPlayers = atoi(pMaxPlayers);
+ return iMaxPlayers;
}
-char* GetCurrentPlaylistVarHook(const char* varName, bool useOverrides)
+void ConCommand_playlist(const CCommand& args)
{
- if (!useOverrides && !strcmp(varName, "max_players"))
- useOverrides = true;
+ if (args.ArgC() < 2)
+ return;
- return GetCurrentPlaylistVarOriginal(varName, useOverrides);
+ R2::SetCurrentPlaylist(args.Arg(1));
}
-int GetCurrentGamemodeMaxPlayersHook()
+void ConCommand_setplaylistvaroverride(const CCommand& args)
{
- char* maxPlayersStr = GetCurrentPlaylistVar("max_players", 0);
- if (!maxPlayersStr)
- return GetCurrentGamemodeMaxPlayers();
+ if (args.ArgC() < 3)
+ return;
- int maxPlayers = atoi(maxPlayersStr);
- return maxPlayers;
+ for (int i = 1; i < args.ArgC(); i += 2)
+ R2::SetPlaylistVarOverride(args.Arg(i), args.Arg(i + 1));
}
-void InitialisePlaylistHooks(HMODULE baseAddress)
+ON_DLL_LOAD_RELIESON("engine.dll", PlaylistHooks, (ConCommand, ConVar), (CModule module))
{
+ AUTOHOOK_DISPATCH()
+
+ R2::GetCurrentPlaylistName = module.Offset(0x18C640).As<const char* (*)()>();
+ R2::SetCurrentPlaylist = module.Offset(0x18EB20).As<void (*)(const char*)>();
+ R2::SetPlaylistVarOverride = module.Offset(0x18ED00).As<void (*)(const char*, const char*)>();
+ R2::GetCurrentPlaylistVar = module.Offset(0x18C680).As<const char* (*)(const char*, bool)>();
+
+ // playlist is the name of the command on respawn servers, but we already use setplaylist so can't get rid of it
+ RegisterConCommand("playlist", ConCommand_playlist, "Sets the current playlist", FCVAR_NONE);
RegisterConCommand("setplaylist", ConCommand_playlist, "Sets the current playlist", FCVAR_NONE);
RegisterConCommand("setplaylistvaroverrides", ConCommand_setplaylistvaroverride, "sets a playlist var override", FCVAR_NONE);
+
// note: clc_SetPlaylistVarOverride is pretty insecure, since it allows for entirely arbitrary playlist var overrides to be sent to the
- // server this is somewhat restricted on custom servers to prevent it being done outside of private matches, but ideally it should be
+ // server, this is somewhat restricted on custom servers to prevent it being done outside of private matches, but ideally it should be
// disabled altogether, since the custom menus won't use it anyway this should only really be accepted if you want vanilla client
// compatibility
Cvar_ns_use_clc_SetPlaylistVarOverride = new ConVar(
"ns_use_clc_SetPlaylistVarOverride", "0", FCVAR_GAMEDLL, "Whether the server should accept clc_SetPlaylistVarOverride messages");
- HookEnabler hook;
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x222180, &Onclc_SetPlaylistVarOverrideHook, reinterpret_cast<LPVOID*>(&Onclc_SetPlaylistVarOverride));
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x18ED00, &SetPlaylistVarOverrideHook, reinterpret_cast<LPVOID*>(&SetPlaylistVarOverrideOriginal));
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x18C680, &GetCurrentPlaylistVarHook, reinterpret_cast<LPVOID*>(&GetCurrentPlaylistVarOriginal));
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x18C430, &GetCurrentGamemodeMaxPlayersHook, reinterpret_cast<LPVOID*>(&GetCurrentGamemodeMaxPlayers));
-
- uintptr_t ba = (uintptr_t)baseAddress;
-
// patch to prevent clc_SetPlaylistVarOverride from being able to crash servers if we reach max overrides due to a call to Error (why is
// this possible respawn, wtf) todo: add a warning for this
- {
- NSMem::BytePatch(ba + 0x18ED8D, "C3");
- }
+ module.Offset(0x18ED8D).Patch("C3");
// patch to allow setplaylistvaroverride to be called before map init on dedicated and private match launched through the game
- NSMem::NOP(ba + 0x18ED17, 6);
+ module.Offset(0x18ED17).NOP(6);
}