aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2023-01-13 14:28:09 +0000
committerGitHub <noreply@github.com>2023-01-13 15:28:09 +0100
commit063260ca0b1f633cf120d79796fe7aa3329c1e26 (patch)
tree1bcc5516729168db6be4981b07115d30a8821da2
parent8bddf5bfe83b52165c589b2dd5e544831a55231d (diff)
downloadNorthstarLauncher-1.12.0.tar.gz
NorthstarLauncher-1.12.0.zip
Execute cfgs before server startup for gamemode being run (#398)v1.12.0-rc5v1.12.0-rc4v1.12.0
* run cfg to initialise gamemode on startup * remove ; characters from mp_gamemode * exec using _Cmd_Exec_f to avoid issues with semicolons in gamemode names allowing additional commands to be run * run from cfg/server/ rather than cfg/ * fixup formatting
-rw-r--r--NorthstarDLL/core/convar/concommand.cpp3
-rw-r--r--NorthstarDLL/engine/hoststate.cpp44
-rw-r--r--NorthstarDLL/engine/r2engine.cpp4
-rw-r--r--NorthstarDLL/engine/r2engine.h2
-rw-r--r--NorthstarDLL/shared/exploit_fixes/exploitfixes.cpp6
-rw-r--r--NorthstarDLL/shared/misccommands.cpp78
6 files changed, 132 insertions, 5 deletions
diff --git a/NorthstarDLL/core/convar/concommand.cpp b/NorthstarDLL/core/convar/concommand.cpp
index 02c9e50f..094fa813 100644
--- a/NorthstarDLL/core/convar/concommand.cpp
+++ b/NorthstarDLL/core/convar/concommand.cpp
@@ -1,9 +1,12 @@
#include "pch.h"
#include "concommand.h"
#include "shared/misccommands.h"
+#include "engine/r2engine.h"
#include <iostream>
+bool (*CCommand__Tokenize)(CCommand& self, const char* pCommandString, R2::cmd_source_t commandSource);
+
//-----------------------------------------------------------------------------
// Purpose: Returns true if this is a command
// Output : bool
diff --git a/NorthstarDLL/engine/hoststate.cpp b/NorthstarDLL/engine/hoststate.cpp
index d474b908..4900539b 100644
--- a/NorthstarDLL/engine/hoststate.cpp
+++ b/NorthstarDLL/engine/hoststate.cpp
@@ -20,9 +20,35 @@ namespace R2
} // namespace R2
ConVar* Cvar_hostport;
+std::string sLastMode;
+
+void (*_fastcall _Cmd_Exec_f)(const CCommand& arg, bool bOnlyIfExists, bool bUseWhitelists);
void ServerStartingOrChangingMap()
{
+ ConVar* Cvar_mp_gamemode = g_pCVar->FindVar("mp_gamemode");
+
+ // directly call _Cmd_Exec_f to avoid weirdness with ; being in mp_gamemode potentially
+ // if we ran exec {mp_gamemode} and mp_gamemode contained semicolons, this could be used to execute more commands
+ char* commandBuf[1040]; // assumedly this is the size of CCommand since we don't have an actual constructor
+ memset(commandBuf, 0, sizeof(commandBuf));
+ CCommand tempCommand = *(CCommand*)&commandBuf;
+ if (sLastMode.length() &&
+ CCommand__Tokenize(
+ tempCommand, fmt::format("exec server/cleanup_gamemode_{}", sLastMode).c_str(), R2::cmd_source_t::kCommandSrcCode))
+ _Cmd_Exec_f(tempCommand, false, false);
+
+ memset(commandBuf, 0, sizeof(commandBuf));
+ if (CCommand__Tokenize(
+ tempCommand,
+ fmt::format("exec server/setup_gamemode_{}", sLastMode = Cvar_mp_gamemode->GetString()).c_str(),
+ R2::cmd_source_t::kCommandSrcCode))
+ {
+ _Cmd_Exec_f(tempCommand, false, false);
+ }
+
+ Cbuf_Execute(); // exec everything right now
+
// net_data_block_enabled is required for sp, force it if we're on an sp map
// sucks for security but just how it be
if (!strncmp(g_pHostState->m_levelName, "sp_", 3))
@@ -119,6 +145,22 @@ void, __fastcall, (CHostState* self))
g_pServerAuthentication->StopPlayerAuthServer();
CHostState__State_GameShutdown(self);
+
+ // run gamemode cleanup cfg now instead of when we start next map
+ if (sLastMode.length())
+ {
+ char* commandBuf[1040]; // assumedly this is the size of CCommand since we don't have an actual constructor
+ memset(commandBuf, 0, sizeof(commandBuf));
+ CCommand tempCommand = *(CCommand*)&commandBuf;
+ if (CCommand__Tokenize(
+ tempCommand, fmt::format("exec server/cleanup_gamemode_{}", sLastMode).c_str(), R2::cmd_source_t::kCommandSrcCode))
+ {
+ _Cmd_Exec_f(tempCommand, false, false);
+ Cbuf_Execute();
+ }
+
+ sLastMode.clear();
+ }
}
// clang-format off
@@ -154,4 +196,6 @@ ON_DLL_LOAD_RELIESON("engine.dll", HostState, ConVar, (CModule module))
g_pHostState = module.Offset(0x7CF180).As<CHostState*>();
Cvar_hostport = module.Offset(0x13FA6070).As<ConVar*>();
+
+ _Cmd_Exec_f = module.Offset(0x1232C0).As<void (*__fastcall)(const CCommand&, bool, bool)>();
}
diff --git a/NorthstarDLL/engine/r2engine.cpp b/NorthstarDLL/engine/r2engine.cpp
index 11233a2d..22884a73 100644
--- a/NorthstarDLL/engine/r2engine.cpp
+++ b/NorthstarDLL/engine/r2engine.cpp
@@ -10,6 +10,8 @@ namespace R2
Cbuf_AddTextType Cbuf_AddText;
Cbuf_ExecuteType Cbuf_Execute;
+ bool (*CCommand__Tokenize)(CCommand& self, const char* pCommandString, R2::cmd_source_t commandSource);
+
CEngine* g_pEngine;
void (*CBaseClient__Disconnect)(void* self, uint32_t unknownButAlways1, const char* reason, ...);
@@ -27,6 +29,8 @@ ON_DLL_LOAD("engine.dll", R2Engine, (CModule module))
Cbuf_AddText = module.Offset(0x1203B0).As<Cbuf_AddTextType>();
Cbuf_Execute = module.Offset(0x1204B0).As<Cbuf_ExecuteType>();
+ CCommand__Tokenize = module.Offset(0x418380).As<bool (*)(CCommand&, const char*, R2::cmd_source_t)>();
+
g_pEngine = module.Offset(0x7D70C8).Deref().As<CEngine*>();
CBaseClient__Disconnect = module.Offset(0x1012C0).As<void (*)(void*, uint32_t, const char*, ...)>();
diff --git a/NorthstarDLL/engine/r2engine.h b/NorthstarDLL/engine/r2engine.h
index a7ed62a3..bc242201 100644
--- a/NorthstarDLL/engine/r2engine.h
+++ b/NorthstarDLL/engine/r2engine.h
@@ -59,6 +59,8 @@ namespace R2
typedef void (*Cbuf_ExecuteType)();
extern Cbuf_ExecuteType Cbuf_Execute;
+ extern bool (*CCommand__Tokenize)(CCommand& self, const char* pCommandString, R2::cmd_source_t commandSource);
+
// CEngine
enum EngineQuitState
diff --git a/NorthstarDLL/shared/exploit_fixes/exploitfixes.cpp b/NorthstarDLL/shared/exploit_fixes/exploitfixes.cpp
index e4430fd4..8cb956e6 100644
--- a/NorthstarDLL/shared/exploit_fixes/exploitfixes.cpp
+++ b/NorthstarDLL/shared/exploit_fixes/exploitfixes.cpp
@@ -266,8 +266,6 @@ bool, __fastcall, (const char* pModName)) // 48 83 EC 28 48 8B 0D ? ? ? ? 48 8D
}
// ratelimit stringcmds, and prevent remote clients from calling commands that they shouldn't
-bool (*CCommand__Tokenize)(CCommand& self, const char* pCommandString, R2::cmd_source_t commandSource);
-
// clang-format off
AUTOHOOK(CGameClient__ExecuteStringCommand, engine.dll + 0x1022E0,
bool, __fastcall, (R2::CBaseClient* self, uint32_t unknown, const char* pCommandString))
@@ -287,7 +285,7 @@ bool, __fastcall, (R2::CBaseClient* self, uint32_t unknown, const char* pCommand
memset(commandBuf, 0, sizeof(commandBuf));
CCommand tempCommand = *(CCommand*)&commandBuf;
- if (!CCommand__Tokenize(tempCommand, pCommandString, R2::cmd_source_t::kCommandSrcCode) || !tempCommand.ArgC())
+ if (!R2::CCommand__Tokenize(tempCommand, pCommandString, R2::cmd_source_t::kCommandSrcCode) || !tempCommand.ArgC())
return false;
ConCommand* command = R2::g_pCVar->FindCommand(tempCommand.Arg(0));
@@ -402,8 +400,6 @@ ON_DLL_LOAD("engine.dll", EngineExploitFixes, (CModule module))
{
AUTOHOOK_DISPATCH_MODULE(engine.dll)
- CCommand__Tokenize = module.Offset(0x418380).As<bool (*)(CCommand&, const char*, R2::cmd_source_t)>();
-
// allow client/ui to run clientcommands despite restricting servercommands
module.Offset(0x4FB65).Patch("EB 11");
module.Offset(0x4FBAC).Patch("EB 16");
diff --git a/NorthstarDLL/shared/misccommands.cpp b/NorthstarDLL/shared/misccommands.cpp
index ad8b2a32..f3817867 100644
--- a/NorthstarDLL/shared/misccommands.cpp
+++ b/NorthstarDLL/shared/misccommands.cpp
@@ -45,6 +45,72 @@ void ConCommand_ns_end_reauth_and_leave_to_lobby(const CCommand& arg)
}
}
+void ConCommand_cvar_setdefaultvalue(const CCommand& arg)
+{
+ if (arg.ArgC() < 3)
+ {
+ spdlog::info("usage: cvar_setdefaultvalue mp_gamemode tdm");
+ return;
+ }
+
+ ConVar* pCvar = R2::g_pCVar->FindVar(arg.Arg(1));
+ if (!pCvar)
+ {
+ spdlog::info("usage: cvar_setdefaultvalue mp_gamemode tdm");
+ return;
+ }
+
+ // unfortunately no way for us to not leak memory here, as default value might not be in writeable memory by default
+ int nLen = strlen(arg.Arg(2));
+ char* pBuf = new char[nLen + 1];
+ strncpy_s(pBuf, nLen + 1, arg.Arg(2), nLen);
+
+ pCvar->m_pszDefaultValue = pBuf;
+}
+
+void ConCommand_cvar_setvalueanddefaultvalue(const CCommand& arg)
+{
+ if (arg.ArgC() < 3)
+ {
+ spdlog::info("usage: cvar_setvalueanddefaultvalue mp_gamemode tdm");
+ return;
+ }
+
+ ConVar* pCvar = R2::g_pCVar->FindVar(arg.Arg(1));
+ if (!pCvar)
+ {
+ spdlog::info("usage: cvar_setvalueanddefaultvalue mp_gamemode tdm");
+ return;
+ }
+
+ // unfortunately no way for us to not leak memory here, as default value might not be in writeable memory by default
+ int nLen = strlen(arg.Arg(2));
+ char* pBuf = new char[nLen + 1];
+ strncpy_s(pBuf, nLen + 1, arg.Arg(2), nLen);
+
+ pCvar->m_pszDefaultValue = pBuf;
+ pCvar->SetValue(pCvar->m_pszDefaultValue);
+}
+
+void ConCommand_cvar_reset(const CCommand& arg)
+{
+ if (arg.ArgC() < 2)
+ {
+ spdlog::info("usage: cvar_reset mp_gamemode");
+ return;
+ }
+
+ ConVar* pCvar = R2::g_pCVar->FindVar(arg.Arg(1));
+ if (!pCvar)
+ {
+ spdlog::info("usage: cvar_reset mp_gamemode");
+ return;
+ }
+
+ // reset cvar
+ pCvar->SetValue(pCvar->m_pszDefaultValue);
+}
+
void AddMiscConCommands()
{
RegisterConCommand(
@@ -61,6 +127,18 @@ void AddMiscConCommands()
// this is a concommand because we make a deferred call to it from another thread
RegisterConCommand("ns_end_reauth_and_leave_to_lobby", ConCommand_ns_end_reauth_and_leave_to_lobby, "", FCVAR_NONE);
+
+ RegisterConCommand(
+ "cvar_setdefaultvalue",
+ ConCommand_cvar_setdefaultvalue,
+ "overwrites the default value of a cvar, for use with script and cvar_reset",
+ FCVAR_NONE);
+ RegisterConCommand(
+ "cvar_setvalueanddefaultvalue",
+ ConCommand_cvar_setvalueanddefaultvalue,
+ "overwrites the current value and default value of a cvar, for use with script and cvar_reset",
+ FCVAR_NONE);
+ RegisterConCommand("cvar_reset", ConCommand_cvar_reset, "resets a cvar's value to its default value", FCVAR_NONE);
}
// fixes up various cvar flags to have more sane values