diff --git a/NorthstarDedicatedTest/logging.cpp b/NorthstarDedicatedTest/logging.cpp index 5936007fa..03b914e24 100644 --- a/NorthstarDedicatedTest/logging.cpp +++ b/NorthstarDedicatedTest/logging.cpp @@ -407,6 +407,86 @@ bool CClientState_ProcessPrint_Hook(__int64 thisptr, __int64 msg) return true; } + +typedef double(__fastcall* GetTimeConnectedType)(__int64 thisptr); +GetTimeConnectedType GetTimeConnected; + +typedef char*(__fastcall* GetAddressType)(__int64 thisptr); +GetAddressType GetAddress; + +const char* COM_FormatSeconds(int seconds) +{ + static char string[64]; + + int hours = 0; + int minutes = seconds / 60; + + if (minutes > 0) + { + seconds -= (minutes * 60); + hours = minutes / 60; + + if (hours > 0) + { + minutes -= (hours * 60); + } + } + + if (hours > 0) + { + snprintf(string, sizeof(string), "%2i:%02i:%02i", hours, minutes, seconds); + } + else + { + snprintf(string, sizeof(string), "%02i:%02i", minutes, seconds); + } + + return string; +} + +void __fastcall Host_Status_PrintClient_Hook(__int64 client, char addresses, void (*print)(const char*, ...)) +{ + __int64 playerUid = *(unsigned __int64*)(client + 185928); + DWORD playerSlot = *(DWORD*)(client + 16); + __int64 nci = *(unsigned __int64*)(client + 656); + int state = *(DWORD*)(client + 672); + const char* active; + + if (state == 8) + { + active = "active"; + } + else if (state < 3) + { + active = "connecting"; + if (state < 2) + active = "challenging"; + } + else + { + active = "spawning"; + } + + if (nci) + { + int rate = *(unsigned int*)(nci + 232); + int loss = ((*(float*)(6712 * 1 + nci + 500)) * 100.0); + int ping = ((*(float*)(6712 * 0 + nci + 508)) * 1000.0); + const char* connected = COM_FormatSeconds(GetTimeConnected(nci)); + print("# %i \"%s\" %lld %s %i %i %s %d", (unsigned int)(playerSlot + 1), client + 22, playerUid, connected, ping, loss, active, rate); + if (addresses) + { + char* address = GetAddress(nci); + print(" %s", address); + } + } + else + { + print("#%2i \"%s\" %lld %s", (unsigned int)(playerSlot + 1), client + 22, playerUid, active); + } + print("\n"); +} + void InitialiseEngineSpewFuncHooks(HMODULE baseAddress) { HookEnabler hook; @@ -423,6 +503,11 @@ void InitialiseEngineSpewFuncHooks(HMODULE baseAddress) CClientState_ProcessPrint_Hook, reinterpret_cast(&CClientState_ProcessPrint_Original)); + ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x15B7F0, Host_Status_PrintClient_Hook, NULL); + + GetTimeConnected = (GetTimeConnectedType)((char*)baseAddress + 0x210530); + GetAddress = (GetAddressType)((char*)baseAddress + 0x2101A0); + Cvar_spewlog_enable = new ConVar("spewlog_enable", "1", FCVAR_NONE, "Enables/disables whether the engine spewfunc should be logged"); } @@ -484,4 +569,4 @@ void InitialiseClientPrintHooks(HMODULE baseAddress) ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x198710, TextMsgHook, reinterpret_cast(&TextMsg_Original)); Cvar_cl_showtextmsg = new ConVar("cl_showtextmsg", "1", FCVAR_NONE, "Enable/disable text messages printing on the screen."); -} \ No newline at end of file +} diff --git a/NorthstarDedicatedTest/serverauthentication.cpp b/NorthstarDedicatedTest/serverauthentication.cpp index ac1985cf9..348479439 100644 --- a/NorthstarDedicatedTest/serverauthentication.cpp +++ b/NorthstarDedicatedTest/serverauthentication.cpp @@ -481,6 +481,14 @@ void CBaseClient__DisconnectHook(void* self, uint32_t unknownButAlways1, const c typedef bool (*CCommand__TokenizeType)(CCommand& self, const char* pCommandString, cmd_source_t commandSource); CCommand__TokenizeType CCommand__Tokenize; +// this function checks the command against several "engine client" commands. +// the full array is named "s_clcommands" and can be found at 0x7C5EF0 in engine.dll and is as follows: +// status, pause, recheck, migrateme, server_single_frame, setpause, unpause, +// ping, rpt_server_enable, rpt_client_enable, rpt, rpt_connect, rpt_password, +// rpt_screenshot, rpt_download_log, ss_connect, ss_disconnect +typedef bool (*CGameClient__IsEngineClientCommandType)(__int64 thisptr_unused, const CCommand& args); +CGameClient__IsEngineClientCommandType CGameClient__IsEngineClientCommand; + char CGameClient__ExecuteStringCommandHook(void* self, uint32_t unknown, const char* pCommandString) { // Only log clientcommands if the convar `ns_should_log_all_clientcommands` equals 1 @@ -521,7 +529,7 @@ char CGameClient__ExecuteStringCommandHook(void* self, uint32_t unknown, const c ConCommand* command = g_pCVar->FindCommand(tempCommand.Arg(0)); // if the command doesn't exist pass it on to ExecuteStringCommand for script clientcommands and stuff - if (command && !command->IsFlagSet(FCVAR_CLIENTCMD_CAN_EXECUTE)) + if (command && !command->IsFlagSet(FCVAR_CLIENTCMD_CAN_EXECUTE) && !CGameClient__IsEngineClientCommand(NULL, tempCommand)) { // ensure FCVAR_GAMEDLL concommands without FCVAR_CLIENTCMD_CAN_EXECUTE can't be executed by remote clients if (IsDedicated()) @@ -712,6 +720,7 @@ void InitialiseServerAuthentication(HMODULE baseAddress) hook, (char*)baseAddress + 0x117800, &ProcessConnectionlessPacketHook, reinterpret_cast(&ProcessConnectionlessPacket)); CCommand__Tokenize = (CCommand__TokenizeType)((char*)baseAddress + 0x418380); + CGameClient__IsEngineClientCommand = (CGameClient__IsEngineClientCommandType)((char*)baseAddress + 0x103590); uintptr_t ba = (uintptr_t)baseAddress;