diff options
29 files changed, 348 insertions, 319 deletions
diff --git a/NorthstarDedicatedTest/ExploitFixes.cpp b/NorthstarDedicatedTest/ExploitFixes.cpp index 935e3f63..ff0af8f9 100644 --- a/NorthstarDedicatedTest/ExploitFixes.cpp +++ b/NorthstarDedicatedTest/ExploitFixes.cpp @@ -322,7 +322,6 @@ INVALID_CMD: // basically: by default r2 isn't set as a valve mod, meaning that m_bRestrictServerCommands is false // this is HORRIBLE for security, because it means servers can run arbitrary concommands on clients // especially since we have script commands this could theoretically be awful -#include "gameutils.h" KHOOK(IsValveMod, ("engine.dll", "48 83 EC 28 48 8B 0D ? ? ? ? 48 8D 15 ? ? ? ? E8 ? ? ? ? 85 C0 74 63"), bool, __fastcall, ()) { return !Tier0::CommandLine()->CheckParm("-norestrictservercommands"); diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj index 172ad4ca..d20cb69e 100644 --- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj +++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj @@ -132,6 +132,9 @@ <ClInclude Include="ns_version.h" /> <ClInclude Include="plugins.h" /> <ClInclude Include="plugin_abi.h" /> + <ClInclude Include="r2client.h" /> + <ClInclude Include="r2engine.h" /> + <ClInclude Include="r2server.h" /> <ClInclude Include="serverchathooks.h" /> <ClInclude Include="clientauthhooks.h" /> <ClInclude Include="color.h" /> @@ -142,7 +145,6 @@ <ClInclude Include="dedicated.h" /> <ClInclude Include="dedicatedmaterialsystem.h" /> <ClInclude Include="filesystem.h" /> - <ClInclude Include="gameutils.h" /> <ClInclude Include="hooks.h" /> <ClInclude Include="hookutils.h" /> <ClInclude Include="include\crypto\aes_platform.h" /> @@ -598,7 +600,6 @@ <ClCompile Include="demofixes.cpp" /> <ClCompile Include="dllmain.cpp" /> <ClCompile Include="filesystem.cpp" /> - <ClCompile Include="gameutils.cpp" /> <ClCompile Include="hooks.cpp" /> <ClCompile Include="hookutils.cpp" /> <ClCompile Include="host.cpp" /> @@ -625,6 +626,9 @@ <ClCompile Include="playlist.cpp" /> <ClCompile Include="plugins.cpp" /> <ClCompile Include="commandprint.cpp" /> + <ClCompile Include="r2client.cpp" /> + <ClCompile Include="r2engine.cpp" /> + <ClCompile Include="r2server.cpp" /> <ClCompile Include="rpakfilesystem.cpp" /> <ClCompile Include="scriptbrowserhooks.cpp" /> <ClCompile Include="scriptmainmenupromos.cpp" /> diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters index 8f63935b..d3796ff5 100644 --- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters +++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters @@ -600,9 +600,6 @@ <ClInclude Include="clientauthhooks.h"> <Filter>Header Files\Client</Filter> </ClInclude> - <ClInclude Include="gameutils.h"> - <Filter>Header Files\Shared\Game Functions</Filter> - </ClInclude> <ClInclude Include="memalloc.h"> <Filter>Header Files\Shared</Filter> </ClInclude> @@ -1545,6 +1542,15 @@ <ClInclude Include="demofixes.h"> <Filter>Header Files\Client</Filter> </ClInclude> + <ClInclude Include="r2engine.h"> + <Filter>Header Files\Shared\Game Functions</Filter> + </ClInclude> + <ClInclude Include="r2server.h"> + <Filter>Header Files\Shared\Game Functions</Filter> + </ClInclude> + <ClInclude Include="r2client.h"> + <Filter>Header Files\Shared\Game Functions</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="dllmain.cpp"> @@ -1601,9 +1607,6 @@ <ClCompile Include="masterserver.cpp"> <Filter>Source Files\Shared</Filter> </ClCompile> - <ClCompile Include="gameutils.cpp"> - <Filter>Source Files\Shared\Game Functions</Filter> - </ClCompile> <ClCompile Include="chatcommand.cpp"> <Filter>Source Files\Client</Filter> </ClCompile> @@ -1727,6 +1730,15 @@ <ClCompile Include="mapsprint.cpp"> <Filter>Source Files\Shared\Console</Filter> </ClCompile> + <ClCompile Include="r2client.cpp"> + <Filter>Source Files\Shared\Game Functions</Filter> + </ClCompile> + <ClCompile Include="r2server.cpp"> + <Filter>Source Files\Shared\Game Functions</Filter> + </ClCompile> + <ClCompile Include="r2engine.cpp"> + <Filter>Source Files\Shared\Game Functions</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <MASM Include="audio_asm.asm"> diff --git a/NorthstarDedicatedTest/clientauthhooks.cpp b/NorthstarDedicatedTest/clientauthhooks.cpp index 4784dada..b2dc8ce5 100644 --- a/NorthstarDedicatedTest/clientauthhooks.cpp +++ b/NorthstarDedicatedTest/clientauthhooks.cpp @@ -2,9 +2,9 @@ #include "hooks.h" #include "clientauthhooks.h" #include "hookutils.h" -#include "gameutils.h" #include "masterserver.h" #include "convar.h" +#include "r2client.h" ConVar* Cvar_ns_has_agreed_to_send_token; @@ -24,10 +24,10 @@ void AuthWithStryderHook(void* a1) // if player has agreed to send token and we aren't already authing, try to auth if (Cvar_ns_has_agreed_to_send_token->GetInt() == AGREED_TO_SEND_TOKEN && !g_MasterServerManager->m_bOriginAuthWithMasterServerInProgress) - g_MasterServerManager->AuthenticateOriginWithMasterServer(g_LocalPlayerUserID, g_LocalPlayerOriginToken); + g_MasterServerManager->AuthenticateOriginWithMasterServer(R2::g_LocalPlayerUserID, R2::g_LocalPlayerOriginToken); // invalidate key so auth will fail - *g_LocalPlayerOriginToken = 0; + *R2::g_LocalPlayerOriginToken = 0; } AuthWithStryder(a1); diff --git a/NorthstarDedicatedTest/concommand.cpp b/NorthstarDedicatedTest/concommand.cpp index 5f86ba32..b5da2118 100644 --- a/NorthstarDedicatedTest/concommand.cpp +++ b/NorthstarDedicatedTest/concommand.cpp @@ -1,29 +1,9 @@ #include "pch.h" #include "hooks.h" #include "concommand.h" -#include "gameutils.h" #include "misccommands.h" #include <iostream> -typedef void (*ConCommandConstructorType)( - ConCommand* newCommand, const char* name, void (*callback)(const CCommand&), const char* helpString, int flags, void* parent); -ConCommandConstructorType conCommandConstructor; - -void RegisterConCommand(const char* name, void (*callback)(const CCommand&), const char* helpString, int flags) -{ - spdlog::info("Registering ConCommand {}", name); - - // no need to free this ever really, it should exist as long as game does - ConCommand* newCommand = new ConCommand; - conCommandConstructor(newCommand, name, callback, helpString, flags, nullptr); -} - -ON_DLL_LOAD("engine.dll", ConCommand, [](HMODULE baseAddress) -{ - conCommandConstructor = (ConCommandConstructorType)((char*)baseAddress + 0x415F60); - AddMiscConCommands(); -}) - //----------------------------------------------------------------------------- // Purpose: Returns true if this is a command // Output : bool @@ -139,3 +119,33 @@ char* ConCommandBase::CopyString(const char* szFrom) const } return szTo; } + +typedef void (*ConCommandConstructorType)( + ConCommand* newCommand, const char* name, FnCommandCallback_t callback, const char* helpString, int flags, void* parent); +ConCommandConstructorType ConCommandConstructor; + +void RegisterConCommand(const char* name, FnCommandCallback_t callback, const char* helpString, int flags) +{ + spdlog::info("Registering ConCommand {}", name); + + // no need to free this ever really, it should exist as long as game does + ConCommand* newCommand = new ConCommand; + ConCommandConstructor(newCommand, name, callback, helpString, flags, nullptr); +} + +void RegisterConCommand( + const char* name, FnCommandCallback_t callback, const char* helpString, int flags, FnCommandCompletionCallback completionCallback) +{ + spdlog::info("Registering ConCommand {}", name); + + // no need to free this ever really, it should exist as long as game does + ConCommand* newCommand = new ConCommand; + ConCommandConstructor(newCommand, name, callback, helpString, flags, nullptr); + newCommand->m_pCompletionCallback = completionCallback; +} + +ON_DLL_LOAD("engine.dll", ConCommand, [](HMODULE baseAddress) +{ + ConCommandConstructor = (ConCommandConstructorType)((char*)baseAddress + 0x415F60); + AddMiscConCommands(); +})
\ No newline at end of file diff --git a/NorthstarDedicatedTest/concommand.h b/NorthstarDedicatedTest/concommand.h index ec0b6c9e..c11c7ea4 100644 --- a/NorthstarDedicatedTest/concommand.h +++ b/NorthstarDedicatedTest/concommand.h @@ -135,5 +135,5 @@ class ConCommand : public ConCommandBase }; // Size: 0x0060 void RegisterConCommand(const char* name, void (*callback)(const CCommand&), const char* helpString, int flags); - -#define MAKE_CONCMD(name, helpStr, flags, fn) RegisterConCommand(name, fn, helpStr, flags); +void RegisterConCommand( + const char* name, void (*callback)(const CCommand&), const char* helpString, int flags, FnCommandCompletionCallback completionCallback); diff --git a/NorthstarDedicatedTest/convar.cpp b/NorthstarDedicatedTest/convar.cpp index 8a2fee88..df570da9 100644 --- a/NorthstarDedicatedTest/convar.cpp +++ b/NorthstarDedicatedTest/convar.cpp @@ -4,7 +4,6 @@ #include "cvar.h" #include "convar.h" #include "hookutils.h" -#include "gameutils.h" #include "sourceinterface.h" typedef void (*ConVarRegisterType)( diff --git a/NorthstarDedicatedTest/dedicated.cpp b/NorthstarDedicatedTest/dedicated.cpp index 2df43fe9..6f7a4a73 100644 --- a/NorthstarDedicatedTest/dedicated.cpp +++ b/NorthstarDedicatedTest/dedicated.cpp @@ -2,9 +2,9 @@ #include "hooks.h" #include "dedicated.h" #include "hookutils.h" -#include "gameutils.h" #include "tier0.h" #include "playlist.h" +#include "r2engine.h" #include "hoststate.h" #include "serverauthentication.h" #include "masterserver.h" diff --git a/NorthstarDedicatedTest/dedicatedmaterialsystem.cpp b/NorthstarDedicatedTest/dedicatedmaterialsystem.cpp index 13416b08..2e5c1321 100644 --- a/NorthstarDedicatedTest/dedicatedmaterialsystem.cpp +++ b/NorthstarDedicatedTest/dedicatedmaterialsystem.cpp @@ -4,7 +4,6 @@ #include "dedicated.h" #include "dedicatedmaterialsystem.h" #include "hookutils.h" -#include "gameutils.h" #include "tier0.h" #include "NSMem.h" diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp index bb6f19f3..4c81c49d 100644 --- a/NorthstarDedicatedTest/dllmain.cpp +++ b/NorthstarDedicatedTest/dllmain.cpp @@ -4,7 +4,6 @@ #include "logging.h" #include "keyvalues.h" #include "masterserver.h" -#include "gameutils.h" #include "tier0.h" #include "memalloc.h" #include "maxplayers.h" @@ -166,9 +165,6 @@ bool InitialiseNorthstar() // Write launcher version to log spdlog::info("NorthstarLauncher version: {}", version); - AddDllLoadCallback("engine.dll", InitialiseEngineGameUtilFunctions); - AddDllLoadCallback("server.dll", InitialiseServerGameUtilFunctions); - // run callbacks for any libraries that are already loaded by now CallAllPendingDLLLoadCallbacks(); diff --git a/NorthstarDedicatedTest/gameutils.cpp b/NorthstarDedicatedTest/gameutils.cpp deleted file mode 100644 index ce96a5e5..00000000 --- a/NorthstarDedicatedTest/gameutils.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "pch.h" -#include "convar.h" -#include "gameutils.h" -#include "hoststate.h" - -// cmd.h -Cbuf_GetCurrentPlayerType Cbuf_GetCurrentPlayer; -Cbuf_AddTextType Cbuf_AddText; -Cbuf_ExecuteType Cbuf_Execute; - -// cengine stuff -CEngine* g_pEngine; -server_state_t* sv_m_State; - -// server entity stuff -Server_GetEntityByIndexType Server_GetEntityByIndex; - -// auth -char* g_LocalPlayerUserID; -char* g_LocalPlayerOriginToken; - -// misc stuff -GetBaseLocalClientType GetBaseLocalClient; - -void InitialiseEngineGameUtilFunctions(HMODULE baseAddress) -{ - Cbuf_GetCurrentPlayer = (Cbuf_GetCurrentPlayerType)((char*)baseAddress + 0x120630); - Cbuf_AddText = (Cbuf_AddTextType)((char*)baseAddress + 0x1203B0); - Cbuf_Execute = (Cbuf_ExecuteType)((char*)baseAddress + 0x1204B0); - - R2::g_pHostState = (R2::CHostState*)((char*)baseAddress + 0x7CF180); - g_pEngine = *(CEngine**)((char*)baseAddress + 0x7D70C8); - sv_m_State = (server_state_t*)((char*)baseAddress + 0x12A53D48); - - g_LocalPlayerUserID = (char*)baseAddress + 0x13F8E688; - g_LocalPlayerOriginToken = (char*)baseAddress + 0x13979C80; - - GetBaseLocalClient = (GetBaseLocalClientType)((char*)baseAddress + 0x78200); - - /* NOTE: - g_pCVar->FindVar("convar_name") now works. These are no longer needed. - You can also itterate over every ConVar using CCVarIteratorInternal - dump the pointers to a vector and access them from there. - Example: - std::vector<ConVar*> g_pAllConVars; - for (auto& map : g_pCVar->DumpToMap()) - { - ConVar* pConVar = g_pCVar->FindVar(map.first.c_str()); - if (pConVar) - { - g_pAllConVars.push_back(pConVar); - } - }*/ -} - -void InitialiseServerGameUtilFunctions(HMODULE baseAddress) -{ - Server_GetEntityByIndex = (Server_GetEntityByIndexType)((char*)baseAddress + 0xFB820); -}
\ No newline at end of file diff --git a/NorthstarDedicatedTest/gameutils.h b/NorthstarDedicatedTest/gameutils.h deleted file mode 100644 index d53c7abe..00000000 --- a/NorthstarDedicatedTest/gameutils.h +++ /dev/null @@ -1,125 +0,0 @@ -#pragma once -#include "convar.h" - -// cmd.h -enum class ECommandTarget_t -{ - CBUF_FIRST_PLAYER = 0, - CBUF_LAST_PLAYER = 1, // MAX_SPLITSCREEN_CLIENTS - 1, MAX_SPLITSCREEN_CLIENTS = 2 - CBUF_SERVER = CBUF_LAST_PLAYER + 1, - - CBUF_COUNT, -}; - -enum class cmd_source_t -{ - // Added to the console buffer by gameplay code. Generally unrestricted. - kCommandSrcCode, - - // Sent from code via engine->ClientCmd, which is restricted to commands visible - // via FCVAR_CLIENTCMD_CAN_EXECUTE. - kCommandSrcClientCmd, - - // Typed in at the console or via a user key-bind. Generally unrestricted, although - // the client will throttle commands sent to the server this way to 16 per second. - kCommandSrcUserInput, - - // Came in over a net connection as a clc_stringcmd - // host_client will be valid during this state. - // - // Restricted to FCVAR_GAMEDLL commands (but not convars) and special non-ConCommand - // server commands hardcoded into gameplay code (e.g. "joingame") - kCommandSrcNetClient, - - // Received from the server as the client - // - // Restricted to commands with FCVAR_SERVER_CAN_EXECUTE - kCommandSrcNetServer, - - // Being played back from a demo file - // - // Not currently restricted by convar flag, but some commands manually ignore calls - // from this source. FIXME: Should be heavily restricted as demo commands can come - // from untrusted sources. - kCommandSrcDemoFile, - - // Invalid value used when cleared - kCommandSrcInvalid = -1 -}; - -typedef ECommandTarget_t (*Cbuf_GetCurrentPlayerType)(); -extern Cbuf_GetCurrentPlayerType Cbuf_GetCurrentPlayer; - -// compared to the defs i've seen, this is missing an arg, it could be nTickInterval or source, not sure, guessing it's source -typedef void (*Cbuf_AddTextType)(ECommandTarget_t eTarget, const char* text, cmd_source_t source); -extern Cbuf_AddTextType Cbuf_AddText; - -typedef void (*Cbuf_ExecuteType)(); -extern Cbuf_ExecuteType Cbuf_Execute; - -// cengine stuff -enum EngineQuitState -{ - QUIT_NOTQUITTING = 0, - QUIT_TODESKTOP, - QUIT_RESTART -}; - -enum EngineState_t -{ - DLL_INACTIVE = 0, // no dll - DLL_ACTIVE, // engine is focused - DLL_CLOSE, // closing down dll - DLL_RESTART, // engine is shutting down but will restart right away - DLL_PAUSED, // engine is paused, can become active from this state -}; - -class CEngine -{ - public: - virtual void unknown() {} // unsure if this is where - virtual bool Load(bool dedicated, const char* baseDir) {} - virtual void Unload() {} - virtual void SetNextState(EngineState_t iNextState) {} - virtual EngineState_t GetState() {} - virtual void Frame() {} - virtual double GetFrameTime() {} - virtual float GetCurTime() {} - - EngineQuitState m_nQuitting; - EngineState_t m_nDllState; - EngineState_t m_nNextDllState; - double m_flCurrentTime; - float m_flFrameTime; - double m_flPreviousTime; - float m_flFilteredTime; - float m_flMinFrameTime; // Expected duration of a frame, or zero if it is unlimited. -}; - -extern CEngine* g_pEngine; - -enum server_state_t -{ - ss_dead = 0, // Dead - ss_loading, // Spawning - ss_active, // Running - ss_paused, // Running, but paused -}; - -extern server_state_t* sv_m_State; - -// server entity stuff -typedef void* (*Server_GetEntityByIndexType)(int index); -extern Server_GetEntityByIndexType Server_GetEntityByIndex; - -// auth -extern char* g_LocalPlayerUserID; -extern char* g_LocalPlayerOriginToken; - -// misc stuff - -typedef void* (*GetBaseLocalClientType)(); -extern GetBaseLocalClientType GetBaseLocalClient; - -void InitialiseEngineGameUtilFunctions(HMODULE baseAddress); -void InitialiseServerGameUtilFunctions(HMODULE baseAddress);
\ No newline at end of file diff --git a/NorthstarDedicatedTest/host.cpp b/NorthstarDedicatedTest/host.cpp index 624809b5..a67e0ede 100644 --- a/NorthstarDedicatedTest/host.cpp +++ b/NorthstarDedicatedTest/host.cpp @@ -2,9 +2,9 @@ #include "host.h" #include "convar.h" #include "modmanager.h" -#include "gameutils.h" #include "commandprint.h" #include "mapsprint.h" +#include "r2engine.h" typedef void (*Host_InitType)(bool bDedicated); Host_InitType Host_Init; @@ -54,7 +54,7 @@ void Host_InitHook(bool bDedicated) // run client autoexec if on client if (!bDedicated) - Cbuf_AddText(Cbuf_GetCurrentPlayer(), "exec autoexec_ns_client", cmd_source_t::kCommandSrcCode); + R2::Cbuf_AddText(R2::Cbuf_GetCurrentPlayer(), "exec autoexec_ns_client", R2::cmd_source_t::kCommandSrcCode); } ON_DLL_LOAD("engine.dll", Host_Init, [](HMODULE baseAddress) diff --git a/NorthstarDedicatedTest/hoststate.cpp b/NorthstarDedicatedTest/hoststate.cpp index 4782b559..63d313f8 100644 --- a/NorthstarDedicatedTest/hoststate.cpp +++ b/NorthstarDedicatedTest/hoststate.cpp @@ -3,8 +3,8 @@ #include "masterserver.h" #include "serverauthentication.h" #include "playlist.h" -#include "gameutils.h" #include "tier0.h" +#include "r2engine.h" using namespace R2; @@ -94,8 +94,7 @@ void CHostState__State_GameShutdownHook(CHostState* hostState) ON_DLL_LOAD_RELIESON("engine.dll", HostState, ConVar, [](HMODULE baseAddress) { - Cvar_hostname = *(ConVar**)((char*)baseAddress + 0x1315bae8); - Cvar_hostport = (ConVar*)((char*)baseAddress + 0x13FA6070); + g_pHostState = (CHostState*)((char*)baseAddress + 0x7CF180); HookEnabler hook; ENABLER_CREATEHOOK( diff --git a/NorthstarDedicatedTest/languagehooks.cpp b/NorthstarDedicatedTest/languagehooks.cpp index 13288826..e5063359 100644 --- a/NorthstarDedicatedTest/languagehooks.cpp +++ b/NorthstarDedicatedTest/languagehooks.cpp @@ -1,7 +1,6 @@ #include "pch.h" #include "hooks.h" #include "languagehooks.h" -#include "gameutils.h" #include "tier0.h" #include <filesystem> #include <regex> diff --git a/NorthstarDedicatedTest/masterserver.cpp b/NorthstarDedicatedTest/masterserver.cpp index f8e9a6fa..229b2f95 100644 --- a/NorthstarDedicatedTest/masterserver.cpp +++ b/NorthstarDedicatedTest/masterserver.cpp @@ -1,23 +1,22 @@ #include "pch.h" #include "masterserver.h" -#include "hooks.h" #include "concommand.h" -#include "gameutils.h" #include "playlist.h" -#include "hookutils.h" #include "serverauthentication.h" -#include "gameutils.h" #include "hoststate.h" #include "tier0.h" +#include "r2engine.h" +#include "modmanager.h" +#include "misccommands.h" +#include "version.h" + #include "rapidjson/document.h" #include "rapidjson/stringbuffer.h" #include "rapidjson/writer.h" #include "rapidjson/error/en.h" -#include "modmanager.h" -#include "misccommands.h" + #include <cstring> #include <regex> -#include "version.h" ConVar* Cvar_ns_masterserver_hostname; ConVar* Cvar_ns_report_server_to_masterserver; @@ -622,7 +621,7 @@ void MasterServerManager::AuthenticateWithOwnServer(const char* uid, const char* if (m_bNewgameAfterSelfAuth) { // pretty sure this is threadsafe? - Cbuf_AddText(Cbuf_GetCurrentPlayer(), "ns_end_reauth_and_leave_to_lobby", cmd_source_t::kCommandSrcCode); + R2::Cbuf_AddText(R2::Cbuf_GetCurrentPlayer(), "ns_end_reauth_and_leave_to_lobby", R2::cmd_source_t::kCommandSrcCode); m_bNewgameAfterSelfAuth = false; } diff --git a/NorthstarDedicatedTest/maxplayers.cpp b/NorthstarDedicatedTest/maxplayers.cpp index 3968120a..9e82c014 100644 --- a/NorthstarDedicatedTest/maxplayers.cpp +++ b/NorthstarDedicatedTest/maxplayers.cpp @@ -1,7 +1,6 @@ #include "pch.h" #include "hooks.h" #include "maxplayers.h" -#include "gameutils.h" #include "tier0.h" // never set this to anything below 32 diff --git a/NorthstarDedicatedTest/misccommands.cpp b/NorthstarDedicatedTest/misccommands.cpp index d74e6e5a..fd04a7fe 100644 --- a/NorthstarDedicatedTest/misccommands.cpp +++ b/NorthstarDedicatedTest/misccommands.cpp @@ -1,62 +1,65 @@ #include "pch.h" #include "misccommands.h" #include "concommand.h" -#include "gameutils.h" #include "playlist.h" +#include "r2engine.h" +#include "r2client.h" #include "hoststate.h" #include "masterserver.h" #include "serverauthentication.h" #include "squirrel.h" +void ConCommand_force_newgame(const CCommand& arg) +{ + if (arg.ArgC() < 2) + return; + + R2::g_pHostState->m_iNextState = R2::HostState_t::HS_NEW_GAME; + strncpy(R2::g_pHostState->m_levelName, arg.Arg(1), sizeof(R2::g_pHostState->m_levelName)); +} + +void ConCommand_ns_start_reauth_and_leave_to_lobby(const CCommand& arg) +{ + // hack for special case where we're on a local server, so we erase our own newly created auth data on disconnect + g_MasterServerManager->m_bNewgameAfterSelfAuth = true; + g_MasterServerManager->AuthenticateWithOwnServer(R2::g_LocalPlayerUserID, g_MasterServerManager->m_sOwnClientAuthToken); +} + +void ConCommand_ns_end_reauth_and_leave_to_lobby(const CCommand& arg) +{ + R2::Cbuf_AddText( + R2::Cbuf_GetCurrentPlayer(), + fmt::format("serverfilter {}", g_ServerAuthenticationManager->m_authData.begin()->first).c_str(), + R2::cmd_source_t::kCommandSrcCode); + R2::Cbuf_Execute(); + + // weird way of checking, but check if client script vm is initialised, mainly just to allow players to cancel this + if (g_pClientSquirrel->sqvm) + { + g_ServerAuthenticationManager->m_bNeedLocalAuthForNewgame = true; + + // this won't set playlist correctly on remote clients, don't think they can set playlist until they've left which sorta + // fucks things should maybe set this in HostState_NewGame? + R2::SetCurrentPlaylist("tdm"); + strcpy(R2::g_pHostState->m_levelName, "mp_lobby"); + R2::g_pHostState->m_iNextState = R2::HostState_t::HS_NEW_GAME; + } +} + void AddMiscConCommands() { - MAKE_CONCMD( + RegisterConCommand( "force_newgame", + ConCommand_force_newgame, "forces a map load through directly setting g_pHostState->m_iNextState to HS_NEW_GAME", - FCVAR_NONE, - [](const CCommand& arg) - { - if (arg.ArgC() < 2) - return; - - R2::g_pHostState->m_iNextState = R2::HostState_t::HS_NEW_GAME; - strncpy(R2::g_pHostState->m_levelName, arg.Arg(1), sizeof(R2::g_pHostState->m_levelName)); - }); + FCVAR_NONE); - MAKE_CONCMD( + RegisterConCommand( "ns_start_reauth_and_leave_to_lobby", + ConCommand_ns_start_reauth_and_leave_to_lobby, "called by the server, used to reauth and return the player to lobby when leaving a game", - FCVAR_SERVER_CAN_EXECUTE, - [](const CCommand& arg) - { - // hack for special case where we're on a local server, so we erase our own newly created auth data on disconnect - g_MasterServerManager->m_bNewgameAfterSelfAuth = true; - g_MasterServerManager->AuthenticateWithOwnServer(g_LocalPlayerUserID, g_MasterServerManager->m_sOwnClientAuthToken); - }); + FCVAR_SERVER_CAN_EXECUTE); // this is a concommand because we make a deferred call to it from another thread - MAKE_CONCMD( - "ns_end_reauth_and_leave_to_lobby", - "", - FCVAR_NONE, - [](const CCommand& arg) - { - Cbuf_AddText( - Cbuf_GetCurrentPlayer(), - fmt::format("serverfilter {}", g_ServerAuthenticationManager->m_authData.begin()->first).c_str(), - cmd_source_t::kCommandSrcCode); - Cbuf_Execute(); - - // weird way of checking, but check if client script vm is initialised, mainly just to allow players to cancel this - if (g_pClientSquirrel->sqvm) - { - g_ServerAuthenticationManager->m_bNeedLocalAuthForNewgame = true; - - // this won't set playlist correctly on remote clients, don't think they can set playlist until they've left which sorta - // fucks things should maybe set this in HostState_NewGame? - R2::SetCurrentPlaylist("tdm"); - strcpy(R2::g_pHostState->m_levelName, "mp_lobby"); - R2::g_pHostState->m_iNextState = R2::HostState_t::HS_NEW_GAME; - } - }); + RegisterConCommand("ns_end_reauth_and_leave_to_lobby", ConCommand_ns_end_reauth_and_leave_to_lobby, "", FCVAR_NONE); }
\ No newline at end of file diff --git a/NorthstarDedicatedTest/miscserverscript.cpp b/NorthstarDedicatedTest/miscserverscript.cpp index b8ab951a..26c18d81 100644 --- a/NorthstarDedicatedTest/miscserverscript.cpp +++ b/NorthstarDedicatedTest/miscserverscript.cpp @@ -1,10 +1,9 @@ #include "pch.h" #include "miscserverscript.h" -#include "hooks.h" #include "squirrel.h" #include "masterserver.h" #include "serverauthentication.h" -#include "gameutils.h" +#include "r2client.h" // annoying helper function because i can't figure out getting players or entities from sqvm rn // wish i didn't have to do it like this, but here we are @@ -54,7 +53,7 @@ SQRESULT SQ_IsPlayerIndexLocalPlayer(void* sqvm) return SQRESULT_ERROR; } - g_pServerSquirrel->sq_pushbool(sqvm, !strcmp(g_LocalPlayerUserID, (char*)player + 0xF500)); + g_pServerSquirrel->sq_pushbool(sqvm, !strcmp(R2::g_LocalPlayerUserID, (char*)player + 0xF500)); return SQRESULT_NOTNULL; } diff --git a/NorthstarDedicatedTest/playlist.cpp b/NorthstarDedicatedTest/playlist.cpp index f8c64502..e3acc490 100644 --- a/NorthstarDedicatedTest/playlist.cpp +++ b/NorthstarDedicatedTest/playlist.cpp @@ -4,7 +4,6 @@ #include "hooks.h" #include "concommand.h" #include "convar.h" -#include "gameutils.h" #include "hookutils.h" #include "squirrel.h" diff --git a/NorthstarDedicatedTest/r2client.cpp b/NorthstarDedicatedTest/r2client.cpp new file mode 100644 index 00000000..845eebf1 --- /dev/null +++ b/NorthstarDedicatedTest/r2client.cpp @@ -0,0 +1,20 @@ +#include "pch.h" +#include "r2client.h" + +using namespace R2; + +// use the R2 namespace for game funcs +namespace R2 +{ + char* g_LocalPlayerUserID; + char* g_LocalPlayerOriginToken; + GetBaseLocalClientType GetBaseLocalClient; +} // namespace R2 + +ON_DLL_LOAD("engine.dll", R2EngineClient, [](HMODULE baseAddress) +{ + g_LocalPlayerUserID = (char*)baseAddress + 0x13F8E688; + g_LocalPlayerOriginToken = (char*)baseAddress + 0x13979C80; + + GetBaseLocalClient = (GetBaseLocalClientType)((char*)baseAddress + 0x78200); +})
\ No newline at end of file diff --git a/NorthstarDedicatedTest/r2client.h b/NorthstarDedicatedTest/r2client.h new file mode 100644 index 00000000..f4e0c8a8 --- /dev/null +++ b/NorthstarDedicatedTest/r2client.h @@ -0,0 +1,11 @@ +#pragma once + +// use the R2 namespace for game funcs +namespace R2 +{ + extern char* g_LocalPlayerUserID; + extern char* g_LocalPlayerOriginToken; + + typedef void* (*GetBaseLocalClientType)(); + extern GetBaseLocalClientType GetBaseLocalClient; +} // namespace R2
\ No newline at end of file diff --git a/NorthstarDedicatedTest/r2engine.cpp b/NorthstarDedicatedTest/r2engine.cpp new file mode 100644 index 00000000..c866186a --- /dev/null +++ b/NorthstarDedicatedTest/r2engine.cpp @@ -0,0 +1,23 @@ +#include "pch.h" +#include "r2engine.h" + +using namespace R2; + +// use the R2 namespace for game funcs +namespace R2 +{ + Cbuf_GetCurrentPlayerType Cbuf_GetCurrentPlayer; + Cbuf_AddTextType Cbuf_AddText; + Cbuf_ExecuteType Cbuf_Execute; + + CEngine* g_pEngine; +} // namespace R2 + +ON_DLL_LOAD("engine.dll", R2Engine, [](HMODULE baseAddress) +{ + Cbuf_GetCurrentPlayer = (Cbuf_GetCurrentPlayerType)((char*)baseAddress + 0x120630); + Cbuf_AddText = (Cbuf_AddTextType)((char*)baseAddress + 0x1203B0); + Cbuf_Execute = (Cbuf_ExecuteType)((char*)baseAddress + 0x1204B0); + + g_pEngine = *(CEngine**)((char*)baseAddress + 0x7D70C8); +})
\ No newline at end of file diff --git a/NorthstarDedicatedTest/r2engine.h b/NorthstarDedicatedTest/r2engine.h new file mode 100644 index 00000000..ae02c791 --- /dev/null +++ b/NorthstarDedicatedTest/r2engine.h @@ -0,0 +1,102 @@ +#pragma once + +// use the R2 namespace for game funcs +namespace R2 +{ + // Cbuf + enum class ECommandTarget_t + { + CBUF_FIRST_PLAYER = 0, + CBUF_LAST_PLAYER = 1, // MAX_SPLITSCREEN_CLIENTS - 1, MAX_SPLITSCREEN_CLIENTS = 2 + CBUF_SERVER = CBUF_LAST_PLAYER + 1, + + CBUF_COUNT, + }; + + enum class cmd_source_t + { + // Added to the console buffer by gameplay code. Generally unrestricted. + kCommandSrcCode, + + // Sent from code via engine->ClientCmd, which is restricted to commands visible + // via FCVAR_CLIENTCMD_CAN_EXECUTE. + kCommandSrcClientCmd, + + // Typed in at the console or via a user key-bind. Generally unrestricted, although + // the client will throttle commands sent to the server this way to 16 per second. + kCommandSrcUserInput, + + // Came in over a net connection as a clc_stringcmd + // host_client will be valid during this state. + // + // Restricted to FCVAR_GAMEDLL commands (but not convars) and special non-ConCommand + // server commands hardcoded into gameplay code (e.g. "joingame") + kCommandSrcNetClient, + + // Received from the server as the client + // + // Restricted to commands with FCVAR_SERVER_CAN_EXECUTE + kCommandSrcNetServer, + + // Being played back from a demo file + // + // Not currently restricted by convar flag, but some commands manually ignore calls + // from this source. FIXME: Should be heavily restricted as demo commands can come + // from untrusted sources. + kCommandSrcDemoFile, + + // Invalid value used when cleared + kCommandSrcInvalid = -1 + }; + + typedef ECommandTarget_t (*Cbuf_GetCurrentPlayerType)(); + extern Cbuf_GetCurrentPlayerType Cbuf_GetCurrentPlayer; + + typedef void (*Cbuf_AddTextType)(ECommandTarget_t eTarget, const char* text, cmd_source_t source); + extern Cbuf_AddTextType Cbuf_AddText; + + typedef void (*Cbuf_ExecuteType)(); + extern Cbuf_ExecuteType Cbuf_Execute; + + // CEngine + + enum EngineQuitState + { + QUIT_NOTQUITTING = 0, + QUIT_TODESKTOP, + QUIT_RESTART + }; + + enum class EngineState_t + { + DLL_INACTIVE = 0, // no dll + DLL_ACTIVE, // engine is focused + DLL_CLOSE, // closing down dll + DLL_RESTART, // engine is shutting down but will restart right away + DLL_PAUSED, // engine is paused, can become active from this state + }; + + class CEngine + { + public: + virtual void unknown() {} // unsure if this is where + virtual bool Load(bool dedicated, const char* baseDir) {} + virtual void Unload() {} + virtual void SetNextState(EngineState_t iNextState) {} + virtual EngineState_t GetState() {} + virtual void Frame() {} + virtual double GetFrameTime() {} + virtual float GetCurTime() {} + + EngineQuitState m_nQuitting; + EngineState_t m_nDllState; + EngineState_t m_nNextDllState; + double m_flCurrentTime; + float m_flFrameTime; + double m_flPreviousTime; + float m_flFilteredTime; + float m_flMinFrameTime; // Expected duration of a frame, or zero if it is unlimited. + }; + + extern CEngine* g_pEngine; +} // namespace R2 diff --git a/NorthstarDedicatedTest/r2server.cpp b/NorthstarDedicatedTest/r2server.cpp new file mode 100644 index 00000000..c61e2d13 --- /dev/null +++ b/NorthstarDedicatedTest/r2server.cpp @@ -0,0 +1,21 @@ +#include "pch.h" +#include "r2server.h" + +using namespace R2; + +// use the R2 namespace for game funcs +namespace R2 +{ + server_state_t* g_pServerState; + Server_GetEntityByIndexType Server_GetEntityByIndex; +} // namespace R2 + +ON_DLL_LOAD("engine.dll", R2EngineServer, [](HMODULE baseAddress) +{ + g_pServerState = (server_state_t*)((char*)baseAddress + 0x12A53D48); +}) + +ON_DLL_LOAD("server.dll", R2GameServer, [](HMODULE baseAddress) +{ + Server_GetEntityByIndex = (Server_GetEntityByIndexType)((char*)baseAddress + 0xFB820); +})
\ No newline at end of file diff --git a/NorthstarDedicatedTest/r2server.h b/NorthstarDedicatedTest/r2server.h new file mode 100644 index 00000000..6e09d0d1 --- /dev/null +++ b/NorthstarDedicatedTest/r2server.h @@ -0,0 +1,19 @@ +#pragma once + +// use the R2 namespace for game funcs +namespace R2 +{ + enum server_state_t + { + ss_dead = 0, // Dead + ss_loading, // Spawning + ss_active, // Running + ss_paused, // Running, but paused + }; + + extern server_state_t* g_pServerState; + + // server entity stuff + typedef void* (*Server_GetEntityByIndexType)(int index); + extern Server_GetEntityByIndexType Server_GetEntityByIndex; +} // namespace R2
\ No newline at end of file diff --git a/NorthstarDedicatedTest/scriptserverbrowser.cpp b/NorthstarDedicatedTest/scriptserverbrowser.cpp index 3b4647b5..86db4308 100644 --- a/NorthstarDedicatedTest/scriptserverbrowser.cpp +++ b/NorthstarDedicatedTest/scriptserverbrowser.cpp @@ -1,10 +1,10 @@ #include "pch.h" -#include "hooks.h" #include "scriptserverbrowser.h" #include "squirrel.h" #include "masterserver.h" -#include "gameutils.h" #include "serverauthentication.h" +#include "r2engine.h" +#include "r2client.h" // functions for viewing server browser @@ -334,7 +334,7 @@ SQRESULT SQ_TryAuthWithServer(void* sqvm) // do auth g_MasterServerManager->AuthenticateWithServer( - g_LocalPlayerUserID, + R2::g_LocalPlayerUserID, g_MasterServerManager->m_sOwnClientAuthToken, g_MasterServerManager->m_vRemoteServers[serverIndex].id, (char*)password); @@ -369,9 +369,10 @@ SQRESULT SQ_ConnectToAuthedServer(void* sqvm) // set auth token, then try to connect // i'm honestly not entirely sure how silentconnect works regarding ports and encryption so using connect for now - Cbuf_AddText(Cbuf_GetCurrentPlayer(), fmt::format("serverfilter {}", info.authToken).c_str(), cmd_source_t::kCommandSrcCode); - Cbuf_AddText( - Cbuf_GetCurrentPlayer(), + R2::Cbuf_AddText( + R2::Cbuf_GetCurrentPlayer(), fmt::format("serverfilter {}", info.authToken).c_str(), R2::cmd_source_t::kCommandSrcCode); + R2::Cbuf_AddText( + R2::Cbuf_GetCurrentPlayer(), fmt::format( "connect {}.{}.{}.{}:{}", info.ip.S_un.S_un_b.s_b1, @@ -380,7 +381,7 @@ SQRESULT SQ_ConnectToAuthedServer(void* sqvm) info.ip.S_un.S_un_b.s_b4, info.port) .c_str(), - cmd_source_t::kCommandSrcCode); + R2::cmd_source_t::kCommandSrcCode); g_MasterServerManager->m_bHasPendingConnectionInfo = false; return SQRESULT_NULL; @@ -390,7 +391,7 @@ SQRESULT SQ_ConnectToAuthedServer(void* sqvm) SQRESULT SQ_TryAuthWithLocalServer(void* sqvm) { // do auth request - g_MasterServerManager->AuthenticateWithOwnServer(g_LocalPlayerUserID, g_MasterServerManager->m_sOwnClientAuthToken); + g_MasterServerManager->AuthenticateWithOwnServer(R2::g_LocalPlayerUserID, g_MasterServerManager->m_sOwnClientAuthToken); return SQRESULT_NULL; } @@ -400,10 +401,10 @@ SQRESULT SQ_CompleteAuthWithLocalServer(void* sqvm) { // literally just set serverfilter // note: this assumes we have no authdata other than our own - Cbuf_AddText( - Cbuf_GetCurrentPlayer(), + R2::Cbuf_AddText( + R2::Cbuf_GetCurrentPlayer(), fmt::format("serverfilter {}", g_ServerAuthenticationManager->m_authData.begin()->first).c_str(), - cmd_source_t::kCommandSrcCode); + R2::cmd_source_t::kCommandSrcCode); return SQRESULT_NULL; } diff --git a/NorthstarDedicatedTest/serverauthentication.cpp b/NorthstarDedicatedTest/serverauthentication.cpp index 74163d5a..8190050d 100644 --- a/NorthstarDedicatedTest/serverauthentication.cpp +++ b/NorthstarDedicatedTest/serverauthentication.cpp @@ -1,23 +1,25 @@ #include "pch.h" #include "serverauthentication.h" -#include "hooks.h" #include "cvar.h" #include "convar.h" -#include "hookutils.h" #include "masterserver.h" -#include "httplib.h" -#include "gameutils.h" #include "hoststate.h" #include "bansystem.h" #include "miscserverscript.h" #include "concommand.h" #include "dedicated.h" -#include <fstream> -#include <filesystem> -#include <thread> #include "configurables.h" #include "NSMem.h" #include "tier0.h" +#include "r2engine.h" +#include "r2client.h" +#include "r2server.h" + +#include "httplib.h" + +#include <fstream> +#include <filesystem> +#include <thread> using namespace Tier0; @@ -159,7 +161,7 @@ bool ServerAuthenticationManager::AuthenticatePlayer(void* player, int64_t uid, strcpy((char*)player + 0xF500, strUid.c_str()); // reset from disk if we're doing that - if (m_bForceReadLocalPlayerPersistenceFromDisk && !strcmp(authData.uid, g_LocalPlayerUserID)) + if (m_bForceReadLocalPlayerPersistenceFromDisk && !strcmp(authData.uid, R2::g_LocalPlayerUserID)) { std::fstream pdataStream(GetNorthstarPrefix() + "/placeholder_playerdata.pdata", std::ios_base::in); @@ -228,7 +230,7 @@ bool ServerAuthenticationManager::RemovePlayerAuthData(void* player) return false; // hack for special case where we're on a local server, so we erase our own newly created auth data on disconnect - if (m_bNeedLocalAuthForNewgame && !strcmp((char*)player + 0xF500, g_LocalPlayerUserID)) + if (m_bNeedLocalAuthForNewgame && !strcmp((char*)player + 0xF500, R2::g_LocalPlayerUserID)) return false; // we don't have our auth token at this point, so lookup authdata by uid @@ -419,7 +421,7 @@ void CBaseClient__DisconnectHook(void* self, uint32_t unknownButAlways1, const c } // maybe this should be done outside of auth code, but effort to refactor rn and it sorta fits -typedef bool (*CCommand__TokenizeType)(CCommand& self, const char* pCommandString, cmd_source_t commandSource); +typedef bool (*CCommand__TokenizeType)(CCommand& self, const char* pCommandString, R2::cmd_source_t commandSource); CCommand__TokenizeType CCommand__Tokenize; typedef char (*CGameClient__ExecuteStringCommandType)(void* self, uint32_t unknown, const char* pCommandString); @@ -452,7 +454,7 @@ char CGameClient__ExecuteStringCommandHook(void* self, uint32_t unknown, const c memset(commandBuf, 0, sizeof(commandBuf)); CCommand tempCommand = *(CCommand*)&commandBuf; - if (!CCommand__Tokenize(tempCommand, pCommandString, cmd_source_t::kCommandSrcCode) || !tempCommand.ArgC()) + if (!CCommand__Tokenize(tempCommand, pCommandString, R2::cmd_source_t::kCommandSrcCode) || !tempCommand.ArgC()) return false; ConCommand* command = g_pCVar->FindCommand(tempCommand.Arg(0)); @@ -464,7 +466,7 @@ char CGameClient__ExecuteStringCommandHook(void* self, uint32_t unknown, const c if (IsDedicated()) return false; - if (strcmp((char*)self + 0xF500, g_LocalPlayerUserID)) + if (strcmp((char*)self + 0xF500, R2::g_LocalPlayerUserID)) return false; } @@ -510,7 +512,7 @@ char __fastcall CNetChan___ProcessMessagesHook(void* self, void* buf) Cvar_net_chan_limit_msec_per_sec->GetInt()); // nonzero = kick, 0 = warn, but never kick local player - if (Cvar_net_chan_limit_mode->GetInt() && strcmp(g_LocalPlayerUserID, (char*)sender + 0xF500)) + if (Cvar_net_chan_limit_mode->GetInt() && strcmp(R2::g_LocalPlayerUserID, (char*)sender + 0xF500)) { CBaseClient__Disconnect(sender, 1, "Exceeded net channel processing limit"); return false; @@ -587,7 +589,7 @@ bool ProcessConnectionlessPacketHook(void* a1, netpacket_t* packet) void ConCommand_ns_resetpersistence(const CCommand& args) { - if (*sv_m_State == server_state_t::ss_active) + if (*R2::g_pServerState == R2::server_state_t::ss_active) { spdlog::error("ns_resetpersistence must be entered from the main menu"); return; diff --git a/NorthstarDedicatedTest/squirrel.cpp b/NorthstarDedicatedTest/squirrel.cpp index 3802404c..a64095a8 100644 --- a/NorthstarDedicatedTest/squirrel.cpp +++ b/NorthstarDedicatedTest/squirrel.cpp @@ -1,10 +1,8 @@ #include "pch.h" #include "squirrel.h" -#include "hooks.h" -#include "hookutils.h" #include "concommand.h" #include "modmanager.h" -#include "gameutils.h" +#include "r2engine.h" #include "NSMem.h" RegisterSquirrelFuncType ClientRegisterSquirrelFunc; @@ -137,14 +135,14 @@ template <ScriptContext context> void ScriptCompileErrorHook(void* sqvm, const c // ideally we'd just check if the sqvm was fully initialised here, somehow if (strcmp(file, "console") && strcmp(file, "unnamedbuffer")) { - Cbuf_AddText( - Cbuf_GetCurrentPlayer(), + R2::Cbuf_AddText( + R2::Cbuf_GetCurrentPlayer(), fmt::format("disconnect \"Encountered {} script compilation error, see console for details.\"", GetContextName(realContext)) .c_str(), - cmd_source_t::kCommandSrcCode); + R2::cmd_source_t::kCommandSrcCode); if (realContext == ScriptContext::UI) // likely temp: show console so user can see any errors - Cbuf_AddText(Cbuf_GetCurrentPlayer(), "showconsole", cmd_source_t::kCommandSrcCode); + R2::Cbuf_AddText(R2::Cbuf_GetCurrentPlayer(), "showconsole", R2::cmd_source_t::kCommandSrcCode); } // dont call the original function since it kills game lol |