aboutsummaryrefslogtreecommitdiff
path: root/NorthstarDLL/playlist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'NorthstarDLL/playlist.cpp')
-rw-r--r--NorthstarDLL/playlist.cpp106
1 files changed, 106 insertions, 0 deletions
diff --git a/NorthstarDLL/playlist.cpp b/NorthstarDLL/playlist.cpp
new file mode 100644
index 00000000..fdb23893
--- /dev/null
+++ b/NorthstarDLL/playlist.cpp
@@ -0,0 +1,106 @@
+#include "pch.h"
+#include "playlist.h"
+#include "concommand.h"
+#include "convar.h"
+#include "gameutils.h"
+#include "hookutils.h"
+#include "squirrel.h"
+
+typedef char (*Onclc_SetPlaylistVarOverrideType)(void* a1, void* a2);
+Onclc_SetPlaylistVarOverrideType Onclc_SetPlaylistVarOverride;
+
+typedef int (*GetCurrentGamemodeMaxPlayersType)();
+GetCurrentGamemodeMaxPlayersType GetCurrentGamemodeMaxPlayers;
+
+// function type defined in gameutils.h
+SetPlaylistVarOverrideType SetPlaylistVarOverrideOriginal;
+GetCurrentPlaylistVarType GetCurrentPlaylistVarOriginal;
+
+ConVar* Cvar_ns_use_clc_SetPlaylistVarOverride;
+
+void SetPlaylistCommand(const CCommand& args)
+{
+ if (args.ArgC() < 2)
+ return;
+
+ SetCurrentPlaylist(args.Arg(1));
+}
+
+void SetPlaylistVarOverrideCommand(const CCommand& args)
+{
+ if (args.ArgC() < 3)
+ return;
+
+ for (int i = 1; i < args.ArgC(); i += 2)
+ SetPlaylistVarOverride(args.Arg(i), args.Arg(i + 1));
+}
+
+char Onclc_SetPlaylistVarOverrideHook(void* a1, void* a2)
+{
+ // 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;
+
+ return Onclc_SetPlaylistVarOverride(a1, a2);
+}
+
+void SetPlaylistVarOverrideHook(const char* varName, const char* value)
+{
+ if (strlen(value) >= 64)
+ return;
+
+ SetPlaylistVarOverrideOriginal(varName, value);
+}
+
+char* GetCurrentPlaylistVarHook(const char* varName, bool useOverrides)
+{
+ if (!useOverrides && !strcmp(varName, "max_players"))
+ useOverrides = true;
+
+ return GetCurrentPlaylistVarOriginal(varName, useOverrides);
+}
+
+int GetCurrentGamemodeMaxPlayersHook()
+{
+ char* maxPlayersStr = GetCurrentPlaylistVar("max_players", 0);
+ if (!maxPlayersStr)
+ return GetCurrentGamemodeMaxPlayers();
+
+ int maxPlayers = atoi(maxPlayersStr);
+ return maxPlayers;
+}
+
+#include "NSMem.h"
+void InitialisePlaylistHooks(HMODULE baseAddress)
+{
+ RegisterConCommand("setplaylist", SetPlaylistCommand, "Sets the current playlist", FCVAR_NONE);
+ RegisterConCommand("setplaylistvaroverrides", SetPlaylistVarOverrideCommand, "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
+ // 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");
+ }
+
+ // patch to allow setplaylistvaroverride to be called before map init on dedicated and private match launched through the game
+ NSMem::NOP(ba + 0x18ED17, 6);
+} \ No newline at end of file