PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/Code/GameSDK/GameDll/Network/Lobby/MatchmakingHandler.cpp

https://gitlab.com/blackbird91/CS188_AI_Game
C++ | 754 lines | 566 code | 127 blank | 61 comment | 82 complexity | 8c9fb5ca3eefb205002907e2b913c341 MD5 | raw file
  1. /*
  2. * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
  3. * its licensors.
  4. *
  5. * For complete copyright and license terms please see the LICENSE at the root of this
  6. * distribution (the "License"). All use of this software is governed by the License,
  7. * or, if provided, by the license below or the license accompanying this file. Do not
  8. * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
  9. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. *
  11. */
  12. // Original file Copyright Crytek GMBH or its affiliates, used under license.
  13. // Description : Class for interface between C++ and Lua for MatchMaking
  14. #include "StdAfx.h"
  15. //////////////////////////////////////////////////////////////////////////
  16. // This Include
  17. #include "MatchMakingHandler.h"
  18. #include "GameLobby.h"
  19. #include "GameLobbyManager.h"
  20. #include "GameLobbyCVars.h"
  21. #include "MatchMakingTelemetry.h"
  22. #include "MatchMakingEvents.h"
  23. #include "GameBrowser.h"
  24. #include "ScriptBind_MatchMaking.h"
  25. #include "GameCVars.h"
  26. int CMatchMakingHandler::s_currentMMSearchID = 0;
  27. //------------------------------------------------------------------------
  28. //Constructor
  29. CMatchMakingHandler::CMatchMakingHandler()
  30. : m_pScript( gEnv->pScriptSystem, true ),
  31. m_sessionIdIndex( 0 ),
  32. m_bActive( false ),
  33. m_nSessionParams( 0 ),
  34. m_bIsMerging( false ),
  35. m_startTime( 0.0f ),
  36. m_subscribedUpdateTimer( -1.0f )
  37. {
  38. ClearSessionParameters();
  39. }
  40. //------------------------------------------------------------------------
  41. //Destructor
  42. CMatchMakingHandler::~CMatchMakingHandler()
  43. {
  44. }
  45. //------------------------------------------------------------------------
  46. bool CMatchMakingHandler::LoadScript()
  47. {
  48. bool retval = true;
  49. if( gEnv->pScriptSystem )
  50. {
  51. // Load matchmaking script.
  52. retval = gEnv->pScriptSystem->ExecuteFile( "scripts/Matchmaking/matchmaking.lua", true, true );
  53. if( retval )
  54. {
  55. retval = gEnv->pScriptSystem->GetGlobalValue( "MatchMaking", m_pScript );
  56. }
  57. }
  58. return retval;
  59. }
  60. //------------------------------------------------------------------------
  61. void CMatchMakingHandler::OnInit( CGameLobbyManager* pLobbyManager )
  62. {
  63. g_pGame->GetMatchMakingScriptBind()->AttachTo( this, pLobbyManager );
  64. for( int i = 0; i < k_maxTasks; i++ )
  65. {
  66. m_waitingTasksQueue[i].taskType = eMMHT_None;
  67. m_waitingTasksQueue[i].taskSuccess = false;
  68. }
  69. m_currentTask = m_newTask = 0;
  70. m_bIsMerging = false;
  71. m_nSessionParams = 0;
  72. HSCRIPTFUNCTION scriptFunction;
  73. if( m_pScript->GetValue( "OnInit", scriptFunction ) )
  74. {
  75. Script::Call( gEnv->pScriptSystem, scriptFunction, m_pScript );
  76. gEnv->pScriptSystem->ReleaseFunc( scriptFunction );
  77. }
  78. }
  79. //------------------------------------------------------------------------
  80. void CMatchMakingHandler::OnEnterMatchMaking()
  81. {
  82. if( m_bActive )
  83. return;
  84. LoadScript();
  85. OnInit( g_pGame->GetGameLobbyManager() );
  86. HSCRIPTFUNCTION scriptFunction;
  87. if( m_pScript->GetValue( "OnEnterMatchMaking", scriptFunction ) )
  88. {
  89. Script::Call( gEnv->pScriptSystem, scriptFunction, m_pScript );
  90. gEnv->pScriptSystem->ReleaseFunc( scriptFunction );
  91. }
  92. m_startTime = gEnv->pTimer->GetFrameStartTime().GetSeconds();
  93. m_bActive = true;
  94. m_subscribedUpdateTimer = -1.0f;
  95. }
  96. //------------------------------------------------------------------------
  97. void CMatchMakingHandler::OnLeaveMatchMaking()
  98. {
  99. CryLog( "MMLua: Leaving matchmaking" );
  100. if( !m_bActive )
  101. return;
  102. HSCRIPTFUNCTION scriptFunction;
  103. if( m_pScript->GetValue( "OnLeaveMatchMaking", scriptFunction ) )
  104. {
  105. Script::Call( gEnv->pScriptSystem, scriptFunction, m_pScript );
  106. gEnv->pScriptSystem->ReleaseFunc( scriptFunction );
  107. }
  108. m_sessionIdMap.clear();
  109. //remove our reference to the script table so it can be released
  110. m_pScript = NULL;
  111. m_bActive = false;
  112. }
  113. //------------------------------------------------------------------------
  114. void CMatchMakingHandler::Search( int freeSlots, int maxResults, SCrySessionSearchData* searchParameters, int numSearchParameters )
  115. {
  116. //might still want equivalents of these
  117. //m_findGameTimeout = GetFindGameTimeout();
  118. //m_findGameResults.clear();
  119. SCrySessionSearchParam param;
  120. param.m_type = FIND_GAME_SESSION_QUERY;
  121. param.m_data = searchParameters;
  122. param.m_numFreeSlots = freeSlots;
  123. CRY_ASSERT(param.m_numFreeSlots > 0);
  124. param.m_maxNumReturn = maxResults;
  125. param.m_ranked = false;
  126. int curData = 0;
  127. CRY_ASSERT_MESSAGE( numSearchParameters < FIND_GAMES_SEARCH_NUM_DATA, "Session search data buffer overrun" );
  128. searchParameters[ numSearchParameters ].m_operator = eCSSO_Equal;
  129. searchParameters[ numSearchParameters ].m_data.m_id = LID_MATCHDATA_VERSION;
  130. searchParameters[ numSearchParameters ].m_data.m_type = eCLUDT_Int32;
  131. searchParameters[ numSearchParameters ].m_data.m_int32 = GameLobbyData::GetVersion();
  132. numSearchParameters++;
  133. param.m_numData = numSearchParameters;
  134. ++s_currentMMSearchID;
  135. #if defined(TRACK_MATCHMAKING)
  136. if( CMatchmakingTelemetry* pMMTel = g_pGame->GetMatchMakingTelemetry() )
  137. {
  138. pMMTel->AddEvent( SMMStartSearchEvent( param, s_currentMMSearchID ) );
  139. }
  140. #endif
  141. ECryLobbyError result = g_pGame->GetGameBrowser()->StartSearchingForServers(&param, CMatchMakingHandler::SearchCallback, this, false);
  142. if (result == eCLE_Success)
  143. {
  144. CryLog("MatchMakingHandler::Search() search successfully started, ");//setting s_bShouldBeSearching to FALSE to prevent another one starting");
  145. }
  146. else
  147. {
  148. CryLog("MatchMakingHandler::Search() search failed to start (error=%i)", result);// setting s_bShouldBeSearching to TRUE so we start another one when the timeout occurs", result);
  149. }
  150. }
  151. //------------------------------------------------------------------------
  152. void CMatchMakingHandler::CancelSearch()
  153. {
  154. if( CGameBrowser *pGameBrowser = g_pGame->GetGameBrowser() )
  155. {
  156. pGameBrowser->CancelSearching();
  157. }
  158. }
  159. //------------------------------------------------------------------------
  160. void CMatchMakingHandler::SearchCallback( CryLobbyTaskID taskID, ECryLobbyError error, SCrySessionSearchResult* session, void* arg )
  161. {
  162. CMatchMakingHandler* pThis = (CMatchMakingHandler*)(arg);
  163. if( session )
  164. {
  165. pThis->OnSearchResult( session );
  166. }
  167. if( (error != eCLE_SuccessContinue) && (error != eCLE_SuccessUnreachable) )
  168. {
  169. #if defined (TRACK_MATCHMAKING)
  170. if( CMatchmakingTelemetry* pMMTel = g_pGame->GetMatchMakingTelemetry() )
  171. {
  172. pMMTel->AddEvent( SMMSearchTimedOutEvent( true, s_currentMMSearchID ) );
  173. }
  174. #endif
  175. //search done, inform the Lua next update
  176. pThis->AddWaitingTask( eMMHT_EndSearch, true );
  177. }
  178. }
  179. //------------------------------------------------------------------------
  180. void CMatchMakingHandler::OnSearchResult( SCrySessionSearchResult* pSession )
  181. {
  182. //session will expire at the end of the callback
  183. //so copy it into a results structure (we need lots of details to pass to the matchmaking part
  184. //store it in a map (indexed via sessionID?)
  185. //pass the index to the lua
  186. CGameLobbyManager* pLobbyManager = g_pGame->GetGameLobbyManager();
  187. if( pLobbyManager )
  188. {
  189. CGameLobby* pLobby = pLobbyManager->GetGameLobby();
  190. //first check if this result refers to a lobby we're in/hosting
  191. if( pLobby->IsCurrentSessionId( pSession->m_id ) )
  192. {
  193. //this is the session for the lobby we are in, early out
  194. return;
  195. }
  196. //also check secondary lobby
  197. if( CGameLobby* pSecondaryLobby = pLobbyManager->GetNextGameLobby() )
  198. {
  199. if( ( pSecondaryLobby->IsCurrentSessionId( pSession->m_id ) ) )
  200. {
  201. //this is the session for the lobby we are going to, early out
  202. return;
  203. }
  204. }
  205. const CGameLobby::EActiveStatus activeStatus = (CGameLobby::EActiveStatus) GameLobbyData::GetSearchResultsData( pSession, LID_MATCHDATA_ACTIVE );
  206. bool bIsBadServer = pLobby->IsBadServer( pSession->m_id );
  207. const int skillRank = pLobby->CalculateAverageSkill();
  208. const int sessionSkillRank = GameLobbyData::GetSearchResultsData( pSession, LID_MATCHDATA_SKILL );
  209. const int sessionLanguageId = GameLobbyData::GetSearchResultsData( pSession, LID_MATCHDATA_LANGUAGE );
  210. float sessionScore = LegacyC2MatchMakingScore( pSession, pLobby, false );
  211. int32 region = 0;
  212. #if GAMELOBBY_USE_COUNTRY_FILTERING
  213. region = GameLobbyData::GetSearchResultsData( pSession, LID_MATCHDATA_COUNTRY );
  214. #endif //GAMELOBBY_USE_COUNTRY_FILTERING
  215. #if defined(TRACK_MATCHMAKING)
  216. if( CMatchmakingTelemetry* pMMTel = g_pGame->GetMatchMakingTelemetry() )
  217. {
  218. pMMTel->AddEvent( SMMFoundSessionEvent( pSession, activeStatus, skillRank - sessionSkillRank, region, sessionLanguageId, bIsBadServer, sessionScore ) );
  219. }
  220. #endif //defined(TRACK_MATCHMAKING)
  221. HSCRIPTFUNCTION scriptFunction;
  222. if( m_pScript->GetValue( "OnSearchResult", scriptFunction ) )
  223. {
  224. //Make a table to hold the search result
  225. SmartScriptTable result( gEnv->pScriptSystem );
  226. SessionDetails newSession;
  227. newSession.m_id = pSession->m_id;
  228. cry_strcpy( newSession.m_name, pSession->m_data.m_name );
  229. //capture the session ID in a map
  230. std::pair< TSessionIdMap::iterator, bool > insertResult = m_sessionIdMap.insert( std::make_pair( m_sessionIdIndex++, newSession ) );
  231. if( insertResult.second )
  232. {
  233. CryLog( "MMLua: Adding a server with parameters ping %d, status %d, avSkill %d", pSession->m_ping, activeStatus, sessionSkillRank );
  234. result->SetValue( "SessionId", insertResult.first->first );
  235. result->SetValue( "SearchId", s_currentMMSearchID );
  236. float timeSinceStarted = gEnv->pTimer->GetFrameStartTime().GetSeconds() - m_startTime;
  237. result->SetValue( "TimeFound", timeSinceStarted );
  238. //make a sub table to hold all the known session parameters
  239. SmartScriptTable parameters( gEnv->pScriptSystem );
  240. result->SetValue( "Parameters", parameters );
  241. parameters->SetValue( "ActiveStatus", activeStatus );
  242. parameters->SetValue( "ServerAvSkill", sessionSkillRank );
  243. parameters->SetValue( "Region", region );
  244. parameters->SetValue( "Language", sessionLanguageId );
  245. parameters->SetValue( "BadServer", bIsBadServer );
  246. parameters->SetValue( "Ping", pSession->m_ping );
  247. parameters->SetValue( "FilledSlots", pSession->m_numFilledSlots );
  248. Script::Call( gEnv->pScriptSystem, scriptFunction, m_pScript, result );
  249. gEnv->pScriptSystem->ReleaseFunc( scriptFunction );
  250. }
  251. }
  252. }
  253. }
  254. //------------------------------------------------------------------------
  255. CrySessionID CMatchMakingHandler::GetSessionId( int sessionIndex )
  256. {
  257. TSessionIdMap::const_iterator it = m_sessionIdMap.find( sessionIndex );
  258. if( it == m_sessionIdMap.end() )
  259. {
  260. return CrySessionInvalidID;
  261. }
  262. else
  263. {
  264. return it->second.m_id;
  265. }
  266. }
  267. //------------------------------------------------------------------------
  268. void CMatchMakingHandler::Join( int sessionIndex )
  269. {
  270. bool success = false;
  271. if( CGameLobby* pLobby = g_pGame->GetGameLobby() )
  272. {
  273. TSessionIdMap::const_iterator itSession = m_sessionIdMap.find( sessionIndex );
  274. if( itSession != m_sessionIdMap.end() )
  275. {
  276. #if defined (TRACK_MATCHMAKING)
  277. if( CGameLobbyManager* pLobbyMan = g_pGame->GetGameLobbyManager() )
  278. {
  279. if( CMatchmakingTelemetry* pMMTel = g_pGame->GetMatchMakingTelemetry() )
  280. {
  281. pMMTel->AddEvent( SMMChosenSessionEvent( itSession->second.m_name, itSession->second.m_id, "Lua Matchmaking", false, s_currentMMSearchID, pLobbyMan->IsPrimarySession( pLobby ) ) );
  282. }
  283. }
  284. #endif
  285. m_bIsMerging = false;
  286. success = pLobby->JoinServer( itSession->second.m_id, itSession->second.m_name, CryMatchMakingInvalidConnectionUID, false);
  287. }
  288. else
  289. {
  290. MMLog( "Unable to find session ID in session ID map", true );
  291. }
  292. }
  293. if( success == false )
  294. {
  295. AddWaitingTask( eMMHT_EndJoin, false );
  296. }
  297. }
  298. //------------------------------------------------------------------------
  299. void CMatchMakingHandler::Merge( int sessionIndex )
  300. {
  301. if( CGameLobby* pLobby = g_pGame->GetGameLobby() )
  302. {
  303. TSessionIdMap::const_iterator itSession = m_sessionIdMap.find( sessionIndex );
  304. if( itSession != m_sessionIdMap.end() )
  305. {
  306. #if defined (TRACK_MATCHMAKING)
  307. if( CGameLobbyManager* pLobbyMan = g_pGame->GetGameLobbyManager() )
  308. {
  309. if( CMatchmakingTelemetry* pMMTel = g_pGame->GetMatchMakingTelemetry() )
  310. {
  311. pMMTel->AddEvent( SMMChosenSessionEvent( itSession->second.m_name, itSession->second.m_id, "Lua Matchmaking", false, s_currentMMSearchID, pLobbyMan->IsPrimarySession( pLobby ) ) );
  312. }
  313. }
  314. #endif
  315. m_bIsMerging = true;
  316. bool success = pLobby->MergeToServer( itSession->second.m_id );
  317. if( success == false )
  318. {
  319. AddWaitingTask( eMMHT_EndMerge, false );
  320. }
  321. }
  322. }
  323. }
  324. //------------------------------------------------------------------------
  325. void CMatchMakingHandler::GameLobbyJoinFinished( ECryLobbyError error )
  326. {
  327. bool success = (error == eCLE_Success);
  328. if( m_bIsMerging )
  329. {
  330. AddWaitingTask( eMMHT_EndMerge, success );
  331. }
  332. else
  333. {
  334. AddWaitingTask( eMMHT_EndJoin, success );
  335. }
  336. }
  337. //------------------------------------------------------------------------
  338. void CMatchMakingHandler::GameLobbyCreateFinished( ECryLobbyError error )
  339. {
  340. bool success = (error == eCLE_Success);
  341. AddWaitingTask( eMMHT_EndCreate, success );
  342. }
  343. //------------------------------------------------------------------------
  344. void CMatchMakingHandler::Update( float dt )
  345. {
  346. if( !m_bActive )
  347. return;
  348. //peek queue
  349. EMatchMakingHandlerTask temp = m_waitingTasksQueue[ m_currentTask ].taskType;
  350. if( temp != eMMHT_None )
  351. {
  352. bool taskSuccess = m_waitingTasksQueue[ m_currentTask ].taskSuccess;
  353. switch( temp )
  354. {
  355. case eMMHT_EndSearch:
  356. {
  357. HSCRIPTFUNCTION scriptFunction;
  358. if( m_pScript->GetValue( "OnSearchFinished", scriptFunction ) )
  359. {
  360. Script::Call( gEnv->pScriptSystem, scriptFunction, m_pScript );
  361. gEnv->pScriptSystem->ReleaseFunc( scriptFunction );
  362. }
  363. else
  364. {
  365. CryLog("Important lua Function missing");
  366. }
  367. break;
  368. }
  369. case eMMHT_EndJoin:
  370. {
  371. HSCRIPTFUNCTION scriptFunction;
  372. CryLog( "MMHandler: OnJoinedFinished" );
  373. if( m_pScript->GetValue( "OnJoinFinished", scriptFunction ) )
  374. {
  375. Script::Call( gEnv->pScriptSystem, scriptFunction, m_pScript, taskSuccess );
  376. gEnv->pScriptSystem->ReleaseFunc( scriptFunction );
  377. }
  378. else
  379. {
  380. CryLog("Important lua Function missing");
  381. }
  382. break;
  383. }
  384. case eMMHT_EndMerge:
  385. {
  386. HSCRIPTFUNCTION scriptFunction;
  387. if( m_pScript->GetValue( "OnMergeFinished", scriptFunction ) )
  388. {
  389. Script::Call( gEnv->pScriptSystem, scriptFunction, m_pScript, taskSuccess );
  390. gEnv->pScriptSystem->ReleaseFunc( scriptFunction );
  391. }
  392. else
  393. {
  394. CryLog("Important lua Function missing");
  395. }
  396. break;
  397. }
  398. case eMMHT_EndCreate:
  399. {
  400. HSCRIPTFUNCTION scriptFunction;
  401. if( m_pScript->GetValue( "OnCreateFinished", scriptFunction ) )
  402. {
  403. Script::Call( gEnv->pScriptSystem, scriptFunction, m_pScript, taskSuccess );
  404. gEnv->pScriptSystem->ReleaseFunc( scriptFunction );
  405. }
  406. else
  407. {
  408. CryLog("Important lua Function missing");
  409. }
  410. break;
  411. }
  412. case eMMHT_EndHostMigrate:
  413. {
  414. CryLog( "MMHandler: OnHostMigrate" );
  415. HSCRIPTFUNCTION scriptFunction;
  416. if( m_pScript->GetValue( "OnHostMigrationFinished", scriptFunction ) )
  417. {
  418. Script::Call( gEnv->pScriptSystem, scriptFunction, m_pScript, taskSuccess, m_waitingTasksQueue[ m_currentTask ].taskData.bDat );
  419. gEnv->pScriptSystem->ReleaseFunc( scriptFunction );
  420. }
  421. break;
  422. }
  423. default:
  424. CRY_ASSERT_MESSAGE( false, "MMHandler: Invalid task ID in waiting tasks" );
  425. }
  426. //pop and loop queue
  427. m_waitingTasksQueue[ m_currentTask ].taskType = eMMHT_None;
  428. m_currentTask++;
  429. if( m_currentTask >= k_maxTasks )
  430. {
  431. m_currentTask = 0;
  432. }
  433. }
  434. if( m_subscribedUpdateTimer > 0.0f )
  435. {
  436. m_subscribedUpdateTimer -= dt;
  437. if( m_subscribedUpdateTimer <= 0.0f )
  438. {
  439. m_subscribedUpdateTimer = -1.0f;
  440. CryLog( "MMLua: Calling to subscribed Update" );
  441. HSCRIPTFUNCTION scriptFunction;
  442. if( m_pScript->GetValue( "Update", scriptFunction ) )
  443. {
  444. Script::Call( gEnv->pScriptSystem, scriptFunction, m_pScript );
  445. gEnv->pScriptSystem->ReleaseFunc( scriptFunction );
  446. }
  447. else
  448. {
  449. CryLog("Important lua Function missing");
  450. }
  451. }
  452. }
  453. }
  454. //------------------------------------------------------------------------
  455. void CMatchMakingHandler::OnHostMigrationFinished( bool success, bool isNewHost )
  456. {
  457. TaskData data;
  458. data.bDat = isNewHost;
  459. AddWaitingTask(eMMHT_EndHostMigrate, success, &data );
  460. }
  461. //------------------------------------------------------------------------
  462. float CMatchMakingHandler::LegacyC2MatchMakingScore( SCrySessionSearchResult* session, CGameLobby *lobby, bool includeRand )
  463. {
  464. //Creates sub metrics (between 0-1 (1 being best))
  465. CGameLobbyCVars *pGameLobbyCVars = CGameLobbyCVars::Get();
  466. const CGameLobby::EActiveStatus activeStatus = (CGameLobby::EActiveStatus) GameLobbyData::GetSearchResultsData( session, LID_MATCHDATA_ACTIVE );
  467. const float pingScale = pGameLobbyCVars ? pGameLobbyCVars->gl_findGamePingScale : 1.f;
  468. const float idealPlayerCount = pGameLobbyCVars ? pGameLobbyCVars->gl_findGameIdealPlayerCount : 1.f;
  469. float pingSubMetric = 1.0f - clamp_tpl((session->m_ping / pingScale), 0.0f, 1.0f); //300ms or above gives you a 0 rating
  470. float playerSubMetric = clamp_tpl((float)session->m_numFilledSlots / idealPlayerCount, 0.0f, 1.0f); //more players the better
  471. float lobbySubMetric = (activeStatus != CGameLobby::eAS_Lobby) ? 0.0f : 1.f; // Prefer games that haven't started yet
  472. float skillSubMetric = 0.f;
  473. const int skillRank = lobby->CalculateAverageSkill();
  474. const int sessionSkillRank = GameLobbyData::GetSearchResultsData(session, LID_MATCHDATA_SKILL);
  475. if (skillRank)
  476. {
  477. float diff = (float) abs(skillRank - sessionSkillRank);
  478. float fracDiff = diff / (float) skillRank;
  479. skillSubMetric = 1.f - MIN(fracDiff, 1.f);
  480. skillSubMetric = (skillSubMetric * skillSubMetric);
  481. }
  482. int32 languageId = lobby->GetCurrentLanguageId();
  483. float languageSubMetric = 0.f;
  484. if (languageId == GameLobbyData::GetSearchResultsData(session, LID_MATCHDATA_LANGUAGE))
  485. {
  486. languageSubMetric = 1.f;
  487. }
  488. float randomSubMetric = ((float) (g_pGame->GetRandomNumber() & 0xffff)) / ((float) 0xffff);
  489. if(pGameLobbyCVars)
  490. {
  491. pingSubMetric *= pGameLobbyCVars->gl_findGamePingMultiplier;
  492. playerSubMetric *= pGameLobbyCVars->gl_findGamePlayerMultiplier;
  493. lobbySubMetric *= pGameLobbyCVars->gl_findGameLobbyMultiplier;
  494. skillSubMetric *= pGameLobbyCVars->gl_findGameSkillMultiplier;
  495. languageSubMetric *= pGameLobbyCVars->gl_findGameLanguageMultiplier;
  496. randomSubMetric *= pGameLobbyCVars->gl_findGameRandomMultiplier;
  497. }
  498. float score = pingSubMetric + playerSubMetric + lobbySubMetric + skillSubMetric + languageSubMetric;
  499. if( includeRand )
  500. {
  501. score += randomSubMetric;
  502. }
  503. CryLog("MMLua: Final Score %.2f", score );
  504. return score;
  505. }
  506. //------------------------------------------------------------------------
  507. bool CMatchMakingHandler::AllowedToCreateGame()
  508. {
  509. return (gEnv->IsDedicated()) || (g_pGameCVars->g_EnableDevMenuOptions != 0); // only allow create game on PC if dev options are enabled
  510. }
  511. bool CMatchMakingHandler::AddWaitingTask( EMatchMakingHandlerTask taskID, bool taskSuccess, TaskData* pData /*= NULL*/ )
  512. {
  513. if( !m_bActive )
  514. return false;
  515. bool ok = ( m_waitingTasksQueue[ m_newTask ].taskType == eMMHT_None );
  516. CRY_ASSERT( ok );
  517. if( ok )
  518. {
  519. m_waitingTasksQueue[ m_newTask ].taskType = taskID;
  520. m_waitingTasksQueue[ m_newTask ].taskSuccess = taskSuccess;
  521. if( pData )
  522. {
  523. m_waitingTasksQueue[ m_newTask ].taskData = *pData;
  524. }
  525. m_newTask++;
  526. if( m_newTask >= k_maxTasks )
  527. {
  528. m_newTask = 0;
  529. }
  530. }
  531. return ok;
  532. }
  533. void CMatchMakingHandler::MMLog( const char* message, bool isError )
  534. {
  535. if( isError )
  536. {
  537. CryLog( "MMHandlerError: %s", message );
  538. }
  539. else
  540. {
  541. CryLog( "MMHandlerLog: %s", message );
  542. }
  543. if( CMatchmakingTelemetry* pMMTel = g_pGame->GetMatchMakingTelemetry() )
  544. {
  545. pMMTel->AddEvent( SMMGenericLogEvent( message, isError ) );
  546. }
  547. }
  548. void CMatchMakingHandler::ClearSessionParameters()
  549. {
  550. for (unsigned int i = 0; i < m_nSessionParams; i++)
  551. {
  552. new (&m_sessionParams[i]) SCryLobbyUserData();
  553. }
  554. m_nSessionParams = 0;
  555. }
  556. void CMatchMakingHandler::NewSessionParameter( ELOBBYIDS paramID, ScriptAnyValue valueVal )
  557. {
  558. if( m_nSessionParams < eLDI_Num )
  559. {
  560. m_sessionParams[ m_nSessionParams ].m_id = paramID;
  561. switch( valueVal.type )
  562. {
  563. case ANY_TNUMBER:
  564. m_sessionParams[ m_nSessionParams ].m_type = eCLUDT_Int32;
  565. m_sessionParams[ m_nSessionParams ].m_int32 = (int32)valueVal.number;
  566. break;
  567. case ANY_TBOOLEAN:
  568. m_sessionParams[ m_nSessionParams ].m_type = eCLUDT_Int32;
  569. m_sessionParams[ m_nSessionParams ].m_int32 = (int32)valueVal.b;
  570. break;
  571. case ANY_THANDLE:
  572. m_sessionParams[ m_nSessionParams ].m_type = eCLUDT_Int32;
  573. m_sessionParams[ m_nSessionParams ].m_int32 = (int32)(TRUNCATE_PTR)valueVal.ptr;
  574. break;
  575. default:
  576. MMLog( "MMLua: Unsupported type in session data", true );
  577. }
  578. CryLog( "MMLua: Create Session Parameter, id %d, value %d", m_sessionParams[ m_nSessionParams ].m_id, m_sessionParams[ m_nSessionParams ].m_int32 );
  579. m_nSessionParams++;
  580. }
  581. else
  582. {
  583. MMLog( "MMLua: Too many session search parameters set from Lua", true );
  584. }
  585. }
  586. void CMatchMakingHandler::AdjustCreateSessionData( SCrySessionData* pData, uint32 maxDataItems )
  587. {
  588. if( !m_bActive )
  589. return;
  590. //for every parameter in our data
  591. for( uint32 iParam = 0; iParam < m_nSessionParams; iParam++ )
  592. {
  593. CryLobbyUserDataID paramID = m_sessionParams[ iParam ].m_id;
  594. bool found = false;
  595. //check if it is in the source data
  596. for( uint32 iData = 0; iData < pData->m_numData; iData++ )
  597. {
  598. if( pData->m_data[ iData ].m_id == paramID )
  599. {
  600. //if it is, change it
  601. CRY_ASSERT( pData->m_data[ iData ].m_type == m_sessionParams[ iParam ].m_type );
  602. pData->m_data[ iData ].m_int32 = m_sessionParams[ iParam ].m_int32;
  603. found = true;
  604. break;
  605. }
  606. }
  607. if( ! found )
  608. {
  609. //if not, check we have space for another parameter
  610. if( pData->m_numData < maxDataItems )
  611. {
  612. //and add it to the source data
  613. pData->m_data[ pData->m_numData ] = m_sessionParams[ iParam ];
  614. pData->m_numData++;
  615. }
  616. }
  617. }
  618. }
  619. void CMatchMakingHandler::RequestSubscribedUpdate( float timeToCall )
  620. {
  621. CryLog( "MMLua: Requesting an update call in %.2f secs", timeToCall );
  622. if( m_subscribedUpdateTimer > 0.0f )
  623. {
  624. CryLog( "MMLua: Asking for subscribed update but already have one set, this is bad" );
  625. }
  626. m_subscribedUpdateTimer = timeToCall;
  627. }