//===== Copyright Valve Corporation, All rights reserved. ======// // // Helper class to manager clients making requests for published file information and polling the results at a later time // //==============================================================// #ifndef UGC_FILE_INFO_MANAGER #define UGC_FILE_INFO_MANAGER #ifdef _WIN32 #pragma once #endif #include "ugc_utils.h" #if !defined( NO_STEAM ) && !defined( _PS3 ) class IWorkshopFileInfoManagerCallbackInterface { public: // File requests virtual void OnFileRequestFinished( UGCHandle_t hFileHandle ) = 0; virtual void OnFileRequestError( UGCHandle_t hFileHandle ) = 0; }; // // Holds information about published files on the Workshop // class CWorkshopFileInfoManager; struct PublishedFileInfo_t { PublishedFileInfo_t( PublishedFileId_t nID = 0 ) : m_nPublishedFileId( nID ), m_hFile( k_UGCHandleInvalid ), m_hPreviewFile( k_UGCHandleInvalid ), m_ulSteamIDOwner( 0 ), m_rtimeCreated( 0 ), m_rtimeUpdated( 0 ), m_eVisibility( k_ERemoteStoragePublishedFileVisibilityPublic ), m_rtimeSubscribed( 0 ), m_rtimeLastPlayed( 0 ), m_rtimeCompleted( 0 ), m_unUpVotes( 0 ), m_unDownVotes( 0 ), m_flVotingScore( 0.0f ), m_bVotingDataValid( false ), m_unNumReports( 0 ) { memset( m_rgchTitle, 0, ARRAYSIZE( m_rgchTitle ) ); memset( m_rgchDescription, 0, ARRAYSIZE( m_rgchDescription ) ); memset( m_pchFileName, 0, ARRAYSIZE( m_pchFileName ) ); } friend class CWorkshopFileInfoManager; // Basic info PublishedFileId_t m_nPublishedFileId; char m_rgchTitle[k_cchPublishedDocumentTitleMax]; UGCHandle_t m_hFile; UGCHandle_t m_hPreviewFile; uint64 m_ulSteamIDOwner; uint32 m_rtimeCreated; uint32 m_rtimeUpdated; ERemoteStoragePublishedFileVisibility m_eVisibility; uint32 m_rtimeSubscribed; uint32 m_rtimeLastPlayed; uint32 m_rtimeCompleted; char m_rgchDescription[k_cchPublishedDocumentDescriptionMax]; char m_pchFileName[k_cchFilenameMax]; char m_rgchTags[k_cchTagListMax]; bool m_bTagsTruncated; CCopyableUtlVector m_vTags; // Whether or not the voting data has been properly collected for this item bool HasVoteData( void ) const { return m_bVotingDataValid; } // Get the vote information for this item // NOTE: Because this isn't native to the published file, it must be requested separately. // This function protects from the case where the data is not valid when requested (returns false) bool GetVoteData( float *pScore, uint32 *pUpVotes, uint32 *pDownVotes ) const { // We must have real data here to allow a query for it if ( HasVoteData() == false ) return false; if ( pScore != NULL ) { *pScore = m_flVotingScore; } if ( pUpVotes != NULL ) { *pUpVotes = m_unUpVotes; } if ( pDownVotes != NULL ) { *pDownVotes = m_unDownVotes; } return true; } bool HasTag( const char *pszTag ) const { for ( int i = 0; i < m_vTags.Count(); ++i ) { if ( !V_stricmp( m_vTags[i], pszTag ) ) { return true; } } return false; } private: // Voting info bool m_bVotingDataValid; // If this isn't true, then no request has been done to retrieve it uint32 m_unUpVotes; uint32 m_unDownVotes; float m_flVotingScore; uint32 m_unNumReports; // FIXME: This isn't exposed anywhere, currently }; // // Class which packages up info requests and how to deal with errors and completion // FIXME: May be easier to switch some of these over to callback instead of this system // class CBasePublishedFileRequest { public: CBasePublishedFileRequest( PublishedFileId_t targetID ) : m_nTargetID( targetID ) {} virtual void OnError( EResult nErrorCode ) { /* Do nothing */ } virtual void OnLoaded( PublishedFileInfo_t &info ) { /* Do nothing */ } PublishedFileId_t GetTargetID( void ) const { return m_nTargetID; } private: PublishedFileId_t m_nTargetID; // File ID to get information about }; // // // Workshop file info manager // // class CWorkshopFileInfoManager { public: CWorkshopFileInfoManager( IWorkshopFileInfoManagerCallbackInterface *pCallbackInterface ); ~CWorkshopFileInfoManager( void ); // Add a query for a published file's information bool AddFileInfoQuery( CBasePublishedFileRequest *pRequest, bool bAllowUpdate = false ); bool AddFileVoteInfoRequest( const PublishedFileInfo_t *pInfo, bool bForceUpdate = false ); bool RemovePublishedFileInfo( PublishedFileId_t nID ); void Update( void ); const PublishedFileInfo_t *GetPublishedFileInfoByID( PublishedFileId_t nID ) const; // Check if an info request hasn't been sent off yet bool IsInfoRequestStillPending( PublishedFileId_t id ) const; private: void UpdatePublishedFileInfoQueries( void ); void UpdatePublishedFileVotingInfoQueries( void ); #if !defined( _GAMECONSOLE ) CCallResult m_callbackGetPublishedFileDetails; void Steam_OnGetPublishedFileDetails( RemoteStorageGetPublishedFileDetailsResult_t *pResult, bool bError ); CCallResult m_callbackGetPublishedItemVoteDetails; void Steam_OnGetPublishedItemVoteDetails( RemoteStorageGetPublishedItemVoteDetailsResult_t *pResult, bool bError ); #endif // !_GAMECONSOLE CUtlMap< PublishedFileId_t, PublishedFileInfo_t > m_mapPublishedFileInfoDepot; // Master list of all published file information we've queried for CUtlQueue< CBasePublishedFileRequest * > m_vecPublishedFileInfoQueryList; // List of file IDs that need to be queried for information CBasePublishedFileRequest *m_pActivePublishedFileRequest; // Currently active request query (used as a mutex) CUtlQueue< PublishedFileId_t > m_vecVotingInfoRequests; // List of published file IDs we'd like voting information on bool m_bActiveVotingRequest; // Whether or not there's a voting request already pending IWorkshopFileInfoManagerCallbackInterface *m_pCallbackInterface; // User-supplied callback interface }; #endif // !NO_STEAM #endif // UGC_FILE_INFO_MANAGER