//========= Copyright Valve Corporation, All rights reserved. ============// #include "cbase.h" #include "tf_rating_data.h" #include "gcsdk/enumutils.h" #ifdef CLIENT_DLL #include "tf_matchmaking_shared.h" #endif using namespace GCSDK; #if defined( GC ) #include "tf_matchmaking_rating.h" IMPLEMENT_CLASS_MEMPOOL( CTFRatingData, 1000, UTLMEMORYPOOL_GROW_SLOW ); // Make sure you visit all these if you add new fields to rating data #define ASSERT_LAST_FIELD( foo ) COMPILE_TIME_ASSERT( CSchRatingData::k_iFieldMax == CSchRatingData::k_iField_##foo + 1 ) #else // defined( GC ) #define ASSERT_LAST_FIELD( foo ) // No Sch on client. As long as it fails somewhere. #endif // defined( GC ) // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" //----------------------------------------------------------------------------- // Purpose: Get player's rating data by steamID. Returns NULL if it doesn't exist //----------------------------------------------------------------------------- CTFRatingData *CTFRatingData::YieldingGetPlayerRatingDataBySteamID( const CSteamID &steamID, EMMRating eRatingType ) { #ifdef GC_DLL GCSDK::CGCSharedObjectCache *pSOCache = GGCEcon()->YieldingFindOrLoadSOCache( steamID ); #else GCSDK::CGCClientSharedObjectCache *pSOCache = GCClientSystem()->GetSOCache( steamID ); #endif if ( pSOCache ) { auto *pTypeCache = pSOCache->FindTypeCache( CTFRatingData::k_nTypeID ); if ( pTypeCache ) { for ( uint32 i = 0; i < pTypeCache->GetCount(); ++i ) { CTFRatingData *pRatingData = (CTFRatingData*)pTypeCache->GetObject( i ); if ( eRatingType == (EMMRating)pRatingData->Obj().rating_type() ) { return pRatingData; } } } } return nullptr; } //----------------------------------------------------------------------------- #ifdef GC CTFRatingData::CTFRatingData( uint32 unAccountID, EMMRating eRatingType ) : CTFRatingData( unAccountID, eRatingType, ITFMMRatingBackend::GetRatingBackend( eRatingType ).GetDefaultRatingData() ) {} #endif //----------------------------------------------------------------------------- CTFRatingData::CTFRatingData() {} //----------------------------------------------------------------------------- CTFRatingData::CTFRatingData( uint32 unAccountID, EMMRating eRatingType, const MMRatingData_t &ratingData ) { MutObj().set_account_id( unAccountID ); MutObj().set_rating_type( eRatingType ); MutObj().set_rating_primary( ratingData.unRatingPrimary ); MutObj().set_rating_secondary( ratingData.unRatingSecondary ); MutObj().set_rating_tertiary( ratingData.unRatingTertiary ); // MMRatingData_t fields ASSERT_LAST_FIELD( unRatingTertiary ); } #ifdef GC //----------------------------------------------------------------------------- bool CTFRatingData::BIsKeyLess( const CSharedObject & soRHS ) const { Assert( GetTypeID() == soRHS.GetTypeID() ); const CSOTFRatingData &obj = Obj(); const CSOTFRatingData &rhs = ( static_cast< const CTFRatingData & >( soRHS ) ).Obj(); if ( obj.account_id() < rhs.account_id() ) return true; if ( obj.account_id() > rhs.account_id() ) return false; return obj.rating_type() < rhs.rating_type(); } //----------------------------------------------------------------------------- // Purpose: This is a database backed object, but, all mutations to these // should go through BYieldingUpdateRatingAndAddToTransaction and its // CTFSharedObjectCache user. // // Not implementing to prevent mis-use until there's a path that legitimately // needs them to work. //----------------------------------------------------------------------------- bool CTFRatingData::BYieldingAddInsertToTransaction( GCSDK::CSQLAccess & sqlAccess ) { Assert( false ); return false; } bool CTFRatingData::BYieldingAddWriteToTransaction( GCSDK::CSQLAccess & sqlAccess, const CUtlVector< int > &fields ) { Assert( false ); return false; } bool CTFRatingData::BYieldingAddRemoveToTransaction( GCSDK::CSQLAccess & sqlAccess ) { Assert( false ); return false; } //----------------------------------------------------------------------------- void CTFRatingData::WriteToRecord( CSchRatingData *pRatingData ) const { pRatingData->m_unAccountID = Obj().account_id(); pRatingData->m_nRatingType = Obj().rating_type(); pRatingData->m_unRatingPrimary = Obj().rating_primary(); pRatingData->m_unRatingSecondary = Obj().rating_secondary(); pRatingData->m_unRatingTertiary = Obj().rating_tertiary(); ASSERT_LAST_FIELD( unRatingTertiary ); } //----------------------------------------------------------------------------- void CTFRatingData::ReadFromRecord( const CSchRatingData &ratingData ) { MutObj().set_account_id( ratingData.m_unAccountID ); MutObj().set_rating_type( ratingData.m_nRatingType ); MutObj().set_rating_primary( ratingData.m_unRatingPrimary ); MutObj().set_rating_secondary( ratingData.m_unRatingSecondary ); MutObj().set_rating_tertiary( ratingData.m_unRatingTertiary ); ASSERT_LAST_FIELD( unRatingTertiary ); } //----------------------------------------------------------------------------- // Purpose: Hook for CTFSubscriberMessageFilter to allow us to stop certain // rating types from going to certain subscribers. //----------------------------------------------------------------------------- uint32_t CTFRatingData::FilterSendFlags( uint32_t unTypeFlags ) const { auto &backend = ITFMMRatingBackend::GetRatingBackend( (EMMRating)Obj().rating_type() ); ITFMMRatingBackend::ERatingFlags eBackendFlags = backend.GetRatingFlags(); bool bNetworked = ( eBackendFlags & ITFMMRatingBackend::eRatingFlag_Networked ); bool bOwnerOnly = ( eBackendFlags & ITFMMRatingBackend::eRatingFlag_OwnerOnly ); uint32_t unRemoveFlags = 0u; if ( !bNetworked || bOwnerOnly ) { unRemoveFlags |= k_ESOFlag_SendToOtherGameservers; unRemoveFlags |= k_ESOFlag_SendToOtherUsers; } if ( !bNetworked ) { unRemoveFlags |= k_ESOFlag_SendToOwner; } return unTypeFlags & ~unRemoveFlags; } //----------------------------------------------------------------------------- // Purpose: Updates the rating fields from an MMRatingData_t, add a write or // insert to the given transaction including an audit entry. //----------------------------------------------------------------------------- bool CTFRatingData::BYieldingUpdateRatingAndAddToTransaction( CSQLAccess &transaction, const MMRatingData_t &newData, EMMRatingSource eAdjustmentSource, uint64_t unSourceEventID, RTime32 rtTimestamp ) { // MMRatingData_t fields ASSERT_LAST_FIELD( unRatingTertiary ); CSchRatingHistory schHistory; schHistory.m_unAccountID = Obj().account_id(); schHistory.m_nRatingType = Obj().rating_type(); schHistory.m_nRatingSource = eAdjustmentSource; schHistory.m_unEventID = unSourceEventID; schHistory.m_rtime32Timestamp = rtTimestamp; schHistory.m_unOldRatingPrimary = Obj().rating_primary(); schHistory.m_unOldRatingSecondary = Obj().rating_secondary(); schHistory.m_unOldRatingTertiary = Obj().rating_tertiary(); schHistory.m_unNewRatingPrimary = newData.unRatingPrimary; schHistory.m_unNewRatingSecondary = newData.unRatingSecondary; schHistory.m_unNewRatingTertiary = newData.unRatingTertiary; // Update ourself // MMRatingData_t fields ASSERT_LAST_FIELD( unRatingTertiary ); MutObj().set_rating_primary( newData.unRatingPrimary ); MutObj().set_rating_secondary( newData.unRatingSecondary ); MutObj().set_rating_tertiary( newData.unRatingTertiary ); // Create record CSchRatingData schRatingData; WriteToRecord( &schRatingData ); // Add to transaction return transaction.BYieldingInsertOrUpdateOnPK( &schRatingData ) && transaction.BYieldingInsertRecord( &schHistory ); } #endif // GC //----------------------------------------------------------------------------- // Purpose: Reads out the rating fields for rating systems to use //----------------------------------------------------------------------------- MMRatingData_t CTFRatingData::GetRatingData() { MMRatingData_t rvoData; rvoData.unRatingPrimary = Obj().rating_primary(); rvoData.unRatingSecondary = Obj().rating_secondary(); rvoData.unRatingTertiary = Obj().rating_tertiary(); // If you expanded MMRatingData_t ASSERT_LAST_FIELD( unRatingTertiary ); return rvoData; }