Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions src/game/server/gameinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
#include "missionchooser/iasw_mission_chooser_source.h"
#include "matchmaking/swarm/imatchext_swarm.h"
#include "asw_gamerules.h"
#include "asw_player.h"
#include "asw_util_shared.h"
#include "iconsistency.h"
#endif
Expand Down Expand Up @@ -613,6 +614,16 @@ static bool InitGameSystems( CreateInterfaceFn appSystemFactory )

CServerGameDLL g_ServerGameDLL;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CServerGameDLL, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL, g_ServerGameDLL);
// Crash fix/hardening: the engine can call into game code during lobby soft-close -> restart
// before Steam is fully activated for the new session. Track activation so code can safely
// skip Steam calls until the engine signals readiness.
static bool g_bRDSteamAPIActivated = false;
static float g_flNextDeferredSteamStatsRequestTime = 0.0f;

bool RD_IsSteamAPIActivated()
{
return g_bRDSteamAPIActivated;
}

bool CServerGameDLL::DLLInit( CreateInterfaceFn appSystemFactory,
CreateInterfaceFn physicsFactory, CreateInterfaceFn fileSystemFactory,
Expand Down Expand Up @@ -1064,6 +1075,7 @@ bool CServerGameDLL::SupportsSaveRestore()
bool CServerGameDLL::LevelInit( const char *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background )
{
VPROF("CServerGameDLL::LevelInit");
g_bRDSteamAPIActivated = false;
ResetWindspeed();
UpdateChapterRestrictions( pMapName );

Expand Down Expand Up @@ -1266,6 +1278,11 @@ void CServerGameDLL::ServerActivate( edict_t *pEdictList, int edictCount, int cl
void CServerGameDLL::GameServerSteamAPIActivated( void )
{
// the Steam API pointers used to be initialized here, but that happens automatically now.
// Crash fix/hardening: mark Steam as activated so code can safely call Steam APIs.
g_bRDSteamAPIActivated = true;

// If any players tried to request XP before Steam activation (restart/join window), retry now.
g_flNextDeferredSteamStatsRequestTime = 0.0f;
}

//-----------------------------------------------------------------------------
Expand All @@ -1281,6 +1298,42 @@ void CServerGameDLL::GameFrame( bool simulating )
if ( g_InRestore )
return;

// Crash fix/hardening: if we deferred any Steam stats requests because Steam wasn't activated
// yet (e.g. lobby soft-close -> restart), retry them once Steam is ready.
static const float k_flDeferredSteamStatsRequestTimeout = 30.0f;
if ( g_bRDSteamAPIActivated && gpGlobals && gpGlobals->curtime >= g_flNextDeferredSteamStatsRequestTime )
{
g_flNextDeferredSteamStatsRequestTime = gpGlobals->curtime + 1.0f;
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
{
CASW_Player *pPlayer = ToASW_Player( UTIL_PlayerByIndex( i ) );
if ( !pPlayer )
continue;

if ( pPlayer->m_bDeferredSteamStatsRequest && !pPlayer->m_bPendingSteamStats )
{
if ( pPlayer->m_flDeferredSteamStatsRequestStart < 0.0f )
{
pPlayer->m_flDeferredSteamStatsRequestStart = gpGlobals->curtime;
}

if ( ( gpGlobals->curtime - pPlayer->m_flDeferredSteamStatsRequestStart ) > k_flDeferredSteamStatsRequestTimeout )
{
pPlayer->m_bDeferredSteamStatsRequest = false;
pPlayer->m_flDeferredSteamStatsRequestStart = -1.0f;
continue;
}

pPlayer->RequestExperience();
if ( pPlayer->m_bPendingSteamStats )
{
pPlayer->m_bDeferredSteamStatsRequest = false;
pPlayer->m_flDeferredSteamStatsRequestStart = -1.0f;
}
}
}
}

#ifndef NO_STEAM
// All the calls to us from the engine prior to gameframe (like LevelInit & ServerActivate)
// are done before the engine has got the Steam API connected, so we have to wait until now to connect ourselves.
Expand Down Expand Up @@ -1518,6 +1571,7 @@ void CServerGameDLL::LevelShutdown( void )
MDLCACHE_CRITICAL_SECTION();
IGameSystem::LevelShutdownPreEntityAllSystems();

g_bRDSteamAPIActivated = false;
// YWB:
// This entity pointer is going away now and is corrupting memory on level transitions/restarts
CSoundEnt::ShutdownSoundEnt();
Expand Down
7 changes: 6 additions & 1 deletion src/game/server/gameinterface.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Expose things from GameInterface.cpp. Mostly the engine interfaces.
//
Expand Down Expand Up @@ -211,6 +211,11 @@ class CMapLoadEntityFilter : public IMapEntityFilter

bool IsEngineThreaded();

// Crash fix support: during lobby soft-close -> restart, the engine can call into game code
// (including PlayerSpawn) before Steam is fully activated for the new session.
// This helper lets server-side code skip Steam calls until GameServerSteamAPIActivated fires.
bool RD_IsSteamAPIActivated();

class CServerGameTags : public IServerGameTags
{
public:
Expand Down
2 changes: 2 additions & 0 deletions src/game/server/swarm/asw_player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,8 @@ CASW_Player::CASW_Player()

m_bPendingSteamStats = false;
m_flPendingSteamStatsStart = 0.0f;
m_bDeferredSteamStatsRequest = false;
m_flDeferredSteamStatsRequestStart = -1.0f;

m_bWelcomed = false;

Expand Down
2 changes: 2 additions & 0 deletions src/game/server/swarm/asw_player.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ class CASW_Player : public CBaseMultiplayerPlayer, public IASWPlayerAnimStateHel
bool m_bHasAwardedXP;
bool m_bPendingSteamStats;
float m_flPendingSteamStatsStart;
bool m_bDeferredSteamStatsRequest;
float m_flDeferredSteamStatsRequestStart;
bool m_bSentPromotedMessage;

// static inventory (medals)
Expand Down
10 changes: 10 additions & 0 deletions src/game/shared/swarm/asw_player_experience.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,16 @@ void CASW_Player::RequestExperience()
#else
if ( engine->IsDedicatedServer() )
{
// Crash fix/hardening: during lobby soft-close -> restart, PlayerSpawn can run before
// Steam is activated for the new session. Avoid calling RequestUserStats until the
// engine signals Steam readiness (GameServerSteamAPIActivated).
if ( !RD_IsSteamAPIActivated() )
{
// Defer rather than skip: once Steam is activated, game code will retry this request.
m_bDeferredSteamStatsRequest = true;
return;
}

Assert( SteamGameServerStats() );
if ( SteamGameServerStats() )
{
Expand Down