Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

375 lines
8.6 KiB

  1. //========= Copyright � 1996-2009, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=====================================================================================//
  6. #ifndef _X360
  7. #include "xbox/xboxstubs.h"
  8. #endif
  9. #include "mm_framework.h"
  10. #include "match_searcher.h"
  11. #if !defined( _X360 ) && !defined( NO_STEAM ) && !defined( SWDS )
  12. #include "steam/matchmakingtypes.h"
  13. #endif
  14. #include "proto_oob.h"
  15. #include "fmtstr.h"
  16. // NOTE: This has to be the last file included!
  17. #include "tier0/memdbgon.h"
  18. #pragma warning (disable : 4355 )
  19. static ConVar mm_match_search_update_interval( "mm_match_search_update_interval", "10", FCVAR_DEVELOPMENTONLY, "Interval between matchsearcher updates." );
  20. //
  21. // Match searching overrides
  22. //
  23. class CMatchSearcher_SearchMgr : public CMatchSearcher
  24. {
  25. public:
  26. CMatchSearcher_SearchMgr( CSearchManager *pMgr, KeyValues *pSettings );
  27. public:
  28. virtual void StartSearchPass( KeyValues *pSearchPass );
  29. virtual void OnSearchEvent( KeyValues *pNotify );
  30. virtual void OnSearchDone();
  31. protected:
  32. CSearchManager *m_pMgr;
  33. };
  34. class CMatchSearchResultItem : public IMatchSearchResult
  35. {
  36. public:
  37. explicit CMatchSearchResultItem( XUID xuid, KeyValues *pDetails );
  38. ~CMatchSearchResultItem();
  39. public:
  40. virtual XUID GetOnlineId() { return m_xuid; }
  41. virtual KeyValues * GetGameDetails() { return m_pDetails; }
  42. virtual bool IsJoinable() { return m_pDetails != NULL; }
  43. virtual void Join();
  44. protected:
  45. XUID m_xuid;
  46. KeyValues *m_pDetails;
  47. };
  48. //
  49. // Pool of search managers
  50. //
  51. typedef CUtlVector< CSearchManager * > SearchManagerPool;
  52. static SearchManagerPool & GetSearchManagerPool()
  53. {
  54. static SearchManagerPool s_smp;
  55. return s_smp;
  56. }
  57. void CSearchManager::UpdateAll()
  58. {
  59. SearchManagerPool &smp = GetSearchManagerPool();
  60. for ( int k = 0; k < smp.Count(); )
  61. {
  62. CSearchManager *pUpdate = smp[k];
  63. pUpdate->Update();
  64. if ( smp.IsValidIndex( k ) && smp[k] == pUpdate )
  65. ++ k;
  66. }
  67. }
  68. //
  69. // Search manager implementation
  70. //
  71. CSearchManager::CSearchManager( KeyValues *pSearchParams ) :
  72. m_pSettings( pSearchParams ? pSearchParams->MakeCopy() : NULL ),
  73. m_pSearcher( NULL ),
  74. m_eState( STATE_IDLE )
  75. {
  76. GetSearchManagerPool().AddToTail( this );
  77. DevMsg( "Created CSearchManager(%p):\n", this );
  78. KeyValuesDumpAsDevMsg( m_pSettings, 1 );
  79. }
  80. CSearchManager::~CSearchManager()
  81. {
  82. GetSearchManagerPool().FindAndRemove( this );
  83. DevMsg( "Destroying CSearchManager(%p):\n", this );
  84. KeyValuesDumpAsDevMsg( m_pSettings, 1 );
  85. if ( m_pSearcher )
  86. m_pSearcher->Destroy();
  87. m_pSearcher = NULL;
  88. if ( m_pSettings )
  89. m_pSettings->deleteThis();
  90. m_pSettings = NULL;
  91. ClearResults( m_arrResults );
  92. }
  93. void CSearchManager::ClearResults( CUtlVector< IMatchSearchResult * > &arr )
  94. {
  95. for ( int k = 0; k < arr.Count(); ++ k )
  96. {
  97. IMatchSearchResult *p = arr[k];
  98. CMatchSearchResultItem *pItem = ( CMatchSearchResultItem * ) p;
  99. delete pItem;
  100. }
  101. arr.RemoveAll();
  102. }
  103. void CSearchManager::EnableResultsUpdate( bool bEnable, KeyValues *pSearchParams /* = NULL */ )
  104. {
  105. if ( bEnable && pSearchParams )
  106. {
  107. if ( m_pSettings )
  108. m_pSettings->deleteThis();
  109. m_pSettings = pSearchParams->MakeCopy();
  110. }
  111. if ( !bEnable && m_pSettings )
  112. {
  113. m_pSettings->deleteThis();
  114. }
  115. switch ( m_eState )
  116. {
  117. case STATE_PAUSED:
  118. m_eState = STATE_IDLE;
  119. break;
  120. case STATE_SEARCHING:
  121. m_eState = STATE_SEARCHING_CRITERIA_UPDATED;
  122. break;
  123. }
  124. }
  125. int CSearchManager::GetNumResults()
  126. {
  127. return m_arrResults.Count();
  128. }
  129. IMatchSearchResult * CSearchManager::GetResultByIndex( int iResultIdx )
  130. {
  131. return m_arrResults.IsValidIndex( iResultIdx ) ? m_arrResults[ iResultIdx ] : NULL;
  132. }
  133. IMatchSearchResult * CSearchManager::GetResultByOnlineId( XUID xuidResultOnline )
  134. {
  135. return GetResultById( m_arrResults, xuidResultOnline );
  136. }
  137. IMatchSearchResult * CSearchManager::GetResultById( CUtlVector< IMatchSearchResult * > &arr, XUID id )
  138. {
  139. for ( int k = 0; k < arr.Count(); ++ k )
  140. {
  141. IMatchSearchResult *pResult = arr[k];
  142. if ( pResult && ( pResult->GetOnlineId() == id ) )
  143. return pResult;
  144. }
  145. return NULL;
  146. }
  147. void CSearchManager::Destroy()
  148. {
  149. if ( m_pSearcher )
  150. m_pSearcher->Destroy();
  151. m_pSearcher = NULL;
  152. delete this;
  153. }
  154. void CSearchManager::OnEvent( KeyValues *pEvent )
  155. {
  156. }
  157. void CSearchManager::Update()
  158. {
  159. switch ( m_eState )
  160. {
  161. case STATE_IDLE:
  162. if ( m_pSettings )
  163. {
  164. m_eState = STATE_SEARCHING;
  165. if( m_pSearcher )
  166. m_pSearcher->Destroy();
  167. m_pSearcher = new CMatchSearcher_SearchMgr( this, m_pSettings->MakeCopy() );
  168. }
  169. break;
  170. case STATE_SEARCHING:
  171. case STATE_SEARCHING_CRITERIA_UPDATED:
  172. Assert( m_pSearcher );
  173. m_pSearcher->Update();
  174. break;
  175. case STATE_PAUSED:
  176. if ( Plat_FloatTime() > m_flNextSearchTime &&
  177. !IsLocalClientConnectedToServer() )
  178. {
  179. // Trigger another search
  180. m_eState = STATE_IDLE;
  181. }
  182. break;
  183. }
  184. }
  185. void CSearchManager::OnSearchDone()
  186. {
  187. if ( m_eState == STATE_SEARCHING_CRITERIA_UPDATED )
  188. {
  189. m_eState = STATE_IDLE;
  190. }
  191. else
  192. {
  193. m_eState = STATE_PAUSED;
  194. m_flNextSearchTime = Plat_FloatTime() + mm_match_search_update_interval.GetFloat();
  195. }
  196. // Prepare the new results
  197. IMatchTitleGameSettingsMgr *mgr = g_pMMF->GetMatchTitleGameSettingsMgr();
  198. CUtlVector< IMatchSearchResult * > arrResults;
  199. // Now traverse the results we received and roll them up
  200. for ( int k = 0, kNum = m_pSearcher->GetNumSearchResults(); k < kNum; ++ k )
  201. {
  202. CMatchSearcher::SearchResult_t const &sr = m_pSearcher->GetSearchResult( k );
  203. KeyValues *pDetails = sr.GetGameDetails();
  204. if ( !pDetails )
  205. continue;
  206. // Determine the rollup key
  207. KeyValues *pRollupKey = mgr->RollupGameDetails( pDetails, NULL, m_pSearcher->GetSearchSettings() );
  208. KeyValues::AutoDelete autodelete_pRollupKey( pRollupKey );
  209. if ( !pRollupKey )
  210. continue;
  211. // Find if we already have the rollup information for it
  212. XUID uidKey = pRollupKey->GetUint64( "rollupkey", 0ull );
  213. if ( !uidKey )
  214. continue;
  215. IMatchSearchResult *pResult = GetResultById( arrResults, uidKey );
  216. if ( !pResult )
  217. {
  218. pResult = new CMatchSearchResultItem( uidKey, pRollupKey );
  219. arrResults.AddToTail( pResult );
  220. }
  221. // Roll up these details into an already existing or newly created rollup
  222. mgr->RollupGameDetails( pDetails, pResult->GetGameDetails(), m_pSearcher->GetSearchSettings() );
  223. }
  224. // Now after all the rollup is finished, process ones that have not had any matching details
  225. for ( int k = 0; k < m_arrResults.Count(); ++ k )
  226. {
  227. IMatchSearchResult *pOldResult = m_arrResults[k];
  228. XUID uidKey = pOldResult->GetOnlineId();
  229. if ( GetResultById( arrResults, uidKey ) )
  230. continue; // have fresh data
  231. if ( !mgr->RollupGameDetails( NULL, pOldResult->GetGameDetails(), m_pSearcher->GetSearchSettings() ) )
  232. continue; // cannot keep this result
  233. arrResults.AddToTail( pOldResult );
  234. m_arrResults.FastRemove( k -- );
  235. }
  236. // Remove all old results, swap for new results and broadcast a notification
  237. ClearResults( m_arrResults );
  238. m_arrResults.Swap( arrResults );
  239. }
  240. //
  241. // MatchSearcher override
  242. //
  243. CMatchSearcher_SearchMgr::CMatchSearcher_SearchMgr( CSearchManager *pMgr, KeyValues *pSettings ) :
  244. CMatchSearcher( pSettings ),
  245. m_pMgr( pMgr )
  246. {
  247. // Let the title extend the game settings
  248. g_pMMF->GetMatchTitleGameSettingsMgr()->InitializeGameSettings( m_pSettings, "search_rollup" );
  249. DevMsg( "CMatchSearcher_SearchMgr title adjusted settings:\n" );
  250. KeyValuesDumpAsDevMsg( m_pSettings, 1 );
  251. // Signal that we are starting a search
  252. KeyValues *pNotify = new KeyValues( "OnMatchSearchMgrUpdate", "update", "searchstarted" );
  253. pNotify->SetPtr( "mgr", m_pMgr );
  254. g_pMatchFramework->GetEventsSubscription()->BroadcastEvent( pNotify );
  255. }
  256. void CMatchSearcher_SearchMgr::StartSearchPass( KeyValues *pSearchPass )
  257. {
  258. CMatchSearcher::StartSearchPass( pSearchPass );
  259. }
  260. void CMatchSearcher_SearchMgr::OnSearchEvent( KeyValues *pNotify )
  261. {
  262. // Swallow events
  263. pNotify->deleteThis();
  264. }
  265. void CMatchSearcher_SearchMgr::OnSearchDone()
  266. {
  267. CMatchSearcher::OnSearchDone();
  268. m_pMgr->OnSearchDone();
  269. // Signal that we are finished with search
  270. KeyValues *pNotify = new KeyValues( "OnMatchSearchMgrUpdate", "update", "searchfinished" );
  271. pNotify->SetPtr( "mgr", m_pMgr );
  272. g_pMatchFramework->GetEventsSubscription()->BroadcastEvent( pNotify );
  273. }
  274. //
  275. // CMatchSearchResultItem implementation
  276. //
  277. CMatchSearchResultItem::CMatchSearchResultItem( XUID xuid, KeyValues *pDetails ) :
  278. m_xuid( xuid ),
  279. m_pDetails( pDetails ? pDetails->MakeCopy() : NULL )
  280. {
  281. }
  282. CMatchSearchResultItem::~CMatchSearchResultItem()
  283. {
  284. if ( m_pDetails )
  285. m_pDetails->deleteThis();
  286. m_pDetails = NULL;
  287. }
  288. void CMatchSearchResultItem::Join()
  289. {
  290. if ( !m_pDetails )
  291. return;
  292. // Detach details
  293. KeyValues *pSettings = m_pDetails;
  294. m_pDetails = NULL;
  295. // Trigger matchmaking
  296. g_pMatchFramework->MatchSession( pSettings );
  297. // Delete settings
  298. pSettings->deleteThis();
  299. }