Team Fortress 2 Source Code as on 22/4/2020
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.

337 lines
11 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. //===================================================================
  4. #include "cbase.h"
  5. #include "econ_item_preset.h"
  6. #include "tier1/generichash.h"
  7. #ifdef GC_DLL
  8. #include "gcsdk/sqlaccess/sqlaccess.h"
  9. #endif
  10. using namespace GCSDK;
  11. #ifdef GC_DLL
  12. IMPLEMENT_CLASS_MEMPOOL( CEconItemPerClassPresetData, 10 * 1000, UTLMEMORYPOOL_GROW_SLOW );
  13. #endif
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16. // --------------------------------------------------------------------------
  17. // Purpose:
  18. // --------------------------------------------------------------------------
  19. CEconItemPerClassPresetData::CEconItemPerClassPresetData()
  20. : m_unAccountID( 0 )
  21. , m_unClassID( (equipped_class_t)-1 )
  22. , m_unActivePreset( INVALID_PRESET_INDEX )
  23. {
  24. }
  25. CEconItemPerClassPresetData::CEconItemPerClassPresetData( uint32 unAccountID, equipped_class_t unClassID )
  26. : m_unAccountID( unAccountID )
  27. , m_unClassID( unClassID )
  28. , m_unActivePreset( 0 )
  29. {
  30. }
  31. void CEconItemPerClassPresetData::SerializeToProtoBufItem( CSOClassPresetClientData& msgPresetData ) const
  32. {
  33. msgPresetData.set_account_id( m_unAccountID );
  34. msgPresetData.set_class_id( m_unClassID );
  35. msgPresetData.set_active_preset_id( m_unActivePreset );
  36. }
  37. void CEconItemPerClassPresetData::DeserializeFromProtoBufItem( const CSOClassPresetClientData &msgPresetData )
  38. {
  39. m_unAccountID = msgPresetData.account_id();
  40. m_unClassID = msgPresetData.class_id();
  41. m_unActivePreset = msgPresetData.active_preset_id();
  42. }
  43. bool CEconItemPerClassPresetData::BIsKeyLess( const CSharedObject& soRHS ) const
  44. {
  45. const CEconItemPerClassPresetData *soPresetData = assert_cast< const CEconItemPerClassPresetData * >( &soRHS );
  46. Assert( m_unAccountID == soPresetData->m_unAccountID );
  47. return m_unClassID < soPresetData->m_unClassID;
  48. }
  49. #ifdef GC
  50. static bool BYieldingAddPresetItemRowsForSpecificPreset( GCSDK::CSQLAccess &sqlAccess, CSchItemPresetInstance& schItemPresetInstance, const CUtlVector<PresetSlotItem_t>& vecPresetData )
  51. {
  52. FOR_EACH_VEC( vecPresetData, j )
  53. {
  54. schItemPresetInstance.m_unSlotID = vecPresetData[j].m_unSlotID;
  55. schItemPresetInstance.m_ulItemID = vecPresetData[j].m_ulItemOriginalID;
  56. if ( !sqlAccess.BYieldingInsertRecord( &schItemPresetInstance ) )
  57. return false;
  58. }
  59. return true;
  60. }
  61. bool CEconItemPerClassPresetData::BYieldingAddInsertToTransaction( GCSDK::CSQLAccess &sqlAccess )
  62. {
  63. // Write out the preset data for our selected items.
  64. CSchItemPresetInstance schItemPresetInstance;
  65. schItemPresetInstance.m_unAccountID = m_unAccountID;
  66. schItemPresetInstance.m_unClassID = m_unClassID;
  67. for ( int i = 0; i < ARRAYSIZE( m_PresetData ); i++ )
  68. {
  69. schItemPresetInstance.m_unPresetID = i;
  70. if ( !BYieldingAddPresetItemRowsForSpecificPreset( sqlAccess, schItemPresetInstance, m_PresetData[i] ) )
  71. return false;
  72. }
  73. // Write out the data for which preset is active for this class.
  74. CSchSelectedItemPreset schSelectedItemPreset;
  75. schSelectedItemPreset.m_unAccountID = m_unAccountID;
  76. schSelectedItemPreset.m_unClassID = m_unClassID;
  77. schSelectedItemPreset.m_unPresetID = m_unActivePreset;
  78. if ( !sqlAccess.BYieldingInsertRecord( &schSelectedItemPreset ) )
  79. return false;
  80. return true;
  81. }
  82. bool CEconItemPerClassPresetData::BYieldingAddWriteToTransaction( GCSDK::CSQLAccess &sqlAccess, const CUtlVector< int > &fields )
  83. {
  84. Assert( sqlAccess.BInTransaction() );
  85. FOR_EACH_VEC( fields, i )
  86. {
  87. const int iField = fields[i];
  88. if ( iField == kPerClassPresetDataDirtyField_ActivePreset )
  89. {
  90. CSchSelectedItemPreset schSelectedItemPreset;
  91. schSelectedItemPreset.m_unAccountID = m_unAccountID;
  92. schSelectedItemPreset.m_unClassID = m_unClassID;
  93. schSelectedItemPreset.m_unPresetID = m_unActivePreset;
  94. if ( !sqlAccess.BYieldingUpdateRecord( schSelectedItemPreset, CSET_2_COL( CSchSelectedItemPreset, k_iField_unAccountID, k_iField_unClassID ), CSET_1_COL( CSchSelectedItemPreset, k_iField_unPresetID ) ) )
  95. return false;
  96. }
  97. else if ( iField >= kPerClassPresetDataDirtyField_PresetData_Base )
  98. {
  99. int iDirtyPreset = iField - kPerClassPresetDataDirtyField_PresetData_Base;
  100. Assert( iDirtyPreset >= 0 );
  101. Assert( iDirtyPreset < ARRAYSIZE( m_PresetData ) );
  102. // First, remove any existing rows for this preset.
  103. CSchItemPresetInstance schItemPresetInstance;
  104. schItemPresetInstance.m_unAccountID = m_unAccountID;
  105. schItemPresetInstance.m_unClassID = m_unClassID;
  106. schItemPresetInstance.m_unPresetID = iDirtyPreset;
  107. if ( !sqlAccess.BYieldingDeleteRecords( schItemPresetInstance, CSET_3_COL( CSchItemPresetInstance, k_iField_unAccountID, k_iField_unPresetID, k_iField_unClassID ) ) )
  108. return false;
  109. // Don't write out data for our currently-equipped items. We'll handle these by
  110. // writing them out as actually equipped.
  111. if ( iDirtyPreset != GetActivePreset() )
  112. {
  113. // Add our new rows.
  114. if ( !BYieldingAddPresetItemRowsForSpecificPreset( sqlAccess, schItemPresetInstance, m_PresetData[iDirtyPreset] ) )
  115. return false;
  116. }
  117. }
  118. }
  119. return true;
  120. }
  121. bool CEconItemPerClassPresetData::BYieldingAddRemoveToTransaction( GCSDK::CSQLAccess &sqlAccess )
  122. {
  123. CSchItemPresetInstance schItemPresetInstance;
  124. schItemPresetInstance.m_unAccountID = m_unAccountID;
  125. schItemPresetInstance.m_unClassID = m_unClassID;
  126. if ( !sqlAccess.BYieldingDeleteRecords( schItemPresetInstance, CSET_2_COL( CSchItemPresetInstance, k_iField_unAccountID, k_iField_unClassID ) ) )
  127. return false;
  128. CSchSelectedItemPreset schSelectedItemPreset;
  129. schSelectedItemPreset.m_unAccountID = m_unAccountID;
  130. schSelectedItemPreset.m_unClassID = m_unClassID;
  131. if ( !sqlAccess.BYieldingDeleteRecords( schSelectedItemPreset, CSET_2_COL( CSchSelectedItemPreset, k_iField_unAccountID, k_iField_unClassID ) ) )
  132. return false;
  133. return true;
  134. }
  135. // --------------------------------------------------------------------------
  136. // Purpose:
  137. // --------------------------------------------------------------------------
  138. bool CEconItemPerClassPresetData::BAddToMessage( CUtlBuffer & bufOutput ) const
  139. {
  140. CSOClassPresetClientData msgClientPresetData;
  141. SerializeToProtoBufItem( msgClientPresetData );
  142. return CProtoBufSharedObjectBase::SerializeToBuffer( msgClientPresetData, bufOutput );
  143. }
  144. // --------------------------------------------------------------------------
  145. // Purpose:
  146. // --------------------------------------------------------------------------
  147. bool CEconItemPerClassPresetData::BAddToMessage( std::string *pBuffer ) const
  148. {
  149. CSOClassPresetClientData msgClientPresetData;
  150. SerializeToProtoBufItem( msgClientPresetData );
  151. return msgClientPresetData.SerializeToString( pBuffer );
  152. }
  153. //----------------------------------------------------------------------------
  154. // Purpose: Adds just the item ID to the message so that the client can find
  155. // which item to destroy
  156. //----------------------------------------------------------------------------
  157. bool CEconItemPerClassPresetData::BAddDestroyToMessage( CUtlBuffer & bufDestroy ) const
  158. {
  159. CSOClassPresetClientData msgClientPresetData;
  160. msgClientPresetData.set_class_id( m_unClassID );
  161. return CProtoBufSharedObjectBase::SerializeToBuffer( msgClientPresetData, bufDestroy );
  162. }
  163. //----------------------------------------------------------------------------
  164. // Purpose: Adds just the item ID to the message so that the client can find
  165. // which item to destroy
  166. //----------------------------------------------------------------------------
  167. bool CEconItemPerClassPresetData::BAddDestroyToMessage( std::string *pBuffer ) const
  168. {
  169. CSOClassPresetClientData msgClientPresetData;
  170. msgClientPresetData.set_class_id( m_unClassID );
  171. return msgClientPresetData.SerializeToString( pBuffer );
  172. }
  173. #endif
  174. bool CEconItemPerClassPresetData::BParseFromMessage( const CUtlBuffer & buffer )
  175. {
  176. CSOClassPresetClientData msgClientPresetData;
  177. if( !msgClientPresetData.ParseFromArray( buffer.Base(), buffer.TellMaxPut() ) )
  178. return false;
  179. DeserializeFromProtoBufItem( msgClientPresetData );
  180. return true;
  181. }
  182. bool CEconItemPerClassPresetData::BParseFromMessage( const std::string &buffer )
  183. {
  184. CSOClassPresetClientData msgClientPresetData;
  185. if( !msgClientPresetData.ParseFromString( buffer ) )
  186. return false;
  187. DeserializeFromProtoBufItem( msgClientPresetData );
  188. return true;
  189. }
  190. //----------------------------------------------------------------------------
  191. // Purpose:
  192. //----------------------------------------------------------------------------
  193. bool CEconItemPerClassPresetData::BUpdateFromNetwork( const CSharedObject & objUpdate )
  194. {
  195. Copy( objUpdate );
  196. return true;
  197. }
  198. void CEconItemPerClassPresetData::Copy( const CSharedObject & soRHS )
  199. {
  200. const CEconItemPerClassPresetData& rhs = static_cast<const CEconItemPerClassPresetData&>( soRHS );
  201. m_unAccountID = rhs.m_unAccountID;
  202. m_unClassID = rhs.m_unClassID;
  203. m_unActivePreset = rhs.m_unActivePreset;
  204. for ( int i = 0; i < ARRAYSIZE( m_PresetData ); i++ )
  205. {
  206. m_PresetData[i].CopyArray( rhs.m_PresetData[i].Base(), rhs.m_PresetData[i].Count() );
  207. }
  208. }
  209. void CEconItemPerClassPresetData::Dump() const
  210. {
  211. #if 0
  212. EmitInfo( SPEW_GC, SPEW_ALWAYS, LOG_ALWAYS, "preset id=%d class id=%d slot id=%d item id=%llu\n",
  213. m_unPresetID, m_unClassID, m_unSlotID, m_ulItemID );
  214. #endif
  215. }
  216. #ifdef GC_DLL
  217. //----------------------------------------------------------------------------
  218. // Purpose:
  219. //----------------------------------------------------------------------------
  220. const CUtlVector<PresetSlotItem_t> *CEconItemPerClassPresetData::FindItemsForPresetIndex( equipped_preset_t unPreset ) const
  221. {
  222. if ( unPreset >= ARRAYSIZE( m_PresetData ) )
  223. return NULL;
  224. return &m_PresetData[ unPreset ];
  225. }
  226. //----------------------------------------------------------------------------
  227. // Purpose:
  228. //----------------------------------------------------------------------------
  229. void CEconItemPerClassPresetData::SetActivePreset( equipped_preset_t unPreset )
  230. {
  231. if ( unPreset >= ARRAYSIZE( m_PresetData ) )
  232. return;
  233. m_unActivePreset = unPreset;
  234. }
  235. //----------------------------------------------------------------------------
  236. // Purpose:
  237. //----------------------------------------------------------------------------
  238. void CEconItemPerClassPresetData::EquipItemIntoActivePresetSlot( equipped_slot_t unSlot, itemid_t unOriginalItemID )
  239. {
  240. Assert( GetItemSchema()->IsValidItemSlot( unSlot, EQUIP_TYPE_CLASS ) );
  241. Assert( m_unActivePreset < ARRAYSIZE( m_PresetData ) );
  242. auto& PresetData = m_PresetData[m_unActivePreset];
  243. FOR_EACH_VEC( PresetData, i )
  244. {
  245. if ( PresetData[i].m_unSlotID == unSlot )
  246. {
  247. // If we're unequipping, stop tracking this slot.
  248. if ( unOriginalItemID == INVALID_ITEM_ID )
  249. {
  250. PresetData.FastRemove( i );
  251. }
  252. // Otherwise store the current reference.
  253. else
  254. {
  255. PresetData[i].m_ulItemOriginalID = unOriginalItemID;
  256. }
  257. return;
  258. }
  259. }
  260. // We don't expect to get here without having an item equipped already, but it's possible if
  261. // items get swapped around on the back end, or if we process messages out of order and/or drop
  262. // some.
  263. if ( unOriginalItemID != INVALID_ITEM_ID )
  264. {
  265. PresetSlotItem_t PresetSlotItem;
  266. PresetSlotItem.m_unSlotID = unSlot;
  267. PresetSlotItem.m_ulItemOriginalID = unOriginalItemID;
  268. PresetData.AddToTail( PresetSlotItem );
  269. }
  270. }
  271. //----------------------------------------------------------------------------
  272. // Purpose:
  273. //----------------------------------------------------------------------------
  274. void CEconItemPerClassPresetData::RemoveAllItemsFromPresetIndex( equipped_preset_t unPreset )
  275. {
  276. if ( unPreset >= ARRAYSIZE( m_PresetData ) )
  277. return;
  278. m_PresetData[unPreset].Purge();
  279. }
  280. #endif // GC_DLL