Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

442 lines
20 KiB

  1. //====== Copyright �, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose: CEconItem, a shared object for econ items
  4. //
  5. //=============================================================================
  6. #ifndef ECONITEMINTERFACE_H
  7. #define ECONITEMINTERFACE_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "game_item_schema.h" // needed for GameItemDefinition_t
  12. class CAttribute_String;
  13. //-----------------------------------------------------------------------------
  14. // Purpose: Template helper classes for dealing with types.
  15. //-----------------------------------------------------------------------------
  16. // StripConstIfPresent<T> will take an input type T and "return" via ResultType:
  17. //
  18. // - T: T
  19. // - const T: T
  20. //
  21. // This is used to prevent having to have different specializations for "T" versus
  22. // "const T" when checking for equivalent template type arguments, etc.
  23. template < typename T >
  24. struct StripConstIfPresent { typedef T ResultType; };
  25. template < typename T > struct StripConstIfPresent<const T> { typedef T ResultType; };
  26. // AreTypesIdentical<T, U> takes two input types and "returns" via kValue whether the
  27. // types are exactly equal. This is intended for checking type equivalence at compile-time
  28. // in ways that template specializations for functions/classes may not be ideal for.
  29. //
  30. // We use it in the attribute code to guarantee that we're only doing The Old, Scary Path
  31. // when dealing with attributes of The Old, Scary Type.
  32. template < typename T, typename U >
  33. struct AreTypesIdentical { enum { kValue = false }; };
  34. template < typename T > struct AreTypesIdentical<T, T> { enum { kValue = true }; };
  35. // IsValidAttributeValueTypeImpl<T> is a hand-made specialization for what types we want
  36. // to consider valid attribute data types. This is used as a sanity check to make sure we
  37. // don't pass in completely arbitrary types to things like FindAttribute(). (Doing so
  38. // would cause an assert at runtime, but it seems like getting compile-time asserts is
  39. // advantageous, and probably worth paying the small cost of adding to this list whenever
  40. // a new attribute type is added.)
  41. template < typename T>
  42. struct IsValidAttributeValueTypeImpl { enum { kValue = false }; };
  43. template < > struct IsValidAttributeValueTypeImpl<attrib_value_t> { enum { kValue = true }; };
  44. template < > struct IsValidAttributeValueTypeImpl<float> { enum { kValue = true }; };
  45. template < > struct IsValidAttributeValueTypeImpl<CAttribute_String> { enum { kValue = true }; };
  46. template < > struct IsValidAttributeValueTypeImpl<Vector> { enum { kValue = true }; };
  47. template < typename T >
  48. struct IsValidAttributeValueType : public IsValidAttributeValueTypeImpl< typename StripConstIfPresent<T>::ResultType > { };
  49. //-----------------------------------------------------------------------------
  50. // Purpose: Interface for callback functions per-attribute-data-type. When adding
  51. // a new attribute data type that can't be converted to any existing type,
  52. // you'll need to add a new virtual function here or the code will fail
  53. // to compile.
  54. //-----------------------------------------------------------------------------
  55. class IEconItemAttributeIterator
  56. {
  57. public:
  58. virtual ~IEconItemAttributeIterator ( ) { }
  59. // Returns whether to continue iteration after this element.
  60. virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, attrib_value_t value ) = 0;
  61. virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, float value ) = 0;
  62. virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const CAttribute_String& value ) = 0;
  63. virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const Vector& value ) = 0;
  64. };
  65. //-----------------------------------------------------------------------------
  66. // Purpose: Iterator where each callback is default implemented, but the value
  67. // is ignored. Derive from this iterator when you only care about certain
  68. // attribute types.
  69. //
  70. //-----------------------------------------------------------------------------
  71. class CEconItemSpecificAttributeIterator : public IEconItemAttributeIterator
  72. {
  73. // By default, always return true
  74. virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, attrib_value_t value ) { return true; }
  75. virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const CAttribute_String& value ) { return true; }
  76. virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const Vector& value ) { return true; }
  77. };
  78. //-----------------------------------------------------------------------------
  79. // Purpose: Interface for a single callback function per-attribute, regardless of
  80. // what type of data it stores and what the value is. This can be used
  81. // to count attributes, display generic information about definitions, etc.
  82. // but can't be used to pull data.
  83. //
  84. // To implement a subclass, override the OnIterateAttributeValueUntyped()
  85. // method.
  86. //-----------------------------------------------------------------------------
  87. class IEconItemUntypedAttributeIterator : public IEconItemAttributeIterator
  88. {
  89. public:
  90. virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, attrib_value_t ) OVERRIDE
  91. {
  92. return OnIterateAttributeValueUntyped( pAttrDef );
  93. }
  94. virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, float ) OVERRIDE
  95. {
  96. return OnIterateAttributeValueUntyped( pAttrDef );
  97. }
  98. virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const CAttribute_String& ) OVERRIDE
  99. {
  100. return OnIterateAttributeValueUntyped( pAttrDef );
  101. }
  102. virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const Vector& ) OVERRIDE
  103. {
  104. return OnIterateAttributeValueUntyped( pAttrDef );
  105. }
  106. private:
  107. virtual bool OnIterateAttributeValueUntyped( const CEconItemAttributeDefinition *pAttrDef ) = 0;
  108. };
  109. //-----------------------------------------------------------------------------
  110. // Purpose: Simple class to answer the question "does this attribute exist" without
  111. // regards to what value it might have. Intended to be used by FindAttribute()
  112. // but made global because why not.
  113. //-----------------------------------------------------------------------------
  114. class CAttributeIterator_HasAttribute : public IEconItemUntypedAttributeIterator
  115. {
  116. public:
  117. CAttributeIterator_HasAttribute( const CEconItemAttributeDefinition *pAttrDef )
  118. : m_pAttrDef( pAttrDef )
  119. , m_bFound( false )
  120. {
  121. Assert( m_pAttrDef );
  122. }
  123. bool WasFound() const
  124. {
  125. return m_bFound;
  126. }
  127. private:
  128. bool OnIterateAttributeValueUntyped( const CEconItemAttributeDefinition *pAttrDef ) OVERRIDE
  129. {
  130. // We don't assert because we might be reusing the same iterator between calls.
  131. // Assert( !m_bFound );
  132. if ( m_pAttrDef == pAttrDef )
  133. {
  134. m_bFound = true;
  135. }
  136. return !m_bFound;
  137. }
  138. private:
  139. const CEconItemAttributeDefinition *m_pAttrDef;
  140. bool m_bFound;
  141. };
  142. //-----------------------------------------------------------------------------
  143. // Purpose: Helper class to answer the question "does this attribute exist? and if
  144. // so what is its value?". There are some template shenanigans that happen
  145. // to make things as safe as possible, and to catch errors as early as
  146. // possible.
  147. //
  148. // TActualTypeInMemory: the in-memory type of the data we're going to try
  149. // to read out (ie., "attrib_value_t", "CAttribute_String",
  150. // etc.
  151. //
  152. // TTreatAsThisType: if TActualTypeInMemory is "attrib_value_t", then we're
  153. // dealing with the old attribute system and so maybe we
  154. // want to treat these bits as a float, or a bitmask, or
  155. // who knows! Specifying this type for non-attrib_value_t
  156. // in-memory types is invalid and will fail to compile.
  157. //
  158. // This class isn't intended to be used directly but instead called from
  159. // either FindAttribute() or FindAttribute_UnsafeBitwiseCast(). It's
  160. // global because C++ doesn't support template member functions on a
  161. // template class inside a standalone template function. Weird.
  162. //-----------------------------------------------------------------------------
  163. template < typename TActualTypeInMemory, typename TTreatAsThisType = TActualTypeInMemory >
  164. class CAttributeIterator_GetTypedAttributeValue : public IEconItemAttributeIterator
  165. {
  166. public:
  167. CAttributeIterator_GetTypedAttributeValue( const CEconItemAttributeDefinition *pAttrDef, TTreatAsThisType *outpValue )
  168. : m_pAttrDef( pAttrDef )
  169. , m_outpValue( outpValue )
  170. , m_bFound( false )
  171. {
  172. // If this fails, it means that the type TActualTypeInMemory isn't something the attribute
  173. // system is prepared to recognize as a valid attribute storage type. The list of valid types
  174. // are IsValidAttributeValueTypeImpl<> specializations.
  175. //
  176. // If you added a new type and didn't make a specialization for it, this will fail. If you
  177. // *didn't* add a new type, it probably means you're passing a pointer of an incorrect type
  178. // in to FindAttribute().
  179. COMPILE_TIME_ASSERT( IsValidAttributeValueType<TActualTypeInMemory>::kValue );
  180. // The only reason we allow callers to specify a different TTreatAsThisType (versus having
  181. // it always match TActualTypeInMemory) is to deal with the old attribute system, which sometimes
  182. // had attributes have int/float types and sometimes had attribute data values that were 32
  183. // arbitrary bits. We test here to make sure that we're only using the "treat these bits as
  184. // a different type" behavior code when dealing with attributes using the old storage system
  185. // (attrib_value_t) or when we're trying to get the pointer to buffer contents for a string.
  186. COMPILE_TIME_ASSERT( ((AreTypesIdentical<TActualTypeInMemory, attrib_value_t>::kValue && AreTypesIdentical<TTreatAsThisType, float>::kValue) ||
  187. (AreTypesIdentical<TActualTypeInMemory, CAttribute_String>::kValue && AreTypesIdentical<TTreatAsThisType, const char *>::kValue) ||
  188. AreTypesIdentical<TActualTypeInMemory, TTreatAsThisType>::kValue) );
  189. Assert( m_pAttrDef );
  190. Assert( outpValue );
  191. }
  192. virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, attrib_value_t value ) OVERRIDE
  193. {
  194. return OnIterateAttributeValueTyped( pAttrDef, value );
  195. }
  196. virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, float value ) OVERRIDE
  197. {
  198. return OnIterateAttributeValueTyped( pAttrDef, value );
  199. }
  200. virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const CAttribute_String& value ) OVERRIDE
  201. {
  202. return OnIterateAttributeValueTyped( pAttrDef, value );
  203. }
  204. virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const Vector& value ) OVERRIDE
  205. {
  206. return OnIterateAttributeValueTyped( pAttrDef, value );
  207. }
  208. bool WasFound() const
  209. {
  210. return m_bFound;
  211. }
  212. private:
  213. // Generic template function for handling any attribute value of any type besides the one that we're looking
  214. // for. For example, if we say "we're looking for attribute 'damage multiplier' and give me back a float", then
  215. // all other attribute value types (strings, structures, etc.) will go through this code, which does nothing
  216. // except look for caller errors.
  217. //
  218. // If you call FindAttribute() and specify the wrong type for an attribute (ie., using the above example, looking
  219. // for "damage multiplier" but feeding in a string), it will get found in this function, which will assert and
  220. // tell you you've got the wrong type. (FindAttribute() in that case will return false because it's impossible
  221. // for us to safely copy the value out.)
  222. template < typename TAnyOtherType >
  223. bool OnIterateAttributeValueTyped( const CEconItemAttributeDefinition *pAttrDef, const TAnyOtherType& value )
  224. {
  225. COMPILE_TIME_ASSERT( IsValidAttributeValueType<TAnyOtherType>::kValue );
  226. // We don't assert because we might be reusing the same iterator between calls.
  227. // Assert( !m_bFound );
  228. AssertMsg( m_pAttrDef != pAttrDef, "Incorrect type found for attribute during iteration." );
  229. return true;
  230. }
  231. // Overload for attributes of the data type we're looking for. ie., if we say "we're looking for attribute
  232. // 'damage multiplier' and give me back a float", this will be the <float> specialization. We assume that
  233. // we're only going to find at most one attribute per definition and stop looking after we've found the first.
  234. //
  235. // Note that this is just a normal member function, but is *not* a template member function, which would compile
  236. // under VC but otherwise be illegal.
  237. bool OnIterateAttributeValueTyped( const CEconItemAttributeDefinition *pAttrDef, const TActualTypeInMemory& value )
  238. {
  239. // We don't assert because we might be reusing the same iterator between calls.
  240. // Assert( !m_bFound );
  241. if ( m_pAttrDef == pAttrDef )
  242. {
  243. m_bFound = true;
  244. CopyAttributeValueToOutput( &value, reinterpret_cast<TTreatAsThisType *>( m_outpValue ) );
  245. }
  246. return !m_bFound;
  247. }
  248. private:
  249. static void CopyAttributeValueToOutput( const TActualTypeInMemory *pValue, TTreatAsThisType *out_pValue )
  250. {
  251. // Even if we are using the old attribute type system, we need to guarantee that the type
  252. // in memory (ie., uint32) and the type we're considering it as (ie., float) are the same size
  253. // because we're going to be doing bitwise casts.
  254. COMPILE_TIME_ASSERT( sizeof( TActualTypeInMemory ) == sizeof( TTreatAsThisType ) );
  255. Assert( pValue );
  256. Assert( out_pValue );
  257. *out_pValue = *reinterpret_cast<const TTreatAsThisType *>( pValue );
  258. }
  259. private:
  260. const CEconItemAttributeDefinition *m_pAttrDef;
  261. TTreatAsThisType *m_outpValue;
  262. bool m_bFound;
  263. };
  264. //-----------------------------------------------------------------------------
  265. // Purpose: Custom code path to support getting the char * result from an
  266. // attribute of type CAttribute_String.
  267. //
  268. // We can't specify the implementation here because we may or may not
  269. // have the definition of CAttribute_String in scope. We also can't
  270. // declare the template specialization here and define it later because
  271. // that would violate the standard, so instead we have the template
  272. // function call a declared-but-not-defined non-template function that
  273. // we can define later.
  274. //-----------------------------------------------------------------------------
  275. void CopyStringAttributeValueToCharPointerOutput( const CAttribute_String *pValue, const char **out_pValue );
  276. template < >
  277. inline void CAttributeIterator_GetTypedAttributeValue<CAttribute_String, const char *>::CopyAttributeValueToOutput( const CAttribute_String *pValue, const char **out_pValue )
  278. {
  279. CopyStringAttributeValueToCharPointerOutput( pValue, out_pValue );
  280. }
  281. //-----------------------------------------------------------------------------
  282. // Purpose: Look for the existence/nonexistence of an attribute with the
  283. // definition [pAttrDef]. Can be called on anything with an IterateAttributes()
  284. // member functions (IEconItemInterface, CEconItemDefinition).
  285. //-----------------------------------------------------------------------------
  286. template < typename TAttributeContainerType >
  287. bool FindAttribute( const TAttributeContainerType *pSomethingThatHasAnIterateAttributesFunction, const CEconItemAttributeDefinition *pAttrDef )
  288. {
  289. if ( !pAttrDef )
  290. return false;
  291. CAttributeIterator_HasAttribute it( pAttrDef );
  292. pSomethingThatHasAnIterateAttributesFunction->IterateAttributes( &it );
  293. return it.WasFound();
  294. }
  295. //-----------------------------------------------------------------------------
  296. // Purpose:
  297. //-----------------------------------------------------------------------------
  298. template < typename TActualTypeInMemory, typename TTreatAsThisType, typename TAttributeContainerType >
  299. bool FindAttribute_UnsafeBitwiseCast( const TAttributeContainerType *pSomethingThatHasAnIterateAttributesFunction, const CEconItemAttributeDefinition *pAttrDef, TTreatAsThisType *out_pValue )
  300. {
  301. if ( !pAttrDef )
  302. return false;
  303. CAttributeIterator_GetTypedAttributeValue<TActualTypeInMemory, TTreatAsThisType> it( pAttrDef, out_pValue );
  304. pSomethingThatHasAnIterateAttributesFunction->IterateAttributes( &it );
  305. return it.WasFound();
  306. }
  307. //-----------------------------------------------------------------------------
  308. // Purpose:
  309. //-----------------------------------------------------------------------------
  310. template < typename TAttributeContainerType, typename T >
  311. bool FindAttribute( const TAttributeContainerType *pSomethingThatHasAnIterateAttributesFunction, const CEconItemAttributeDefinition *pAttrDef, T *out_pValue )
  312. {
  313. return FindAttribute_UnsafeBitwiseCast<T, T, TAttributeContainerType>( pSomethingThatHasAnIterateAttributesFunction, pAttrDef, out_pValue );
  314. }
  315. //-----------------------------------------------------------------------------
  316. // Purpose:
  317. //-----------------------------------------------------------------------------
  318. class IEconItemInterface
  319. {
  320. public:
  321. virtual ~IEconItemInterface() { }
  322. // Is an attribute present? We neither know nor care anything about the attribute
  323. // value stored.
  324. bool FindAttribute( const CEconItemAttributeDefinition *pAttrDef ) const
  325. {
  326. return ::FindAttribute( this, pAttrDef );
  327. }
  328. // If an attribute is present, it will copy the value into out_pValue and return true.
  329. // If the attribute is not present, it will return false and not touch the value in
  330. // out_pValue. If a T is passed in that is not a type the attribute system understands,
  331. // this function will fail to compile.
  332. template < typename T >
  333. bool FindAttribute( const CEconItemAttributeDefinition *pAttrDef, T *out_pValue ) const
  334. {
  335. return ::FindAttribute( this, pAttrDef, out_pValue );
  336. }
  337. virtual int GetCustomPaintKitIndex( void ) const;
  338. virtual int GetCustomPaintKitSeed( void ) const;
  339. virtual float GetCustomPaintKitWear( float flWearDefault = 0.0f ) const;
  340. virtual float GetStickerAttributeBySlotIndexFloat( int nSlotIndex, EStickerAttributeType type, float flDefault ) const;
  341. virtual uint32 GetStickerAttributeBySlotIndexInt( int nSlotIndex, EStickerAttributeType type, uint32 uiDefault ) const;
  342. // IEconItemInterface common implementation.
  343. virtual bool IsTradable() const;
  344. virtual bool IsMarketable() const;
  345. virtual bool IsCommodity() const;
  346. virtual bool IsUsableInCrafting() const;
  347. virtual bool IsHiddenFromDropList() const;
  348. virtual RTime32 GetExpirationDate() const;
  349. // IEconItemInterface interface.
  350. virtual const GameItemDefinition_t *GetItemDefinition() const = 0;
  351. virtual uint32 GetAccountID() const = 0;
  352. virtual uint64 GetItemID() const = 0;
  353. virtual int32 GetQuality() const = 0;
  354. virtual int32 GetRarity() const = 0;
  355. virtual uint8 GetFlags() const = 0;
  356. virtual eEconItemOrigin GetOrigin() const = 0;
  357. virtual uint16 GetQuantity() const = 0;
  358. virtual uint32 GetItemLevel() const = 0;
  359. virtual bool GetInUse() const = 0; // is this item in use somewhere in the backend? (ie., cross-game trading)
  360. virtual const char *GetCustomName() const = 0; // get a user-generated name, if present, otherwise NULL; return value is UTF8
  361. virtual const char *GetCustomDesc() const = 0; // get a user-generated flavor text, if present, otherwise NULL; return value is UTF8
  362. virtual int GetItemSetIndex() const = 0;
  363. // IEconItemInterface attribute iteration interface. This is not meant to be used for
  364. // attribute lookup! This is meant for anything that requires iterating over the full
  365. // attribute list.
  366. virtual void IterateAttributes( IEconItemAttributeIterator *pIterator ) const = 0;
  367. // We can check whether the item is potentially tradable in future if enough time
  368. // passes, and if yes can get the exact date when it becomes tradable
  369. bool IsPotentiallyTradable() const;
  370. RTime32 GetCacheRefreshDateTime() const;
  371. RTime32 GetTradableAfterDateTime() const;
  372. RTime32 GetUseAfterDateTime() const;
  373. };
  374. #endif // ECONITEMINTERFACE_H