1
0
mirror of https://github.com/Mauler125/r5sdk.git synced 2025-02-09 19:15:03 +01:00

Potential fix for intermittent crash during playlists reload

This should fix a rare crash that happens when the playlists file is reloaded during disconnect. The client fetches the playlists from the server on connect. On disconnect, we want to reload the one from the client so that if the player want's to create his own game, that he would have his own playlists. The fix is to delay the reload of the playlists file to the beginning of the next frame.
This commit is contained in:
Kawe Mazidjatari 2023-05-16 00:44:59 +02:00
parent 14e19f38ef
commit 53788d5ba5
4 changed files with 49 additions and 44 deletions

@ -7,11 +7,8 @@
#include "core/stdafx.h"
#include "engine/net.h"
#ifndef NETCONSOLE
#include "tier0/frametask.h"
#include "tier1/cvar.h"
#include "vpc/keyvalues.h"
#include "mathlib/color.h"
#include "common/callback.h"
#include "net.h"
#include "net_chan.h"
#ifndef CLIENT_DLL
@ -160,24 +157,6 @@ void NET_PrintFunc(const char* fmt, ...)
DevMsg(context, "%s", result.c_str());
}
//-----------------------------------------------------------------------------
// Purpose: shutdown netchannel
// Input : *this -
// *szReason -
// bBadRep -
// bRemoveNow -
//-----------------------------------------------------------------------------
void NET_Shutdown(void* thisptr, const char* szReason, uint8_t bBadRep, bool bRemoveNow)
{
#ifndef DEDICATED
// Re-load playlist from the disk to replace the one we received from the server.
_DownloadPlaylists_f();
KeyValues::InitPlaylists();
#endif // !DEDICATED
v_NET_Shutdown(thisptr, szReason, bBadRep, bRemoveNow);
}
//-----------------------------------------------------------------------------
// Purpose: disconnect the client and shutdown netchannel
// Input : *pClient -
@ -194,9 +173,9 @@ void NET_RemoveChannel(CClient* pClient, int nIndex, const char* szReason, uint8
return;
}
v_NET_Shutdown(pClient->GetNetChan(), szReason, bBadRep, bRemoveNow); // Shutdown NetChannel.
pClient->Clear(); // Reset CClient instance for client.
g_ServerPlayer[nIndex].Reset(); // Reset ServerPlayer slot.
pClient->GetNetChan()->Shutdown(szReason, bBadRep, bRemoveNow); // Shutdown NetChannel.
pClient->Clear(); // Reset CClient slot.
g_ServerPlayer[nIndex].Reset(); // Reset ServerPlayer slot.
#endif // !CLIENT_DLL
}
#endif // !NETCONSOLE
@ -312,9 +291,6 @@ void VNet::Attach() const
DetourAttach((LPVOID*)&v_NET_SendDatagram, &NET_SendDatagram);
DetourAttach((LPVOID*)&v_NET_Decompress, &NET_Decompress);
DetourAttach((LPVOID*)&v_NET_PrintFunc, &NET_PrintFunc);
#ifndef DEDICATED
DetourAttach((LPVOID*)&v_NET_Shutdown, &NET_Shutdown);
#endif
}
void VNet::Detach() const
@ -324,9 +300,6 @@ void VNet::Detach() const
DetourDetach((LPVOID*)&v_NET_SendDatagram, &NET_SendDatagram);
DetourDetach((LPVOID*)&v_NET_Decompress, &NET_Decompress);
DetourDetach((LPVOID*)&v_NET_PrintFunc, &NET_PrintFunc);
#ifndef DEDICATED
DetourDetach((LPVOID*)&v_NET_Shutdown, &NET_Shutdown);
#endif
}
///////////////////////////////////////////////////////////////////////////////

