//========= Copyright Valve Corporation, All rights reserved. ============// #ifndef ECONITEMDESCRIPTION_H #define ECONITEMDESCRIPTION_H #ifdef _WIN32 #pragma once #endif #include "localization_provider.h" // needed for locchar_t type #if defined( TF_DLL ) || defined( TF_CLIENT_DLL ) || defined( TF_GC_DLL ) #define PROJECT_TF #endif #define TF_ANTI_IDLEBOT_VERIFICATION defined( PROJECT_TF ) #if TF_ANTI_IDLEBOT_VERIFICATION #define TF_ANTI_IDLEBOT_VERIFICATION_ONLY_COMMA , #define TF_ANTI_IDLEBOT_VERIFICATION_ONLY_ARG( arg ) arg #else #define TF_ANTI_IDLEBOT_VERIFICATION_ONLY_COMMA #define TF_ANTI_IDLEBOT_VERIFICATION_ONLY_ARG( arg ) #endif #if TF_ANTI_IDLEBOT_VERIFICATION #include "checksum_md5.h" #include "tf_gcmessages.pb.h" #include "tf_gcmessages.h" #ifdef CLIENT_DLL #include "gc_clientsystem.h" #endif // CLIENT_DLL #endif // TF_ANTI_IDLEBOT_VERIFICATION #ifdef GC_DLL #include "gcsdk/gclogger.h" using namespace GCSDK; #endif class IEconItemInterface; namespace GCSDK { class CSharedObjectTypeCache; } //----------------------------------------------------------------------------- // Purpose: Generate a description block for an IEconItemInterface. What the // client does with the description is anyone's guess, but this will // generate a block of UTF16 lines of text with meta/color data that // can be used for whatever. //----------------------------------------------------------------------------- enum EDescriptionLineMetaFlags { kDescLineFlag_Name = 0x001, // the item name (can be renamed by user) kDescLineFlag_Type = 0x002, // the item type (ie., "Level 5 Rocket Launcher") kDescLineFlag_Desc = 0x004, // base item description (description from the item definition, level, etc.) kDescLineFlag_Attribute = 0x008, // some sort of gameplay-affecting attribute kDescLineFlag_Misc = 0x010, // not an attribute, not name/level kDescLineFlag_Empty = 0x020, // line with no content that needs to be displayed; meant for spacing kDescLineFlag_Set = 0x040, // this line is associated with item sets somehow kDescLineFlag_LimitedUse= 0x080, // this is a limited use item kDescLineFlag_SetName = 0x100, // this line is the title for an item set kDescLineFlag_Collection = 0x200, // this line is associated with item collections kDescLineFlag_CollectionCurrentItem = 0x400, // this line is the current item being describe kDescLineFlag_CollectionName = 0x800, // this line is the collection name kDescLineFlagSet_DisplayInAttributeBlock = ~(kDescLineFlag_Name | kDescLineFlag_Type), }; struct econ_item_description_line_t { attrib_colors_t eColor; // desired color type for this line -- will likely be looked up either in VGUI or in the schema uint32 unMetaType; // type information for this line -- "item name"? "item level"?; etc.; can be game-specific CUtlConstStringBase sText; // actual text for this, post-localization item_definition_index_t unDefIndex; // item def index for description lines which represent names of other items (used by bundles) bool bIsItemForSale; // if this line is an item (eg in the case where a bundle description lists its contained items) - is the given item for sale? }; class IEconItemDescription { public: // This may yield on the GC and should never yield on the client. static void YieldingFillOutEconItemDescription( IEconItemDescription *out_pDescription, CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); public: IEconItemDescription() { } virtual ~IEconItemDescription() { } uint32 GetLineCount() const { return m_vecDescLines.Count(); } const econ_item_description_line_t& GetLine( int i ) const { return m_vecDescLines[i]; } // Finds and returns the first line with *all* of the passed in search flags. Will return NULL if a line // will all of the flags cannot be found. const econ_item_description_line_t *GetFirstLineWithMetaType( uint32 unMetaTypeSearchFlags ) const; private: // When generating an item description, this is guaranteed to be called once and only once before GenerateDescription() // is called. Any data that may yield but will be needed somewhere deep inside GenerateDescription() should be determined // and cached off here. virtual void YieldingCacheDescriptionData( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ) { } // Take the properties off our pEconItem, and anything that we calculated in YieldingCacheDescriptionData() above and // fill out all of our description lines. virtual void GenerateDescriptionLines( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ) = 0; protected: CUtlVector m_vecDescLines; }; // This will be defined as either 1 or 0 depending on which project we're in. We test its value explicitly // rather than just checking defined() because otherwise failing to include this header file will silently // result in it appearing to be undefined. #define BUILD_ITEM_NAME_AND_DESC (defined( CLIENT_DLL ) || defined( GC_DLL )) #if BUILD_ITEM_NAME_AND_DESC //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- class IAccountPersonaLocalizer { public: virtual const locchar_t *FindAccountPersonaName( uint32 unAccountID ) const = 0; }; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- class CEconItemDescription : public IEconItemDescription, public IAccountPersonaLocalizer { public: // Instances should be filled out via YieldingFillOutEconItemDescription(). CEconItemDescription() #if TF_ANTI_IDLEBOT_VERIFICATION : m_pHashContext( NULL ) , m_bIsVerbose( false ) #ifdef GC_DLL , m_bTextModeEnabled( false ) #else // if defined( CLIENT_DLL ) , m_bUnknownPlayer( false ) #endif // GC_DLL #endif // TF_ANTI_IDLEBOT_VERIFICATION { // } // External helper interface, also used internally. This should only be used to add lines // that are not a part of the properties of the item, but are instead a part of the environment // around the item (ie., "this item cannot be equipped in this slot because another item is // equipped that has conflicting regions"). // // The final argument is an optional target array to use for the description lines instead of // our internal storage. We can use this to queue up and then batch-submit/-discard lines. Passing // in NULL means "use the internal array". virtual void AddDescLine( const locchar_t *pString, attrib_colors_t eColor, uint32 unMetaType, CUtlVector *out_pOptionalDescLineDest = NULL, item_definition_index_t unDefIndex = INVALID_ITEM_DEF_INDEX, bool bIsItemForSale = true ); virtual void AddEmptyDescLine( CUtlVector *out_pOptionalDescLineDest = NULL ); virtual void LocalizedAddDescLine( const CLocalizationProvider *pLocalizationProvider, const char *pLocalizationToken, attrib_colors_t eColor, uint32 unMetaType, CUtlVector *out_pOptionalDescLineDest = NULL, item_definition_index_t unDefIndex = INVALID_ITEM_DEF_INDEX, bool bIsItemForSale = true ); // A helper class to iterate all attributes that we expect to appear on an item description. This // is useable from outside CEconItemDescription. Attributes can be accessed in iteration order or // manually sorted to be grouped by positive/negative status, etc. class CVisibleAttributeDisplayer : public IEconItemAttributeIterator { public: virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, attrib_value_t value ) OVERRIDE; virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, float value ) OVERRIDE { return true; } virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const uint64& value ) OVERRIDE { return true; } virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const CAttribute_String& value ) OVERRIDE { return true; } virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const CAttribute_DynamicRecipeComponent& value ) OVERRIDE { // Don't show these return true; } virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const CAttribute_ItemSlotCriteria& value ) OVERRIDE { // Don't show these return true; } virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const CAttribute_WorldItemPlacement& value ) OVERRIDE { // Don't show these return true; } void SortAttributes(); void Finalize( const IEconItemInterface *pEconItem, CEconItemDescription *pEconItemDescription, const CLocalizationProvider *pLocalizationProvider ); private: struct attrib_iterator_value_t { const CEconItemAttributeDefinition *m_pAttrDef; attrib_value_t m_value; }; CUtlVector m_vecAttributes; }; class CRecipeNameAttributeDisplayer : public CVisibleAttributeDisplayer { public: virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, attrib_value_t value ) OVERRIDE; }; #if TF_ANTI_IDLEBOT_VERIFICATION void SetHashContext( MD5Context_t *pHashContext ) { AssertMsg( pHashContext == NULL || m_pHashContext == NULL, "Only one hash context allowed per item description!" ); m_pHashContext = pHashContext; } void SetVerbose( bool bIsVerbose ) { m_bIsVerbose = bIsVerbose; } #ifdef GC_DLL void SetHashGCTextModeEnabled( bool bTextModeEnabled ) { m_bTextModeEnabled = bTextModeEnabled; } #endif // GC_DLL #endif // TF_ANTI_IDLEBOT_VERIFICATION #ifdef GC_DLL bool HasUnknownPlayer( ) const { return false; } #else // if defined( CLIENT_DLL ) bool HasUnknownPlayer( ) const { return m_bUnknownPlayer; } #endif private: // IEconItemDescription interface. virtual void YieldingCacheDescriptionData( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void GenerateDescriptionLines( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); private: // Internal. virtual void AddAttributeDescription( const CLocalizationProvider *pLocalizationProvider, const CEconItemAttributeDefinition *pAttribDef, attrib_value_t value, attrib_colors_t eOverrideDisplayColor = NUM_ATTRIB_COLORS ); virtual void Generate_ItemName( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_ItemLevelDesc( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); #if defined( STAGING_ONLY ) && defined( CLIENT_DLL ) virtual void Generate_DebugInformation( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); #endif // defined( DEBUG ) && defined( CLIENT_DLL ) virtual void Generate_CraftTag( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_StyleDesc( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_HolidayRestriction( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_QualityDesc( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_ItemRarityDesc( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_WearAmountDesc( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_ItemDesc( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_Bundle( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_GiftedBy( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); #ifdef PROJECT_TF virtual void Generate_DuelingMedal( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_MapContributor( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_FriendlyHat( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_SaxxyAwardDesc( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_MvmChallenges( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_SquadSurplusClaimedBy( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_DynamicRecipe( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_Leaderboard( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); #endif // PROJECT_TF virtual void Generate_XifierToolTargetItem( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_Painted( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_Uses( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_LootListDesc( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_EventDetail( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_ItemSetDesc( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_CollectionDesc( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_ExpirationDesc( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_MarketInformation( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_FlagsAttributes( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_DropPeriodDesc( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_VisibleAttributes( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); virtual void Generate_DirectX8Warning( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ); // Helpers for the above. virtual void Generate_ItemLevelDesc_Default( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem, const locchar_t *locTypename ); virtual bool BGenerate_ItemLevelDesc_StrangeNameAndStats( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem, const locchar_t *locTypename ); // returns true if generated a level/desc based on strange stats or false if nothing was generated const locchar_t *GetLocalizedStringForStrangeRestrictionAttr( const CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem, int iAttrIndex ) const; // Internal data. void YieldingFillOutAccountPersonaName( const CLocalizationProvider *pLocalizationProvider, uint32 unAccountID ); const locchar_t *FindAccountPersonaName( uint32 unAccountID ) const; void YieldingFillOutAccountTypeCache( uint32 unAccountID, int nClassID ); GCSDK::CSharedObjectTypeCache *FindAccountTypeCache( uint32 unAccountID, int nClassID ) const; // Defined in source file -- not meant for external access. template < typename T > const T *FindAccountTypeCacheSingleton( uint32 unAccountID, int nClassID ) const; // Precache data. struct steam_account_persona_name_t { uint32 unAccountID; CUtlConstStringBase loc_sPersonaName; }; CUtlVector vecPersonaNames; struct steam_account_type_cache_t { uint32 unAccountID; int nClassID; GCSDK::CSharedObjectTypeCache *pTypeCache; }; CUtlVector vecTypeCaches; #if TF_ANTI_IDLEBOT_VERIFICATION MD5Context_t *m_pHashContext; bool m_bIsVerbose; #ifdef GC_DLL bool m_bTextModeEnabled; #else // if defined( CLIENT_DLL ) bool m_bUnknownPlayer; #endif // GC_DLL #endif // TF_ANTI_IDLEBOT_VERIFICATION }; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- class CEconAttributeDescription { private: // Internal constructor. void InternalConstruct ( const CLocalizationProvider *pLocalizationProvider, const CEconItemAttributeDefinition *pAttribDef, attrib_value_t value, TF_ANTI_IDLEBOT_VERIFICATION_ONLY_ARG( MD5Context_t *pHashContext ) TF_ANTI_IDLEBOT_VERIFICATION_ONLY_COMMA IAccountPersonaLocalizer *pOptionalAccountPersonaLocalizer ); public: // Outward-facing constructor. Pass in whatever you want for "value" and we'll // use the raw bits for their value interpreted however the attribute says. template < typename T > CEconAttributeDescription ( const CLocalizationProvider *pLocalizationProvider, const CEconItemAttributeDefinition *pAttribDef, T value, TF_ANTI_IDLEBOT_VERIFICATION_ONLY_ARG( MD5Context_t *pHashContext = NULL ) TF_ANTI_IDLEBOT_VERIFICATION_ONLY_COMMA IAccountPersonaLocalizer *pOptionalAccountPersonaLocalizer = NULL ) { COMPILE_TIME_ASSERT( sizeof( T ) == sizeof( attrib_value_t ) ); InternalConstruct( pLocalizationProvider, pAttribDef, *(attrib_value_t *)&value, TF_ANTI_IDLEBOT_VERIFICATION_ONLY_ARG( pHashContext ) TF_ANTI_IDLEBOT_VERIFICATION_ONLY_COMMA pOptionalAccountPersonaLocalizer ); } const CUtlConstStringBase& GetDescription() const { return m_loc_sValue; } const CUtlConstStringBase& GetShortDescription() const { return m_loc_sShortValue; } attrib_colors_t GetDefaultColor() const { return m_eDefaultColor; } private: CUtlConstStringBase m_loc_sValue; CUtlConstStringBase m_loc_sShortValue; attrib_colors_t m_eDefaultColor; }; //----------------------------------------------------------------------------- // Purpose: control how item name is generated //----------------------------------------------------------------------------- enum EGenerateLocalizedFullItemNameFlag_t { k_EGenerateLocalizedFullItemName_Default = 0, k_EGenerateLocalizedFullItemName_WithPaintWear = ( 1 << 0 ), k_EGenerateLocalizedFullItemName_WithoutCustomName = ( 1 << 1 ), k_EGenerateLocalizedFullItemName_WithoutQuality = ( 1 << 2 ), k_EGenerateLocalizedFullItemName_WithPaintkitNoItem = ( 1 << 3 ), }; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- class CEconItemLocalizedFullNameGenerator { public: CEconItemLocalizedFullNameGenerator( const CLocalizationProvider *pLocalizationProvider, const CEconItemDefinition *pItemDef, bool bUseingHashContext = true, entityquality_t eQuality = AE_UNIQUE ); const locchar_t *GetFullName() const { return m_loc_LocalizedItemName; } private: locchar_t m_loc_LocalizedItemName[ MAX_ITEM_NAME_LENGTH ]; }; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- class CEconItemLocalizedMarketNameGenerator { public: CEconItemLocalizedMarketNameGenerator( const CLocalizationProvider *pLocalizationProvider, CEconItem *pItem, bool bUseingHashContext = true ); const locchar_t *GetFullName() const { return m_loc_LocalizedItemName; } private: locchar_t m_loc_LocalizedItemName[ MAX_ITEM_NAME_LENGTH ]; }; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- class CSteamAccountIDAttributeCollector : public CEconItemSpecificAttributeIterator { public: virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, attrib_value_t value ) OVERRIDE { if ( pAttrDef->GetDescriptionFormat() == ATTDESCFORM_VALUE_IS_ACCOUNT_ID ) { m_vecSteamAccountIDs.AddToTail( value ); } return true; } // Data access. const CUtlVector& GetAccountIDs() { return m_vecSteamAccountIDs; } private: CUtlVector m_vecSteamAccountIDs; }; // -------------------------------------------------------------------------- // Purpose: // -------------------------------------------------------------------------- #if TF_ANTI_IDLEBOT_VERIFICATION #include "checksum_md5.h" enum { kTFDescriptionHash_TextmodeArbitraryKey = 0x19a04480, kTFDescriptionHash_ValidArbitraryKey = 0xa0939180, kTFDescriptionHash_MultiRunArbitraryKey = 0x5790a31d, kTFDescriptionHash_ChallengeXorShenanigans = 0x1870f0d2, }; // Global function/variable names show up in Mac binaries so we give them names that will stand out less // here and then #define them back so the code is readable. #define TF_Description_HashDataMungeContents CompressFragments inline void TFDescription_HashDataMungeContents( MD5Context_t *out_pContext, const void *pContents, size_t unContentLength, bool bIsVerbose, const char* pszInfo ) { Assert( out_pContext ); Assert( pContents ); MD5Update( out_pContext, static_cast( pContents ), unContentLength ); // if Verbose, report the contents to the GC if ( bIsVerbose ) { MD5Context_t md5ContextEx = *out_pContext; MD5Value_t md5ResultEx; MD5Final( &md5ResultEx.bits[0], &md5ContextEx ); #ifdef GC_DLL EmitInfo( SPEW_GC, SPEW_ALWAYS, LOG_ALWAYS, "Verbose Verification GC : [ %s ] - [ %s ] \n", MD5_Print( md5ResultEx.bits, MD5_DIGEST_LENGTH ), pszInfo ); #else // Client reports this to the GC GCSDK::CProtoBufMsg msgResponse( k_EMsgGC_ClientVerificationVerboseResponse ); msgResponse.Body().set_version_checksum( pszInfo ); // before msgResponse.Body().set_version_checksum_ex( &md5ResultEx.bits[0], MD5_DIGEST_LENGTH ); // after GCClientSystem()->BSendMessage( msgResponse ); #endif //delete [] pArr; } } // Okay, this one is actually just a helper macro. #define TFDescription_HashDataMunge( context, field, bIsVerbose, pszInfo ) \ { \ TFDescription_HashDataMungeContents( context, (void *)&field, sizeof( field ), bIsVerbose, pszInfo ); \ } #endif // TF_ANTI_IDLEBOT_VERIFICATION #endif // BUILD_ITEM_NAME_AND_DESC // -------------------------------------------------------------------------- // Purpose: // -------------------------------------------------------------------------- struct CLocalizedRTime32 { RTime32 m_unTime; bool m_bForceGMTOnClient; // display this time in GMT on the client? by default, clients show local time; the GC will ignore this flag and always display GMT const CLocalizationProvider *m_pLocalizationProvider; TF_ANTI_IDLEBOT_VERIFICATION_ONLY_ARG( MD5Context_t *m_pHashContext; ) }; template < > class CLocalizedStringArg { public: enum { kIsValid = true }; CLocalizedStringArg( const CLocalizedRTime32& cTimeIn ); const locchar_t *GetLocArg() const { return m_Str.Get(); } private: CUtlConstStringBase m_Str; }; #endif // ECONITEMDESCRIPTION_H