From 872e33887a420688a2eacde6d3172594e7b733bc Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 18 Feb 2023 00:24:02 +0100 Subject: [PATCH] Server: CPU statistics update logic Implements the server side CPU statistics update logic. In the retail product 'SVC_ServerTick' is only send during 'CClient::ActivatePlayer' and 'CClient::SendServerInfo', which is only called during/after connect, but not during the game. The new implementation sends server CPU statistics to the client every time the CPU usage has changed. This is indicated using the '-1' value in the 'SVC_ServerTick::m_NetTick.m_nCommandTick' member variable. --- r5dev/engine/networkstringtable.cpp | 51 ++++++++++++++++++++++++++++- r5dev/engine/networkstringtable.h | 36 +++++++++++++++++++- 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/r5dev/engine/networkstringtable.cpp b/r5dev/engine/networkstringtable.cpp index 13e8989d..04c21494 100644 --- a/r5dev/engine/networkstringtable.cpp +++ b/r5dev/engine/networkstringtable.cpp @@ -5,7 +5,12 @@ // $NoKeywords: $ //===========================================================================// #include "core/stdafx.h" -#include "engine/networkstringtable.h" +#include "tier1/cvar.h" +#ifndef CLIENT_DLL +#include "server/server.h" +#include "host.h" +#endif // !CLIENT_DLL +#include "networkstringtable.h" //----------------------------------------------------------------------------- // Purpose: @@ -77,3 +82,47 @@ bool CNetworkStringTable::Lock(bool bLock) m_bLocked = bLock; return bState; } + +//----------------------------------------------------------------------------- +// Purpose: Writes network string table delta's to snapshot buffer +// Input : *pClient - +// nTickAck - +// *pMsg - +//----------------------------------------------------------------------------- +static uint8_t s_OldCPUPercentage; +void CNetworkStringTableContainer::WriteUpdateMessage(CNetworkStringTableContainer* thisp, CClient* pClient, unsigned int nTickAck, bf_write* pMsg) +{ +#ifndef CLIENT_DLL + if (sv_stats->GetBool()) + { + uint8_t nCPUPercentage = g_pServer[MAX_PLAYERS].GetCPUUsage() * 100.0f; + if (s_OldCPUPercentage != nCPUPercentage) + { + s_OldCPUPercentage = nCPUPercentage; + SVC_ServerTick serverTick(g_pServer->GetTick(), *host_frametime_unbounded, *host_frametime_stddeviation, nCPUPercentage); + + serverTick.m_nGroup = 0; + serverTick.m_bReliable = 1; + serverTick.m_NetTick.m_nCommandTick = -1; // Statistics only, see 'CClientState::VProcessServerTick'. + + // Send individually instead of writing into snapshot buffer to avoid overflow. + pClient->SendNetMsg(&serverTick, false, true, false); + } + } +#endif // !CLIENT_DLL + v_CNetworkStringTableContainer__WriteUpdateMessage(thisp, pClient, nTickAck, pMsg); +} + +void VNetworkStringTableContainer::Attach() const +{ +#ifndef CLIENT_DLL + DetourAttach(&v_CNetworkStringTableContainer__WriteUpdateMessage, &CNetworkStringTableContainer::WriteUpdateMessage); +#endif // !CLIENT_DLL +} + +void VNetworkStringTableContainer::Detach() const +{ +#ifndef CLIENT_DLL + DetourDetach(&v_CNetworkStringTableContainer__WriteUpdateMessage, &CNetworkStringTableContainer::WriteUpdateMessage); +#endif // !CLIENT_DLL +} \ No newline at end of file diff --git a/r5dev/engine/networkstringtable.h b/r5dev/engine/networkstringtable.h index 944b2168..e5e9b153 100644 --- a/r5dev/engine/networkstringtable.h +++ b/r5dev/engine/networkstringtable.h @@ -7,6 +7,9 @@ #ifndef NETWORKSTRINGTABLE_H #define NETWORKSTRINGTABLE_H +#include "tier1/utlvector.h" +#include "tier1/bitbuf.h" +#include "client/client.h" typedef int TABLEID; @@ -25,6 +28,7 @@ public: void SetTick(int tick_count); bool Lock(bool bLock); +private: TABLEID m_id; bool m_bLocked; // Might be wrong! char* m_pszTableName; @@ -39,11 +43,41 @@ public: class CNetworkStringTableContainer : public INetworkStringTable { public: + static void WriteUpdateMessage(CNetworkStringTableContainer* thisp, CClient* client, unsigned int tick_ack, bf_write* msg); + +private: bool m_bAllowCreation; // create guard int m_nTickCount; // current tick bool m_bLocked; // currently locked? bool m_bEnableRollback; // enables rollback feature - //CUtlVector < CNetworkStringTable* > m_Tables; // the string tables + CUtlVector < CNetworkStringTable* > m_Tables; // the string tables }; +inline CMemory p_CNetworkStringTableContainer__WriteUpdateMessage; +inline auto v_CNetworkStringTableContainer__WriteUpdateMessage = + p_CNetworkStringTableContainer__WriteUpdateMessage.RCast(); + +class VNetworkStringTableContainer : public IDetour +{ + virtual void GetAdr(void) const + { + LogFunAdr("CNetworkStringTableContainer::WriteUpdateMessage", p_CNetworkStringTableContainer__WriteUpdateMessage.GetPtr()); + } + virtual void GetFun(void) const + { +#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) + p_CNetworkStringTableContainer__WriteUpdateMessage = g_GameDll.FindPatternSIMD("48 89 74 24 ?? 55 57 41 54 41 55 41 56 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ??"); +#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) + p_CNetworkStringTableContainer__WriteUpdateMessage = g_GameDll.FindPatternSIMD("48 89 74 24 ?? 48 89 7C 24 ?? 55 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 45 33 ED"); +#endif + v_CNetworkStringTableContainer__WriteUpdateMessage = + p_CNetworkStringTableContainer__WriteUpdateMessage.RCast(); + } + virtual void GetVar(void) const { } + virtual void GetCon(void) const { } + virtual void Attach(void) const; + virtual void Detach(void) const; +}; +/////////////////////////////////////////////////////////////////////////////// + #endif // NETWORKSTRINGTABLE_H \ No newline at end of file