@ -22,9 +22,6 @@ constexpr const char* DEFAULT_NET_ENCRYPTION_KEY = "WDNWLmJYQ2ZlM0VoTid3Yg==";
inline CMemory p_NET_Init;
inline auto v_NET_Init = p_NET_Init.RCast<void* (*)(bool bDeveloper)>();
inline CMemory p_NET_Shutdown;
inline auto v_NET_Shutdown = p_NET_Shutdown.RCast<void (*)(void* thisptr, const char* szReason, uint8_t bBadRep, bool bRemoveNow)>();
inline CMemory p_NET_SetKey;
inline auto v_NET_SetKey = p_NET_SetKey.RCast<void (*)(netkey_t* pKey, const char* szHash)>();
@ -64,7 +61,6 @@ class VNet : public IDetour
virtual void GetAdr(void) const
{
LogFunAdr("NET_Init", p_NET_Init.GetPtr());
LogFunAdr("NET_Shutdown", p_NET_Shutdown.GetPtr());
LogFunAdr("NET_Config", p_NET_Config.GetPtr());
LogFunAdr("NET_SetKey", p_NET_SetKey.GetPtr());
LogFunAdr("NET_ReceiveDatagram", p_NET_ReceiveDatagram.GetPtr());
@ -79,10 +75,8 @@ class VNet : public IDetour
{
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) || defined (GAMEDLL_S2)
p_NET_Init = g_GameDll.FindPatternSIMD("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 48 89 7C 24 20 41 54 41 56 41 57 48 81 EC C0 01 ??");
p_NET_Shutdown = g_GameDll.FindPatternSIMD("48 89 6C 24 18 56 57 41 56 48 83 EC 30 83 B9 D8");
#elif defined (GAMEDLL_S3)
p_NET_Init = g_GameDll.FindPatternSIMD("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 48 89 7C 24 20 41 54 41 56 41 57 48 81 EC F0 01 ??");
p_NET_Shutdown = g_GameDll.FindPatternSIMD("48 89 6C 24 18 56 57 41 56 48 83 EC 30 83 B9 D0");
#endif
p_NET_Config = g_GameDll.FindPatternSIMD("48 81 EC ?? ?? ?? ?? E8 ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 0F 57 C0");
p_NET_SetKey = g_GameDll.FindPatternSIMD("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 48 83 EC 20 48 8B F9 41 B8");
@ -92,7 +86,6 @@ class VNet : public IDetour
p_NET_PrintFunc = g_GameDll.FindPatternSIMD("48 89 54 24 10 4C 89 44 24 18 4C 89 4C 24 20 C3 48");
v_NET_Init = p_NET_Init.RCast<void* (*)(bool)>(); /*48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 48 89 7C 24 20 41 54 41 56 41 57 48 81 EC F0 01 00*/
v_NET_Shutdown = p_NET_Shutdown.RCast<void (*)(void*, const char*, uint8_t, bool)>(); /*48 89 6C 24 18 56 57 41 56 48 83 EC 30 83 B9 D0*/
v_NET_Config = p_NET_Config.RCast<void (*)(void)>();
v_NET_SetKey = p_NET_SetKey.RCast<void (*)(netkey_t*, const char*)>(); /*48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 48 83 EC 20 48 8B F9 41 B8*/
v_NET_ReceiveDatagram = p_NET_ReceiveDatagram.RCast<bool (*)(int, netpacket_s*, bool)>(); /*E8 ?? ?? ?? ?? 84 C0 75 35 48 8B D3*/

@ -5,7 +5,10 @@
//=============================================================================//
#include "core/stdafx.h"
#include "tier0/frametask.h"
#include "tier1/cvar.h"
#include "vpc/keyvalues.h"
#include "common/callback.h"
#include "engine/net.h"
#include "engine/net_chan.h"
#ifndef CLIENT_DLL
@ -220,13 +223,36 @@ void CNetChan::Clear(bool bStopProcessing)
v_NetChan_Clear(this, bStopProcessing);
}
//-----------------------------------------------------------------------------
// Purpose: shutdown netchannel
// Input : *this -
// *szReason -
// bBadRep -
// bRemoveNow -
//-----------------------------------------------------------------------------
void CNetChan::_Shutdown(CNetChan* pChan, const char* szReason, uint8_t bBadRep, bool bRemoveNow)
{
v_NetChan_Shutdown(pChan, szReason, bBadRep, bRemoveNow);
#ifndef DEDICATED
// Delay execution to the next frame; this is required to avoid a rare crash.
// Cannot reload playlists while still disconnecting.
g_TaskScheduler->Dispatch([]()
{
// Re-load and re-init playlists from the disk to replace the cached one we received from the server.
_DownloadPlaylists_f();
KeyValues::InitPlaylists();
}, 0);
#endif // !DEDICATED
}
//-----------------------------------------------------------------------------
// Purpose: process message
// Input : *pChan -
// *pMsg -
// Output : true on success, false on failure
//-----------------------------------------------------------------------------
bool CNetChan::ProcessMessages(CNetChan* pChan, bf_read* pMsg)
bool CNetChan::_ProcessMessages(CNetChan* pChan, bf_read* pMsg)
{
#ifndef CLIENT_DLL
if (!ThreadInServerFrameThread() || !net_processTimeBudget->GetInt())
@ -289,9 +315,11 @@ void CNetChan::SetRemoteCPUStatistics(uint8_t nStats)
///////////////////////////////////////////////////////////////////////////////
void VNetChan::Attach() const
{
DetourAttach(&v_NetChan_ProcessMessages, &CNetChan::ProcessMessages);
DetourAttach((PVOID*)&v_NetChan_Shutdown, &CNetChan::_Shutdown);
DetourAttach((PVOID*)&v_NetChan_ProcessMessages, &CNetChan::_ProcessMessages);
}
void VNetChan::Detach() const
{
DetourDetach(&v_NetChan_ProcessMessages, &CNetChan::ProcessMessages);
DetourDetach((PVOID*)&v_NetChan_Shutdown, &CNetChan::_Shutdown);
DetourDetach((PVOID*)&v_NetChan_ProcessMessages, &CNetChan::_ProcessMessages);
}

@ -105,9 +105,13 @@ public:
const netadr_t& GetRemoteAddress(void) const;
bool IsOverflowed(void) const;
void Clear(bool bStopProcessing);
static bool ProcessMessages(CNetChan* pChan, bf_read* pMsg);
void Clear(bool bStopProcessing);
inline void Shutdown(const char* szReason, uint8_t bBadRep, bool bRemoveNow)
{ _Shutdown(this, szReason, bBadRep, bRemoveNow); }
static void _Shutdown(CNetChan* pChan, const char* szReason, uint8_t bBadRep, bool bRemoveNow);
static bool _ProcessMessages(CNetChan* pChan, bf_read* pMsg);
void SetRemoteFramerate(float flFrameTime, float flFrameTimeStdDeviation);
void SetRemoteCPUStatistics(uint8_t nStats);
@ -185,6 +189,9 @@ static_assert(sizeof(CNetChan) == 0x1AC8);
inline CMemory p_NetChan_Clear;
inline auto v_NetChan_Clear = p_NetChan_Clear.RCast<void (*)(CNetChan* pChannel, bool bStopProcessing)>();
inline CMemory p_NetChan_Shutdown;
inline auto v_NetChan_Shutdown = p_NetChan_Shutdown.RCast<void (*)(void* thisptr, const char* szReason, uint8_t bBadRep, bool bRemoveNow)>();
inline CMemory p_NetChan_ProcessMessages;
inline auto v_NetChan_ProcessMessages = p_NetChan_ProcessMessages.RCast<bool (*)(CNetChan* pChan, bf_read* pMsg)>();
///////////////////////////////////////////////////////////////////////////////
@ -193,15 +200,19 @@ class VNetChan : public IDetour
virtual void GetAdr(void) const
{
LogFunAdr("CNetChan::Clear", p_NetChan_Clear.GetPtr());
LogFunAdr("CNetChan::Shutdown", p_NetChan_Shutdown.GetPtr());
LogFunAdr("CNetChan::ProcessMessages", p_NetChan_ProcessMessages.GetPtr());
}
virtual void GetFun(void) const
{
p_NetChan_Clear = g_GameDll.FindPatternSIMD("88 54 24 10 53 55 57");
v_NetChan_Clear = p_NetChan_Clear.RCast<void (*)(CNetChan*, bool)>(); /*88 54 24 10 53 55 57*/
v_NetChan_Clear = p_NetChan_Clear.RCast<void (*)(CNetChan*, bool)>();
p_NetChan_Shutdown = g_GameDll.FindPatternSIMD("48 89 6C 24 18 56 57 41 56 48 83 EC 30 83 B9");
v_NetChan_Shutdown = p_NetChan_Shutdown.RCast<void (*)(void*, const char*, uint8_t, bool)>();
p_NetChan_ProcessMessages = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B FA");
v_NetChan_ProcessMessages = p_NetChan_ProcessMessages.RCast<bool (*)(CNetChan* pChan, bf_read* pMsg)>();/*48 89 5C 24 ?? 48 89 6C 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B FA*/
v_NetChan_ProcessMessages = p_NetChan_ProcessMessages.RCast<bool (*)(CNetChan*, bf_read*)>();
}
virtual void GetVar(void) const { }
virtual void GetCon(void) const { }