mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
This should in theory fix the server and client desync that takes place after multiple hours of uptime without disconnecting or reloading. Note that in this version of the engine the server tick is only send on connect (Titanfall 2 does seem to send it every tick, as this netmsg is also responsible for updating the server percentage on the 'cl_showfps' HUD, which does work as designed). The patched code still writes a 'statistics only' server tick update every tick, but only sends full if the interval time has been reached for that particular client instance.
148 lines
5.1 KiB
C++
148 lines
5.1 KiB
C++
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
|
||
//
|
||
// Purpose:
|
||
//
|
||
// $NoKeywords: $
|
||
//===========================================================================//
|
||
#include "core/stdafx.h"
|
||
#include "tier1/cvar.h"
|
||
#ifndef CLIENT_DLL
|
||
#include "server/server.h"
|
||
#include "host.h"
|
||
#endif // !CLIENT_DLL
|
||
#include "net.h"
|
||
#include "networkstringtable.h"
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose:
|
||
// Input : i -
|
||
// Output : CNetworkStringTableItem
|
||
//-----------------------------------------------------------------------------
|
||
//CNetworkStringTableItem* CNetworkStringTable::GetItem(int i)
|
||
//{
|
||
// if (i >= 0)
|
||
// {
|
||
// return &m_pItems->Element(i);
|
||
// }
|
||
//
|
||
// Assert(m_pItemsClientSide);
|
||
// return &m_pItemsClientSide->Element(-i);
|
||
//}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: Returns the table identifier
|
||
// Output : TABLEID
|
||
//-----------------------------------------------------------------------------
|
||
TABLEID CNetworkStringTable::GetTableId(void) const
|
||
{
|
||
return m_id;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: Returns the max size of the table
|
||
// Output : int
|
||
//-----------------------------------------------------------------------------
|
||
int CNetworkStringTable::GetMaxStrings(void) const
|
||
{
|
||
return m_nMaxEntries;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: Returns a table, by name
|
||
// Output : const char
|
||
//-----------------------------------------------------------------------------
|
||
const char* CNetworkStringTable::GetTableName(void) const
|
||
{
|
||
return m_pszTableName;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: Returns the number of bits needed to encode an entry index
|
||
// Output : int
|
||
//-----------------------------------------------------------------------------
|
||
int CNetworkStringTable::GetEntryBits(void) const
|
||
{
|
||
return m_nEntryBits;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: Sets the tick count
|
||
//-----------------------------------------------------------------------------
|
||
void CNetworkStringTable::SetTick(int tick_count)
|
||
{
|
||
Assert(tick_count >= m_nTickCount);
|
||
m_nTickCount = tick_count;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: Locks the string table
|
||
//-----------------------------------------------------------------------------
|
||
bool CNetworkStringTable::Lock(bool bLock)
|
||
{
|
||
bool bState = m_bLocked;
|
||
m_bLocked = bLock;
|
||
return bState;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: Writes network string table delta's to snapshot buffer
|
||
// Input : *pClient -
|
||
// nTickAck -
|
||
// *pMsg -
|
||
//-----------------------------------------------------------------------------
|
||
void CNetworkStringTableContainer::WriteUpdateMessage(CNetworkStringTableContainer* thisp, CClient* pClient, unsigned int nTickAck, bf_write* pMsg)
|
||
{
|
||
#ifndef CLIENT_DLL
|
||
const double currentTime = Plat_FloatTime();
|
||
|
||
ServerPlayer_t& clientExtended = g_ServerPlayer[pClient->GetUserID()];
|
||
int commandTick = -1; // -1 means we update statistics only; see 'CClientState::VProcessServerTick()'.
|
||
|
||
// NOTE: if we send this message each tick, the client will start to
|
||
// falter. Unlike other source games, we have to have some delay in
|
||
// between each server tick message for this to work correctly.
|
||
if (clientExtended.m_bRetryClockSync ||
|
||
(currentTime - clientExtended.m_flLastClockSyncTime) > sv_clockSyncInterval->GetFloat())
|
||
{
|
||
// Sync the clocks on the client with that of the server's.
|
||
commandTick = pClient->GetCommandTick();
|
||
clientExtended.m_flLastClockSyncTime = currentTime;
|
||
clientExtended.m_bRetryClockSync = false;
|
||
}
|
||
|
||
// If commandTick == statistics only while server opted out, do not
|
||
// send the message.
|
||
const bool shouldSend = (commandTick == -1 && !sv_stats->GetBool()) ? false : true;
|
||
|
||
if (shouldSend)
|
||
{
|
||
const uint8_t nCPUPercentage = static_cast<uint8_t>(g_pServer->GetCPUUsage() * 100.0f);
|
||
SVC_ServerTick serverTick(g_pServer->GetTick(), *host_frametime_unbounded, *host_frametime_stddeviation, nCPUPercentage);
|
||
|
||
serverTick.m_nGroup = 0;
|
||
serverTick.m_bReliable = true;
|
||
serverTick.m_NetTick.m_nCommandTick = commandTick;
|
||
|
||
pMsg->WriteUBitLong(serverTick.GetType(), NETMSG_TYPE_BITS);
|
||
|
||
if (!pMsg->IsOverflowed())
|
||
{
|
||
serverTick.WriteToBuffer(pMsg);
|
||
}
|
||
else
|
||
{
|
||
Assert(0, "Snapshot buffer overflowed before string table update!");
|
||
clientExtended.m_bRetryClockSync = true; // Retry on next snapshot for this client.
|
||
}
|
||
}
|
||
#endif // !CLIENT_DLL
|
||
v_CNetworkStringTableContainer__WriteUpdateMessage(thisp, pClient, nTickAck, pMsg);
|
||
}
|
||
|
||
void VNetworkStringTableContainer::Detour(const bool bAttach) const
|
||
{
|
||
#if !defined (CLIENT_DLL) && !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) // TODO: doesn't work properly for S0/S1 yet.
|
||
DetourSetup(&v_CNetworkStringTableContainer__WriteUpdateMessage, &CNetworkStringTableContainer::WriteUpdateMessage, bAttach);
|
||
#endif // !CLIENT_DLL && !GAMEDLL_S0 && !GAMEDLL_S1
|
||
}
|