111111#include " missionchooser/iasw_mission_chooser_source.h"
112112#include " matchmaking/swarm/imatchext_swarm.h"
113113#include " asw_gamerules.h"
114+ #include " asw_player.h"
114115#include " asw_util_shared.h"
115116#include " iconsistency.h"
116117#endif
@@ -613,6 +614,16 @@ static bool InitGameSystems( CreateInterfaceFn appSystemFactory )
613614
614615CServerGameDLL g_ServerGameDLL;
615616EXPOSE_SINGLE_INTERFACE_GLOBALVAR (CServerGameDLL, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL, g_ServerGameDLL);
617+ // Crash fix/hardening: the engine can call into game code during lobby soft-close -> restart
618+ // before Steam is fully activated for the new session. Track activation so code can safely
619+ // skip Steam calls until the engine signals readiness.
620+ static bool g_bRDSteamAPIActivated = false ;
621+ static float g_flNextDeferredSteamStatsRequestTime = 0 .0f ;
622+
623+ bool RD_IsSteamAPIActivated ()
624+ {
625+ return g_bRDSteamAPIActivated;
626+ }
616627
617628bool CServerGameDLL::DLLInit ( CreateInterfaceFn appSystemFactory,
618629 CreateInterfaceFn physicsFactory, CreateInterfaceFn fileSystemFactory,
@@ -1064,6 +1075,7 @@ bool CServerGameDLL::SupportsSaveRestore()
10641075bool CServerGameDLL::LevelInit ( const char *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background )
10651076{
10661077 VPROF (" CServerGameDLL::LevelInit" );
1078+ g_bRDSteamAPIActivated = false ;
10671079 ResetWindspeed ();
10681080 UpdateChapterRestrictions ( pMapName );
10691081
@@ -1266,6 +1278,11 @@ void CServerGameDLL::ServerActivate( edict_t *pEdictList, int edictCount, int cl
12661278void CServerGameDLL::GameServerSteamAPIActivated ( void )
12671279{
12681280 // the Steam API pointers used to be initialized here, but that happens automatically now.
1281+ // Crash fix/hardening: mark Steam as activated so code can safely call Steam APIs.
1282+ g_bRDSteamAPIActivated = true ;
1283+
1284+ // If any players tried to request XP before Steam activation (restart/join window), retry now.
1285+ g_flNextDeferredSteamStatsRequestTime = 0 .0f ;
12691286}
12701287
12711288// -----------------------------------------------------------------------------
@@ -1281,6 +1298,42 @@ void CServerGameDLL::GameFrame( bool simulating )
12811298 if ( g_InRestore )
12821299 return ;
12831300
1301+ // Crash fix/hardening: if we deferred any Steam stats requests because Steam wasn't activated
1302+ // yet (e.g. lobby soft-close -> restart), retry them once Steam is ready.
1303+ static const float k_flDeferredSteamStatsRequestTimeout = 30 .0f ;
1304+ if ( g_bRDSteamAPIActivated && gpGlobals && gpGlobals->curtime >= g_flNextDeferredSteamStatsRequestTime )
1305+ {
1306+ g_flNextDeferredSteamStatsRequestTime = gpGlobals->curtime + 1 .0f ;
1307+ for ( int i = 1 ; i <= gpGlobals->maxClients ; i++ )
1308+ {
1309+ CASW_Player *pPlayer = ToASW_Player ( UTIL_PlayerByIndex ( i ) );
1310+ if ( !pPlayer )
1311+ continue ;
1312+
1313+ if ( pPlayer->m_bDeferredSteamStatsRequest && !pPlayer->m_bPendingSteamStats )
1314+ {
1315+ if ( pPlayer->m_flDeferredSteamStatsRequestStart < 0 .0f )
1316+ {
1317+ pPlayer->m_flDeferredSteamStatsRequestStart = gpGlobals->curtime ;
1318+ }
1319+
1320+ if ( ( gpGlobals->curtime - pPlayer->m_flDeferredSteamStatsRequestStart ) > k_flDeferredSteamStatsRequestTimeout )
1321+ {
1322+ pPlayer->m_bDeferredSteamStatsRequest = false ;
1323+ pPlayer->m_flDeferredSteamStatsRequestStart = -1 .0f ;
1324+ continue ;
1325+ }
1326+
1327+ pPlayer->RequestExperience ();
1328+ if ( pPlayer->m_bPendingSteamStats )
1329+ {
1330+ pPlayer->m_bDeferredSteamStatsRequest = false ;
1331+ pPlayer->m_flDeferredSteamStatsRequestStart = -1 .0f ;
1332+ }
1333+ }
1334+ }
1335+ }
1336+
12841337#ifndef NO_STEAM
12851338 // All the calls to us from the engine prior to gameframe (like LevelInit & ServerActivate)
12861339 // are done before the engine has got the Steam API connected, so we have to wait until now to connect ourselves.
@@ -1518,6 +1571,7 @@ void CServerGameDLL::LevelShutdown( void )
15181571 MDLCACHE_CRITICAL_SECTION ();
15191572 IGameSystem::LevelShutdownPreEntityAllSystems ();
15201573
1574+ g_bRDSteamAPIActivated = false ;
15211575 // YWB:
15221576 // This entity pointer is going away now and is corrupting memory on level transitions/restarts
15231577 CSoundEnt::ShutdownSoundEnt ();
0 commit comments