PageRenderTime 54ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://gitlab.com/blackbird91/CS188_AI_Game
C++ | 615 lines | 445 code | 93 blank | 77 comment | 46 complexity | 394a013c560302c587082824f2682a66 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 recording and sending matchmaking data.
  14. // Aim is to record the data we used to rate the available sessions and the session we chose
  15. // so we can later find out if we are making good decisions
  16. // and also data on the actual performance of the session
  17. // so we can see if our decisions are based on good data
  18. #include "StdAfx.h"
  19. //////////////////////////////////////////////////////////////////////////
  20. // This Include
  21. #include "MatchMakingTelemetry.h"
  22. #include "TelemetryCollector.h"
  23. #include "GameLobby.h"
  24. #include "GameLobbyData.h"
  25. #include "GameRulesModules/IGameRulesStateModule.h"
  26. #include "GameRulesModules/IGameRulesPlayerStatsModule.h"
  27. #include "RecordingBuffer.h"
  28. #include "PlaylistManager.h"
  29. #define MATCHMAKING_BUFFER_SIZE (4*1024)
  30. //-------------------------------------------------------------------------
  31. //Matchmaking Telemetry main class/event collector section
  32. //-------------------------------------------------------------------------
  33. //Constructor
  34. CMatchmakingTelemetry::CMatchmakingTelemetry()
  35. {
  36. m_pBuffer = NULL;
  37. m_currentTranscript = eMMTelTranscript_None;
  38. }
  39. //--------------------------------------------------------------------------
  40. //Destructor
  41. CMatchmakingTelemetry::~CMatchmakingTelemetry()
  42. {
  43. if( m_pBuffer && m_pBuffer->size() != 0 )
  44. {
  45. CryWarning( VALIDATOR_MODULE_GAME, VALIDATOR_COMMENT, "Destroying Matchmaking Telemetry object with non-transfered data present" );
  46. }
  47. //Need to check if there's any data in transit to telemetry servers here and halt it
  48. SAFE_DELETE( m_pBuffer );
  49. }
  50. //-------------------------------------------------------------------------
  51. CMatchmakingTelemetry::EMMTelRetVal CMatchmakingTelemetry::BeginMatchMakingTranscript( EMMTelTranscriptType type )
  52. {
  53. CRY_ASSERT( m_currentTranscript == eMMTelTranscript_None );
  54. m_currentTranscript = type;
  55. if( m_pBuffer == NULL )
  56. {
  57. m_pBuffer = new CRecordingBuffer( MATCHMAKING_BUFFER_SIZE );
  58. if( m_pBuffer != NULL )
  59. {
  60. m_pBuffer->SetPacketDiscardCallback( NULL, NULL );
  61. return eMMTelRV_Success;
  62. }
  63. else
  64. {
  65. return eMMTelRV_ErrorOutOfMem;
  66. }
  67. }
  68. else
  69. {
  70. return eMMTelRV_ErrorWrongState;
  71. }
  72. }
  73. //-------------------------------------------------------------------------
  74. CMatchmakingTelemetry::EMMTelRetVal CMatchmakingTelemetry::EndMatchmakingTranscript( EMMTelTranscriptType transcript, bool logLocally )
  75. {
  76. EMMTelRetVal retVal = eMMTelRV_Success;
  77. //TODO: Decide on valid ways to use Begin/End Transcript, and promote comments to warnings if these are invalid
  78. if( transcript != m_currentTranscript )
  79. {
  80. CryWarning( VALIDATOR_MODULE_GAME, VALIDATOR_COMMENT, "MMTel: Tried to close a type %d transcript block but current type is %d", transcript, m_currentTranscript );
  81. retVal = eMMTelRV_ErrorWrongState;
  82. }
  83. else if( m_pBuffer == NULL || m_pBuffer->size() == 0 )
  84. {
  85. //there is actually no data to send
  86. CryWarning( VALIDATOR_MODULE_GAME, VALIDATOR_COMMENT, "MMTel: When close a type %d transcript block there was no data to send", m_currentTranscript );
  87. retVal = eMMTelRV_ErrorWrongState;
  88. }
  89. else
  90. {
  91. //pass our buffer to our telemetry producer, the producer takes ownership of it
  92. CTelemetryCollector *tc=static_cast<CTelemetryCollector*>(static_cast<CGame*>(g_pGame)->GetITelemetryCollector());
  93. ITelemetryProducer *pProducer = new CMMTelemetryProducer( m_pBuffer );
  94. if( pProducer )
  95. {
  96. char* nameBase;
  97. switch( transcript )
  98. {
  99. case eMMTelTranscript_QuickMatch:
  100. nameBase = "matchmakingdata";
  101. break;
  102. case eMMTelTranscript_SessionQuality:
  103. nameBase = "sessionperformance";
  104. break;
  105. default:
  106. nameBase = "unknowndata";
  107. }
  108. if( logLocally )
  109. {
  110. CryFixedStringT<24> localFilename;
  111. localFilename.Format( "%s%d.xml", nameBase, gEnv->pSystem->GetApplicationInstance() );
  112. CTelemetrySaveToFile* pLogger = new CTelemetrySaveToFile( pProducer, localFilename.c_str() );
  113. if( pLogger )
  114. {
  115. pProducer = pLogger;
  116. }
  117. }
  118. CryFixedStringT<24> remoteFilename;
  119. remoteFilename.Format( "%s.xml", nameBase );
  120. tc->SubmitTelemetryProducer( pProducer, remoteFilename.c_str() );
  121. //clear out buffer pointer
  122. m_pBuffer = NULL;
  123. m_currentTranscript = eMMTelTranscript_None;
  124. }
  125. else
  126. {
  127. retVal = eMMTelRV_ErrorDispatchBlocked;
  128. }
  129. }
  130. CryLog( "MMT: End Transcript call finished" );
  131. return retVal;
  132. }
  133. //-------------------------------------------------------------------------
  134. void CMatchmakingTelemetry::AddEvent( const SMatchMakingEvent& event )
  135. {
  136. if( m_pBuffer )
  137. {
  138. m_pBuffer->AddPacket( event );
  139. }
  140. }
  141. //-------------------------------------------------------------------------
  142. void CMatchmakingTelemetry::OnOwnClientEnteredGame()
  143. {
  144. //called on every client before the game starts
  145. #if defined(TRACK_MATCHMAKING)
  146. CryLog("MMT: End Quick match Telemetry");
  147. EndMatchmakingTranscript( eMMTelTranscript_QuickMatch, true );
  148. #endif
  149. }
  150. //-------------------------------------------------------------------------
  151. void CMatchmakingTelemetry::OnClientEnteredGame( ChannelId channelId, bool isReset, EntityId playerId )
  152. {
  153. //called on the server for every player. called after OnOwnClientEnteredGame
  154. if( m_currentTranscript == eMMTelTranscript_None )
  155. {
  156. CryLog("MMT: Start Session Quality Telemetry");
  157. BeginMatchMakingTranscript( eMMTelTranscript_SessionQuality );
  158. }
  159. //tell the Telemetry System this player has joined so we know to record their session performance
  160. CGameLobby* pGameLobby = g_pGame->GetGameLobby();
  161. if( pGameLobby != NULL && pGameLobby->GetState() == eLS_Game )
  162. {
  163. SCryMatchMakingConnectionUID conUID = pGameLobby->GetConnectionUIDFromChannelID( channelId );
  164. CryUserID guid = pGameLobby->GetUserIDFromChannelID( channelId );
  165. CryFixedStringT<CRYLOBBY_USER_NAME_LENGTH> name;
  166. pGameLobby->GetPlayerNameFromChannelId( channelId, name );
  167. AddEvent( SMMPlayerJoinedEvent( name, guid, conUID ) );
  168. }
  169. }
  170. //-------------------------------------------------------------------------
  171. void CMatchmakingTelemetry::OnClientDisconnect( ChannelId channelId, EntityId playerId )
  172. {
  173. CryLog("MMT: OnClienDisconnect");
  174. //tell the Telemetry System this player has left so we know to not expect anymore session performance records
  175. CGameLobby* pGameLobby = g_pGame->GetGameLobby();
  176. if( pGameLobby )
  177. {
  178. SCryMatchMakingConnectionUID conUID = pGameLobby->GetConnectionUIDFromChannelID( channelId );
  179. CryUserID guid = pGameLobby->GetUserIDFromChannelID( channelId );
  180. AddEvent( SMMPlayerLeftEvent( guid, conUID ) );
  181. }
  182. }
  183. //-------------------------------------------------------------------------
  184. //Matchmaking Telemetry Producer Section
  185. //-------------------------------------------------------------------------
  186. //Constructor
  187. CMMTelemetryProducer::CMMTelemetryProducer( CRecordingBuffer* pInBuffer )
  188. : m_pDataBuffer( pInBuffer ),
  189. m_currentElement( pInBuffer->begin() )
  190. {
  191. }
  192. //-------------------------------------------------------------------------
  193. //Destructor
  194. CMMTelemetryProducer::~CMMTelemetryProducer()
  195. {
  196. //delete the buffer we took ownership of
  197. SAFE_DELETE( m_pDataBuffer );
  198. }
  199. //-------------------------------------------------------------------------
  200. ITelemetryProducer::EResult CMMTelemetryProducer::ProduceTelemetry( char *pOutBuffer, int inMinRequired, int inBufferSize, int *pOutWritten )
  201. {
  202. ITelemetryProducer::EResult retVal = eTS_Available;
  203. uint32 writtingIndex = 0;
  204. //change to unsigned for signed/unsigned mis-match protection
  205. uint32 bufferSize = inBufferSize;
  206. EventDataString entryString;
  207. CRecordingBuffer::iterator end = m_pDataBuffer->end();
  208. bool writtenEnough = false;
  209. if( m_currentElement == m_pDataBuffer->begin() )
  210. {
  211. //open a top level XML tag
  212. entryString.Format( "<MatchMakingTelemetryXML>\n" );
  213. if( (writtingIndex + entryString.length()) < bufferSize )
  214. {
  215. memcpy( pOutBuffer + writtingIndex, entryString.c_str(), entryString.length() );
  216. writtingIndex += entryString.length();
  217. }
  218. }
  219. while( !writtenEnough && m_currentElement != end )
  220. {
  221. switch( m_currentElement->type )
  222. {
  223. case eMMTelE_StartSearch:
  224. OutputStartSearchData( *m_currentElement, entryString );
  225. break;
  226. case eMMTelE_FoundSession:
  227. OutputFoundSessionData( *m_currentElement, entryString );
  228. break;
  229. case eMMTelE_ChosenSession:
  230. OutputChosenSessionData( *m_currentElement, entryString );
  231. break;
  232. case eMMTelE_NoServerSelected:
  233. OutputNoServerSelectedData( *m_currentElement, entryString );
  234. break;
  235. case eMMTelE_SearchTimedOut:
  236. OutputSearchTimedOutData( *m_currentElement, entryString );
  237. break;
  238. case eMMTelE_ServerConnectFailed:
  239. OutputServerConnectFailedData( *m_currentElement, entryString );
  240. break;
  241. case eMMTelE_MigrateHostLobby:
  242. OutputMigrateHostLobbyData( *m_currentElement, entryString );
  243. break;
  244. case eMMTelE_BecomeServer:
  245. OutputBecomeHostData( *m_currentElement, entryString );
  246. break;
  247. case eMMTelE_DemotedToClient:
  248. OutputDemotedData( *m_currentElement, entryString );
  249. break;
  250. case eMMTelE_MigrateCompleted:
  251. OutputMigrateCompletedData( *m_currentElement, entryString );
  252. break;
  253. case eMMTelE_ServerRequestMerge:
  254. OutputServerRequestingMergeData( *m_currentElement, entryString );
  255. break;
  256. case eMMTelE_MergeRequested:
  257. OutputMergeRequestedData( *m_currentElement, entryString );
  258. break;
  259. case eMMTelE_LaunchGame:
  260. OutputLaunchGameData( *m_currentElement, entryString );
  261. break;
  262. case eMMTelE_LeaveMatchMaking:
  263. OutputLeaveMatchMakingData( *m_currentElement, entryString );
  264. break;
  265. case eMMTelE_PlayerJoinedMM:
  266. OutputPlayerJoinedMMData( *m_currentElement, entryString );
  267. break;
  268. case eMMTelE_PlayerLeftMM:
  269. OutputPlayerLeftMMData( *m_currentElement, entryString );
  270. break;
  271. case eMMTelE_PlayerJoined:
  272. OutputPlayerJoinedData( *m_currentElement, entryString );
  273. break;
  274. case eMMTelE_PlayerLeft:
  275. OutputPlayerLeftData( *m_currentElement, entryString );
  276. break;
  277. case eMMTelE_PlayerPing:
  278. OutputPlayerPingData( *m_currentElement, entryString );
  279. break;
  280. case eMMTelE_PlayerReportLag:
  281. OutputPlayerReportLagData( *m_currentElement, entryString );
  282. break;
  283. case eMMTelE_GenericLog:
  284. OutputGenericLogData( *m_currentElement, entryString );
  285. break;
  286. //Still Need to support these types:
  287. //eMMTelE_MigrationClientAvailable:
  288. //eMMTelE_MigrationClientChosen:
  289. default: //not a type we have data for
  290. entryString.clear();
  291. }
  292. //check we have space then add the data to the buffer
  293. if( (writtingIndex + entryString.length()) < bufferSize )
  294. {
  295. memcpy( pOutBuffer + writtingIndex, entryString.c_str(), entryString.length() );
  296. writtingIndex += entryString.length();
  297. //successfully written element, move onto next
  298. m_currentElement++;
  299. }
  300. else
  301. {
  302. CRY_ASSERT_MESSAGE( (int)writtingIndex >= inMinRequired, "MatchMaking Telemetry event is too large to send" );
  303. writtenEnough = true;
  304. }
  305. }
  306. if( m_currentElement == end )
  307. {
  308. //close the top level XML tag
  309. entryString.Format( "</MatchMakingTelemetryXML>" );
  310. //check we're not going to run out of space
  311. if( (writtingIndex + entryString.length()) < bufferSize )
  312. {
  313. memcpy( pOutBuffer + writtingIndex, entryString.c_str(), entryString.length() );
  314. writtingIndex += entryString.length();
  315. retVal = eTS_EndOfStream;
  316. }
  317. }
  318. *pOutWritten = writtingIndex;
  319. return retVal;
  320. }
  321. //-------------------------------------------------------------------------
  322. void CMMTelemetryProducer::OutputStartSearchData( SRecording_Packet& eventPacket, EventDataString& entryString )
  323. {
  324. SMMStartSearchEvent& searchEvent = reinterpret_cast<SMMStartSearchEvent&>( eventPacket );
  325. entryString.Format( "<searchParams searchID=\"%d\" numFreeSlots=\"%d\" ranked=\"%d\" ", searchEvent.m_searchID, searchEvent.m_numFreeSlots, searchEvent.m_ranked );
  326. EventDataString row; //needs to be same type and size as dest string
  327. if( searchEvent.m_version != -1 )
  328. {
  329. row.Format( "version=\"%d\" ", searchEvent.m_version );
  330. entryString += row;
  331. }
  332. if( CPlaylistManager* pPlaylistmanager = g_pGame->GetPlaylistManager() )
  333. {
  334. if( searchEvent.m_playlist != -1 )
  335. {
  336. row.Format( "playlist=\"%s\" ", pPlaylistmanager->GetPlaylistNameById(searchEvent.m_playlist) );
  337. entryString += row;
  338. }
  339. if( searchEvent.m_variant != -1 )
  340. {
  341. row.Format( "variant=\"%s\" ", pPlaylistmanager->GetVariantName(searchEvent.m_variant) );
  342. entryString += row;
  343. }
  344. }
  345. if( searchEvent.m_searchRegion != -1 )
  346. {
  347. row.Format( "searchRegion=\"%d\" ", searchEvent.m_variant );
  348. entryString += row;
  349. }
  350. else
  351. {
  352. row.Format( "regionlessSearch=\"1\" " );
  353. entryString += row;
  354. }
  355. row.Format( "timestamp=\"%lld\" />\n", searchEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  356. entryString += row;
  357. }
  358. //-------------------------------------------------------------------------
  359. void CMMTelemetryProducer::OutputFoundSessionData( SRecording_Packet& eventPacket, EventDataString& entryString )
  360. {
  361. SMMFoundSessionEvent& sessionEvent = reinterpret_cast<SMMFoundSessionEvent&>( eventPacket );
  362. const char* pStatusName = NULL;
  363. switch( sessionEvent.m_status )
  364. {
  365. case CGameLobby::eAS_Lobby:
  366. pStatusName = "Lobby";
  367. break;
  368. case CGameLobby::eAS_Game:
  369. pStatusName = "InGame";
  370. break;
  371. case CGameLobby::eAS_EndGame:
  372. pStatusName = "EndGame";
  373. break;
  374. case CGameLobby::eAS_StartingGame:
  375. pStatusName = "StartGame";
  376. break;
  377. }
  378. entryString.Format( "<foundSession serverName=\"%s\" sessionId=\"%s\" ping=\"%d\" filledSlots=\"%d\" status=\"%s\" rankDifference=\"%d\" region=\"%d\" language=\"%d\" badServer=\"%d\" c2mmscore=\"%.3f\" timestamp=\"%lld\" />\n",
  379. sessionEvent.m_sessionName, sessionEvent.m_sessionID, sessionEvent.m_ping, sessionEvent.m_filledSlots,
  380. pStatusName, sessionEvent.m_rankDiff, sessionEvent.m_region, sessionEvent.m_language, sessionEvent.m_badServer,
  381. sessionEvent.m_score, sessionEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  382. }
  383. //-------------------------------------------------------------------------
  384. void CMMTelemetryProducer::OutputChosenSessionData( SRecording_Packet& eventPacket, EventDataString& entryString )
  385. {
  386. SMMChosenSessionEvent& sessionEvent = reinterpret_cast<SMMChosenSessionEvent&>( eventPacket );
  387. char* tagName;
  388. if( sessionEvent.m_created )
  389. {
  390. tagName = "createdServer";
  391. }
  392. else
  393. {
  394. tagName = "chosenServer";
  395. }
  396. entryString.Format( "<%s searchID=\"%d\" rulesUsed=\"%s\" serverName=\"%s\" sessionId=\"%s\" isPrimary=\"%d\" timestamp=\"%lld\" />\n",
  397. tagName, sessionEvent.m_searchID, sessionEvent.m_rulesDescription, sessionEvent.m_sessionName,
  398. sessionEvent.m_sessionID, sessionEvent.m_primary, sessionEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  399. }
  400. //-------------------------------------------------------------------------
  401. void CMMTelemetryProducer::OutputServerConnectFailedData( SRecording_Packet& eventPacket, EventDataString& entryString )
  402. {
  403. SMMServerConnectFailedEvent& failedEvent = reinterpret_cast<SMMServerConnectFailedEvent&>( eventPacket );
  404. entryString.Format( "<failedToConnectToServer sessionId=\"%s\" primarySession=\"%d\" errorCode=\"%d\" timestamp=\"%lld\" />\n",
  405. failedEvent.m_sessionID, failedEvent.m_wasPrimary, failedEvent.m_errorCode, failedEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  406. }
  407. //-------------------------------------------------------------------------
  408. void CMMTelemetryProducer::OutputNoServerSelectedData( SRecording_Packet& eventPacket, EventDataString& entryString )
  409. {
  410. SMMNoServerSelectedEvent& noJoinEvent = reinterpret_cast<SMMNoServerSelectedEvent&>( eventPacket );
  411. entryString.Format( "<noServerSelected searchID=\"%d\" reason=\"%s\" timestamp=\"%lld\" />\n", noJoinEvent.m_searchID, noJoinEvent.m_reason, noJoinEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  412. }
  413. //-------------------------------------------------------------------------
  414. void CMMTelemetryProducer::OutputSearchTimedOutData( SRecording_Packet& eventPacket, EventDataString& entryString )
  415. {
  416. SMMSearchTimedOutEvent& timedoutEvent = reinterpret_cast<SMMSearchTimedOutEvent&>( eventPacket );
  417. entryString.Format( "<searchTimedOut searchID=\"%d\" searchingAgain=\"%d\" timestamp=\"%lld\" />\n", timedoutEvent.m_searchID, timedoutEvent.m_searchingAgain, timedoutEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  418. }
  419. //-------------------------------------------------------------------------
  420. void CMMTelemetryProducer::OutputMigrateHostLobbyData( SRecording_Packet& eventPacket, EventDataString& entryString )
  421. {
  422. SMMMigrateHostLobbyEvent& promoteEvent = reinterpret_cast<SMMMigrateHostLobbyEvent&>( eventPacket );
  423. entryString.Format( "<startMigrateHostInLobby timestamp=\"%lld\" />\n", promoteEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  424. }
  425. //-------------------------------------------------------------------------
  426. void CMMTelemetryProducer::OutputBecomeHostData( SRecording_Packet& eventPacket, EventDataString& entryString )
  427. {
  428. SMMBecomeHostEvent& promoteEvent = reinterpret_cast<SMMBecomeHostEvent&>( eventPacket );
  429. entryString.Format( "<promotedToHost timestamp=\"%lld\" />\n", promoteEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  430. }
  431. //-------------------------------------------------------------------------
  432. void CMMTelemetryProducer::OutputDemotedData( SRecording_Packet& eventPacket, EventDataString& entryString )
  433. {
  434. SMMBecomeHostEvent& demoteEvent = reinterpret_cast<SMMBecomeHostEvent&>( eventPacket );
  435. entryString.Format( "<demotedToClient timestamp=\"%lld\" />\n", demoteEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  436. }
  437. //-------------------------------------------------------------------------
  438. void CMMTelemetryProducer::OutputMigrateCompletedData( SRecording_Packet& eventPacket, EventDataString& entryString )
  439. {
  440. SMMMigrateCompletedEvent& migrateEvent = reinterpret_cast<SMMMigrateCompletedEvent&>( eventPacket );
  441. entryString.Format( "<migrationCompleted newHostName=\"%s\" newSessionId=\"%s\" timestamp=\"%lld\" />\n", migrateEvent.m_newServer, migrateEvent.m_newSessionID, migrateEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  442. }
  443. //-------------------------------------------------------------------------
  444. void CMMTelemetryProducer::OutputServerRequestingMergeData( SRecording_Packet& eventPacket, EventDataString& entryString )
  445. {
  446. SMMServerRequestingMerge& mergeEvent = reinterpret_cast<SMMServerRequestingMerge&>( eventPacket );
  447. entryString.Format( "<requestingMerge currentSessionId=\"%s\" newSessionId=\"%s\" timestamp=\"%lld\" />\n",
  448. mergeEvent.m_currentSessionID, mergeEvent.m_newSessionID, mergeEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  449. }
  450. //-------------------------------------------------------------------------
  451. void CMMTelemetryProducer::OutputMergeRequestedData( SRecording_Packet& eventPacket, EventDataString& entryString )
  452. {
  453. SMMMergeRequestedEvent& mergeEvent = reinterpret_cast<SMMMergeRequestedEvent&>( eventPacket );
  454. entryString.Format( "<mergeRequested newSessionId=\"%s\" timestamp=\"%lld\" />\n", mergeEvent.m_sessionID, mergeEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  455. }
  456. //-------------------------------------------------------------------------
  457. void CMMTelemetryProducer::OutputLaunchGameData( SRecording_Packet& eventPacket, EventDataString& entryString )
  458. {
  459. SMMLaunchGameEvent& launchEvent = reinterpret_cast<SMMLaunchGameEvent&>( eventPacket );
  460. entryString.Format( "<matchStarted sessionId=\"%s\" timestamp=\"%lld\" />\n", launchEvent.m_sessionID, launchEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  461. }
  462. //-------------------------------------------------------------------------
  463. void CMMTelemetryProducer::OutputLeaveMatchMakingData( SRecording_Packet& eventPacket, EventDataString& entryString )
  464. {
  465. SMMLeaveMatchMakingEvent& leaveEvent = reinterpret_cast<SMMLeaveMatchMakingEvent&>( eventPacket );
  466. entryString.Format( "<leftMatchMaking timestamp=\"%lld\" />\n", leaveEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  467. }
  468. //-------------------------------------------------------------------------
  469. void CMMTelemetryProducer::OutputPlayerJoinedMMData( SRecording_Packet& eventPacket, EventDataString& entryString )
  470. {
  471. SMMPlayerJoinedMMEvent& playerEvent = reinterpret_cast<SMMPlayerJoinedMMEvent&>( eventPacket );
  472. entryString.Format( "<playerJoined guid=\"%s\" username=\"%s\" sessionId=\"%s\" numCurrentPlayers=\"%d\" isLocal=\"%d\" timestamp = \"%lld\" />\n",
  473. playerEvent.m_guid, playerEvent.m_userName, playerEvent.m_sessionID, playerEvent.m_nCurrentPlayers,
  474. playerEvent.m_local, playerEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  475. }
  476. //-------------------------------------------------------------------------
  477. void CMMTelemetryProducer::OutputPlayerLeftMMData( SRecording_Packet& eventPacket, EventDataString& entryString )
  478. {
  479. SMMPlayerLeftMMEvent& playerEvent = reinterpret_cast<SMMPlayerLeftMMEvent&>( eventPacket );
  480. entryString.Format( "<playerLeft guid=\"%s\" username=\"%s\" sessionId=\"%s\" numCurrentPlayers=\"%d\" isLocal=\"%d\" timestamp=\"%lld\" />\n",
  481. playerEvent.m_guid, playerEvent.m_userName, playerEvent.m_sessionID, playerEvent.m_nCurrentPlayers,
  482. playerEvent.m_local, playerEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  483. }
  484. //-------------------------------------------------------------------------
  485. void CMMTelemetryProducer::OutputPlayerJoinedData( SRecording_Packet& eventPacket, EventDataString& entryString )
  486. {
  487. SMMPlayerJoinedEvent& playerEvent = reinterpret_cast<SMMPlayerJoinedEvent&>( eventPacket );
  488. entryString.Format( "<playerJoined GUID=\"%s\" conUID=\"%d\" name=\"%s\" timestamp=\"%lld\" />\n",
  489. playerEvent.m_guid, playerEvent.m_conUID.m_uid, playerEvent.m_name, playerEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  490. }
  491. //-------------------------------------------------------------------------
  492. void CMMTelemetryProducer::OutputPlayerLeftData( SRecording_Packet& eventPacket, EventDataString& entryString )
  493. {
  494. SMMPlayerLeftEvent& playerEvent = reinterpret_cast<SMMPlayerLeftEvent&>( eventPacket );
  495. entryString.Format( "<playerLeft GUID=\"%s\" conUID=\"%d\" timestamp=\"%lld\" />\n",
  496. playerEvent.m_guid, playerEvent.m_conUID.m_uid, playerEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  497. }
  498. //-------------------------------------------------------------------------
  499. void CMMTelemetryProducer::OutputPlayerPingData( SRecording_Packet& eventPacket, EventDataString& entryString )
  500. {
  501. SMMPlayerPingEvent& pingEvent = reinterpret_cast<SMMPlayerPingEvent&>( eventPacket );
  502. entryString.Format( "<playerPing GUID=\"%s\" conUID=\"%d\" ping=\"%d\" timestamp=\"%lld\" />\n",
  503. pingEvent.m_guid, pingEvent.m_conUID.m_uid, pingEvent.m_ping, pingEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  504. }
  505. //-------------------------------------------------------------------------
  506. void CMMTelemetryProducer::OutputPlayerReportLagData( SRecording_Packet& eventPacket, EventDataString& entryString )
  507. {
  508. SMMPlayerReportLagEvent& lagEvent = reinterpret_cast<SMMPlayerReportLagEvent&>( eventPacket );
  509. entryString.Format( "<playerReportLag GUID=\"%s\" timestamp=\"%lld\" />\n", lagEvent.m_guid, lagEvent.m_timeStamp.GetMilliSecondsAsInt64() );
  510. }
  511. void CMMTelemetryProducer::OutputGenericLogData( SRecording_Packet& eventPacket, EventDataString& entryString )
  512. {
  513. SMMGenericLogEvent& logEvent = reinterpret_cast<SMMGenericLogEvent&>( eventPacket );
  514. if( logEvent.m_bError )
  515. {
  516. entryString.Format( "<error message=\"%s\" />\n", logEvent.m_message );
  517. }
  518. else
  519. {
  520. entryString.Format( "<log message=\"%s\" />\n", logEvent.m_message );
  521. }
  522. }