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.

692 lines
26 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Shared object based on a CBaseRecord subclass
  4. //
  5. //=============================================================================
  6. #include "stdafx.h"
  7. #include "gcsdk_gcmessages.pb.h"
  8. #include "google/protobuf/descriptor.h"
  9. #include "google/protobuf/reflection_ops.h"
  10. #include "google/protobuf/descriptor.pb.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. using ::google::protobuf::FieldDescriptor;
  14. using ::google::protobuf::Descriptor;
  15. using ::google::protobuf::Message;
  16. using ::google::protobuf::Reflection;
  17. namespace GCSDK
  18. {
  19. //----------------------------------------------------------------------------
  20. // Purpose: returns true if the field has the key_field option
  21. //----------------------------------------------------------------------------
  22. inline bool IsKeyField( const FieldDescriptor *pFieldDescriptor )
  23. {
  24. return pFieldDescriptor->options().GetExtension( key_field );
  25. }
  26. //----------------------------------------------------------------------------
  27. // Purpose: Copies a field from one protobuf message to another
  28. //----------------------------------------------------------------------------
  29. void CopyProtoBufField( ::google::protobuf::Message & msgDest, const ::google::protobuf::Message & msgSource, const ::google::protobuf::FieldDescriptor *pFieldDest, const ::google::protobuf::FieldDescriptor *pFieldSource )
  30. {
  31. Assert( pFieldDest->cpp_type() == pFieldSource->cpp_type() );
  32. Assert( pFieldDest->is_repeated() == pFieldSource->is_repeated() );
  33. if( pFieldSource->cpp_type() != pFieldDest->cpp_type() || pFieldSource->is_repeated() != pFieldDest->is_repeated() )
  34. return;
  35. if ( pFieldDest->is_repeated() )
  36. {
  37. int nFieldSize = msgSource.GetReflection()->FieldSize( msgSource, pFieldSource );
  38. switch( pFieldDest->cpp_type() )
  39. {
  40. case ::google::protobuf::FieldDescriptor::CPPTYPE_INT32:
  41. {
  42. for ( int i = 0; i < nFieldSize; i++ )
  43. {
  44. if ( msgDest.GetReflection()->FieldSize( msgDest, pFieldDest ) <= i )
  45. {
  46. msgDest.GetReflection()->AddInt32( &msgDest, pFieldDest, msgSource.GetReflection()->GetRepeatedInt32( msgSource, pFieldSource, i ) );
  47. }
  48. else
  49. {
  50. msgDest.GetReflection()->SetRepeatedInt32( &msgDest, pFieldDest, i, msgSource.GetReflection()->GetRepeatedInt32( msgSource, pFieldSource, i ) );
  51. }
  52. }
  53. }
  54. break;
  55. case ::google::protobuf::FieldDescriptor::CPPTYPE_INT64:
  56. {
  57. for ( int i = 0; i < nFieldSize; i++ )
  58. {
  59. if ( msgDest.GetReflection()->FieldSize( msgDest, pFieldDest ) <= i )
  60. {
  61. msgDest.GetReflection()->AddInt64( &msgDest, pFieldDest, msgSource.GetReflection()->GetRepeatedInt64( msgSource, pFieldSource, i ) );
  62. }
  63. else
  64. {
  65. msgDest.GetReflection()->SetRepeatedInt64( &msgDest, pFieldDest, i, msgSource.GetReflection()->GetRepeatedInt64( msgSource, pFieldSource, i ) );
  66. }
  67. }
  68. }
  69. break;
  70. case ::google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
  71. {
  72. for ( int i = 0; i < nFieldSize; i++ )
  73. {
  74. if ( msgDest.GetReflection()->FieldSize( msgDest, pFieldDest ) <= i )
  75. {
  76. msgDest.GetReflection()->AddUInt32( &msgDest, pFieldDest, msgSource.GetReflection()->GetRepeatedUInt32( msgSource, pFieldSource, i ) );
  77. }
  78. else
  79. {
  80. msgDest.GetReflection()->SetRepeatedUInt32( &msgDest, pFieldDest, i, msgSource.GetReflection()->GetRepeatedUInt32( msgSource, pFieldSource, i ) );
  81. }
  82. }
  83. }
  84. break;
  85. case ::google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
  86. {
  87. for ( int i = 0; i < nFieldSize; i++ )
  88. {
  89. if ( msgDest.GetReflection()->FieldSize( msgDest, pFieldDest ) <= i )
  90. {
  91. msgDest.GetReflection()->AddUInt64( &msgDest, pFieldDest, msgSource.GetReflection()->GetRepeatedUInt64( msgSource, pFieldSource, i ) );
  92. }
  93. else
  94. {
  95. msgDest.GetReflection()->SetRepeatedUInt64( &msgDest, pFieldDest, i, msgSource.GetReflection()->GetRepeatedUInt64( msgSource, pFieldSource, i ) );
  96. }
  97. }
  98. }
  99. break;
  100. case ::google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
  101. {
  102. for ( int i = 0; i < nFieldSize; i++ )
  103. {
  104. if ( msgDest.GetReflection()->FieldSize( msgDest, pFieldDest ) <= i )
  105. {
  106. msgDest.GetReflection()->AddDouble( &msgDest, pFieldDest, msgSource.GetReflection()->GetRepeatedDouble( msgSource, pFieldSource, i ) );
  107. }
  108. else
  109. {
  110. msgDest.GetReflection()->SetRepeatedDouble( &msgDest, pFieldDest, i, msgSource.GetReflection()->GetRepeatedDouble( msgSource, pFieldSource, i ) );
  111. }
  112. }
  113. }
  114. break;
  115. case ::google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
  116. {
  117. for ( int i = 0; i < nFieldSize; i++ )
  118. {
  119. if ( msgDest.GetReflection()->FieldSize( msgDest, pFieldDest ) <= i )
  120. {
  121. msgDest.GetReflection()->AddFloat( &msgDest, pFieldDest, msgSource.GetReflection()->GetRepeatedFloat( msgSource, pFieldSource, i ) );
  122. }
  123. else
  124. {
  125. msgDest.GetReflection()->SetRepeatedFloat( &msgDest, pFieldDest, i, msgSource.GetReflection()->GetRepeatedFloat( msgSource, pFieldSource, i ) );
  126. }
  127. }
  128. }
  129. break;
  130. case ::google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
  131. {
  132. for ( int i = 0; i < nFieldSize; i++ )
  133. {
  134. if ( msgDest.GetReflection()->FieldSize( msgDest, pFieldDest ) <= i )
  135. {
  136. msgDest.GetReflection()->AddBool( &msgDest, pFieldDest, msgSource.GetReflection()->GetRepeatedBool( msgSource, pFieldSource, i ) );
  137. }
  138. else
  139. {
  140. msgDest.GetReflection()->SetRepeatedBool( &msgDest, pFieldDest, i, msgSource.GetReflection()->GetRepeatedBool( msgSource, pFieldSource, i ) );
  141. }
  142. }
  143. }
  144. break;
  145. case ::google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
  146. {
  147. for ( int i = 0; i < nFieldSize; i++ )
  148. {
  149. if ( msgDest.GetReflection()->FieldSize( msgDest, pFieldDest ) <= i )
  150. {
  151. msgDest.GetReflection()->AddEnum( &msgDest, pFieldDest, msgSource.GetReflection()->GetRepeatedEnum( msgSource, pFieldSource, i ) );
  152. }
  153. else
  154. {
  155. msgDest.GetReflection()->SetRepeatedEnum( &msgDest, pFieldDest, i, msgSource.GetReflection()->GetRepeatedEnum( msgSource, pFieldSource, i ) );
  156. }
  157. }
  158. }
  159. break;
  160. case ::google::protobuf::FieldDescriptor::CPPTYPE_STRING:
  161. {
  162. for ( int i = 0; i < nFieldSize; i++ )
  163. {
  164. if ( msgDest.GetReflection()->FieldSize( msgDest, pFieldDest ) <= i )
  165. {
  166. msgDest.GetReflection()->AddString( &msgDest, pFieldDest, msgSource.GetReflection()->GetRepeatedString( msgSource, pFieldSource, i ) );
  167. }
  168. else
  169. {
  170. msgDest.GetReflection()->SetRepeatedString( &msgDest, pFieldDest, i, msgSource.GetReflection()->GetRepeatedString( msgSource, pFieldSource, i ) );
  171. }
  172. }
  173. }
  174. break;
  175. case ::google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
  176. {
  177. for ( int i = 0; i < nFieldSize; i++ )
  178. {
  179. if ( msgDest.GetReflection()->FieldSize( msgDest, pFieldDest ) <= i )
  180. {
  181. msgDest.GetReflection()->AddMessage( &msgDest, pFieldDest )->CopyFrom( msgSource.GetReflection()->GetRepeatedMessage( msgSource, pFieldSource, i ) );
  182. }
  183. else
  184. {
  185. msgDest.GetReflection()->MutableRepeatedMessage( &msgDest, pFieldDest, i )->CopyFrom( msgSource.GetReflection()->GetRepeatedMessage( msgSource, pFieldSource, i ) );
  186. }
  187. }
  188. }
  189. break;
  190. }
  191. }
  192. else
  193. {
  194. switch( pFieldDest->cpp_type() )
  195. {
  196. case ::google::protobuf::FieldDescriptor::CPPTYPE_INT32:
  197. {
  198. msgDest.GetReflection()->SetInt32( &msgDest, pFieldDest, msgSource.GetReflection()->GetInt32( msgSource, pFieldSource ) );
  199. }
  200. break;
  201. case ::google::protobuf::FieldDescriptor::CPPTYPE_INT64:
  202. {
  203. msgDest.GetReflection()->SetInt64( &msgDest, pFieldDest, msgSource.GetReflection()->GetInt64( msgSource, pFieldSource ) );
  204. }
  205. break;
  206. case ::google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
  207. {
  208. msgDest.GetReflection()->SetUInt32( &msgDest, pFieldDest, msgSource.GetReflection()->GetUInt32( msgSource, pFieldSource ) );
  209. }
  210. break;
  211. case ::google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
  212. {
  213. msgDest.GetReflection()->SetUInt64( &msgDest, pFieldDest, msgSource.GetReflection()->GetUInt64( msgSource, pFieldSource ) );
  214. }
  215. break;
  216. case ::google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
  217. {
  218. msgDest.GetReflection()->SetDouble( &msgDest, pFieldDest, msgSource.GetReflection()->GetDouble( msgSource, pFieldSource ) );
  219. }
  220. break;
  221. case ::google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
  222. {
  223. msgDest.GetReflection()->SetFloat( &msgDest, pFieldDest, msgSource.GetReflection()->GetFloat( msgSource, pFieldSource ) );
  224. }
  225. break;
  226. case ::google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
  227. {
  228. msgDest.GetReflection()->SetBool( &msgDest, pFieldDest, msgSource.GetReflection()->GetBool( msgSource, pFieldSource ) );
  229. }
  230. break;
  231. case ::google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
  232. {
  233. msgDest.GetReflection()->SetEnum( &msgDest, pFieldDest, msgSource.GetReflection()->GetEnum( msgSource, pFieldSource ) );
  234. }
  235. break;
  236. case ::google::protobuf::FieldDescriptor::CPPTYPE_STRING:
  237. {
  238. msgDest.GetReflection()->SetString( &msgDest, pFieldDest, msgSource.GetReflection()->GetString( msgSource, pFieldSource ) );
  239. }
  240. break;
  241. case ::google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
  242. {
  243. msgDest.GetReflection()->MutableMessage( &msgDest, pFieldDest )->CopyFrom( msgSource.GetReflection()->GetMessage( msgSource, pFieldSource ) );
  244. }
  245. break;
  246. }
  247. }
  248. }
  249. //----------------------------------------------------------------------------
  250. // Purpose: compares fields in two protobuf objects
  251. //----------------------------------------------------------------------------
  252. bool IsProtoBufFieldLess( const ::google::protobuf::Message & msgLHS, const ::google::protobuf::Message & msgRHS, const ::google::protobuf::FieldDescriptor *pFieldLHS, const ::google::protobuf::FieldDescriptor *pFieldRHS )
  253. {
  254. Assert( pFieldLHS->cpp_type() == pFieldRHS->cpp_type() );
  255. if( pFieldLHS->cpp_type() != pFieldRHS->cpp_type() )
  256. return false;
  257. switch( pFieldLHS->cpp_type() )
  258. {
  259. case ::google::protobuf::FieldDescriptor::CPPTYPE_INT32:
  260. {
  261. return msgLHS.GetReflection()->GetInt32( msgLHS, pFieldLHS ) < msgRHS.GetReflection()->GetInt32( msgRHS, pFieldRHS );
  262. }
  263. break;
  264. case ::google::protobuf::FieldDescriptor::CPPTYPE_INT64:
  265. {
  266. return msgLHS.GetReflection()->GetInt64( msgLHS, pFieldLHS ) < msgRHS.GetReflection()->GetInt64( msgRHS, pFieldRHS );
  267. }
  268. break;
  269. case ::google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
  270. {
  271. return msgLHS.GetReflection()->GetUInt32( msgLHS, pFieldLHS ) < msgRHS.GetReflection()->GetUInt32( msgRHS, pFieldRHS );
  272. }
  273. break;
  274. case ::google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
  275. {
  276. return msgLHS.GetReflection()->GetUInt64( msgLHS, pFieldLHS ) < msgRHS.GetReflection()->GetUInt64( msgRHS, pFieldRHS );
  277. }
  278. break;
  279. case ::google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
  280. {
  281. return msgLHS.GetReflection()->GetDouble( msgLHS, pFieldLHS ) < msgRHS.GetReflection()->GetDouble( msgRHS, pFieldRHS );
  282. }
  283. break;
  284. case ::google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
  285. {
  286. return msgLHS.GetReflection()->GetFloat( msgLHS, pFieldLHS ) < msgRHS.GetReflection()->GetFloat( msgRHS, pFieldRHS );
  287. }
  288. break;
  289. case ::google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
  290. {
  291. return msgLHS.GetReflection()->GetBool( msgLHS, pFieldLHS ) < msgRHS.GetReflection()->GetBool( msgRHS, pFieldRHS );
  292. }
  293. break;
  294. case ::google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
  295. {
  296. return msgLHS.GetReflection()->GetEnum( msgLHS, pFieldLHS )->number() < msgRHS.GetReflection()->GetEnum( msgRHS, pFieldRHS )->number();
  297. }
  298. break;
  299. case ::google::protobuf::FieldDescriptor::CPPTYPE_STRING:
  300. {
  301. return Q_stricmp( msgLHS.GetReflection()->GetString( msgLHS, pFieldLHS ).c_str(), msgRHS.GetReflection()->GetString( msgRHS, pFieldRHS ).c_str() ) > 0;
  302. }
  303. break;
  304. case ::google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
  305. {
  306. return false;
  307. }
  308. break;
  309. }
  310. // unknown field types return false
  311. return false;
  312. }
  313. //----------------------------------------------------------------------------
  314. // Purpose: Returns true if the key fields in LHS are less than the key fields
  315. // in RHS
  316. //----------------------------------------------------------------------------
  317. bool CProtoBufSharedObjectBase::BIsKeyLess( const CSharedObject & soRHS ) const
  318. {
  319. const ::google::protobuf::Message & msgLHS = *GetPObject();
  320. const ::google::protobuf::Message & msgRHS = *((const CProtoBufSharedObjectBase &)soRHS).GetPObject();
  321. const ::google::protobuf::Descriptor *pDescriptor = msgLHS.GetDescriptor();
  322. for( int nField = 0; nField < pDescriptor->field_count(); nField++ )
  323. {
  324. const ::google::protobuf::FieldDescriptor *pFieldDescriptor = pDescriptor->field( nField );
  325. if( !IsKeyField( pFieldDescriptor ) )
  326. continue;
  327. if( IsProtoBufFieldLess( msgLHS, msgRHS, pFieldDescriptor, pFieldDescriptor ) )
  328. return true;
  329. // if the fields are less when reversed it means we know the keys aren't equal and don't
  330. // need to keep looping
  331. if( IsProtoBufFieldLess( msgRHS, msgLHS, pFieldDescriptor, pFieldDescriptor ) )
  332. return false;
  333. }
  334. return false;
  335. }
  336. void CProtoBufSharedObjectBase::RecursiveAddProtoBufToKV( KeyValues *pKVDest, const ::google::protobuf::Message & msg )
  337. {
  338. using ::google::protobuf::FieldDescriptor;
  339. const ::google::protobuf::Descriptor *pDescriptor = msg.GetDescriptor();
  340. const ::google::protobuf::Reflection *pReflection = msg.GetReflection();
  341. for ( int iField = 0; iField < pDescriptor->field_count(); iField++ )
  342. {
  343. const ::google::protobuf::FieldDescriptor *pField = pDescriptor->field( iField );
  344. const char *pFieldName = pField->name().c_str();
  345. if ( pField->is_repeated() )
  346. {
  347. KeyValues *pKVContainer = pKVDest->FindKey( pFieldName, true );
  348. for ( int iRepeated = 0; iRepeated < pReflection->FieldSize( msg, pField ); iRepeated++ )
  349. {
  350. KeyValues *pKVNode = pKVContainer->CreateNewKey();
  351. switch ( pField->cpp_type() )
  352. {
  353. case FieldDescriptor::CPPTYPE_INT32: pKVNode->SetInt( NULL, pReflection->GetRepeatedInt32( msg, pField, iRepeated ) ); break;
  354. case FieldDescriptor::CPPTYPE_INT64: pKVNode->SetUint64( NULL, (uint64)pReflection->GetRepeatedInt64( msg, pField, iRepeated ) ); break;
  355. case FieldDescriptor::CPPTYPE_UINT32: pKVNode->SetInt( NULL, (int32)pReflection->GetRepeatedUInt32( msg, pField, iRepeated ) ); break;
  356. case FieldDescriptor::CPPTYPE_UINT64: pKVNode->SetUint64( NULL, pReflection->GetRepeatedUInt64( msg, pField, iRepeated ) ); break;
  357. case FieldDescriptor::CPPTYPE_DOUBLE: pKVNode->SetFloat( NULL, (float)pReflection->GetRepeatedDouble( msg, pField, iRepeated ) ); break;
  358. case FieldDescriptor::CPPTYPE_FLOAT: pKVNode->SetFloat( NULL, pReflection->GetRepeatedFloat( msg, pField, iRepeated ) ); break;
  359. case FieldDescriptor::CPPTYPE_BOOL: pKVNode->SetBool( NULL, pReflection->GetRepeatedBool( msg, pField, iRepeated ) ); break;
  360. case FieldDescriptor::CPPTYPE_ENUM: pKVNode->SetInt( NULL, pReflection->GetRepeatedEnum( msg, pField, iRepeated )->number() ); break;
  361. case FieldDescriptor::CPPTYPE_STRING: pKVNode->SetString( NULL, pReflection->GetRepeatedString( msg, pField, iRepeated ).c_str() ); break;
  362. case FieldDescriptor::CPPTYPE_MESSAGE:
  363. {
  364. const ::google::protobuf::Message &subMsg = pReflection->GetRepeatedMessage( msg, pField, iRepeated );
  365. RecursiveAddProtoBufToKV( pKVNode, subMsg );
  366. break;
  367. }
  368. default:
  369. AssertMsg1( false, "Unknown cpp_type %d", pField->cpp_type() );
  370. break;
  371. }
  372. }
  373. }
  374. else
  375. {
  376. switch ( pField->cpp_type() )
  377. {
  378. case FieldDescriptor::CPPTYPE_INT32: pKVDest->SetInt( pFieldName, pReflection->GetInt32( msg, pField ) ); break;
  379. case FieldDescriptor::CPPTYPE_INT64: pKVDest->SetUint64( pFieldName, (uint64)pReflection->GetInt64( msg, pField ) ); break;
  380. case FieldDescriptor::CPPTYPE_UINT32: pKVDest->SetInt( pFieldName, (int32)pReflection->GetUInt32( msg, pField ) ); break;
  381. case FieldDescriptor::CPPTYPE_UINT64: pKVDest->SetUint64( pFieldName, pReflection->GetUInt64( msg, pField ) ); break;
  382. case FieldDescriptor::CPPTYPE_DOUBLE: pKVDest->SetFloat( pFieldName, (float)pReflection->GetDouble( msg, pField ) ); break;
  383. case FieldDescriptor::CPPTYPE_FLOAT: pKVDest->SetFloat( pFieldName, pReflection->GetFloat( msg, pField ) ); break;
  384. case FieldDescriptor::CPPTYPE_BOOL: pKVDest->SetBool( pFieldName, pReflection->GetBool( msg, pField ) ); break;
  385. case FieldDescriptor::CPPTYPE_ENUM: pKVDest->SetInt( pFieldName, pReflection->GetEnum( msg, pField )->number() );break;
  386. case FieldDescriptor::CPPTYPE_STRING: pKVDest->SetString( pFieldName, pReflection->GetString( msg, pField ).c_str() );break;
  387. case FieldDescriptor::CPPTYPE_MESSAGE:
  388. {
  389. KeyValues *pKVSub = pKVDest->FindKey( pFieldName, true );
  390. const ::google::protobuf::Message &subMsg = pReflection->GetMessage( msg, pField );
  391. RecursiveAddProtoBufToKV( pKVSub, subMsg );
  392. break;
  393. }
  394. default:
  395. AssertMsg1( false, "Unknown cpp_type %d", pField->cpp_type() );
  396. break;
  397. }
  398. }
  399. }
  400. }
  401. KeyValues *CProtoBufSharedObjectBase::CreateKVFromProtoBuf( const ::google::protobuf::Message & msg )
  402. {
  403. KeyValues *pKVDest = new KeyValues( msg.GetDescriptor()->name().c_str() );
  404. RecursiveAddProtoBufToKV( pKVDest, msg );
  405. return pKVDest;
  406. }
  407. //----------------------------------------------------------------------------
  408. // Purpose: Dumps a debug string for the object
  409. //----------------------------------------------------------------------------
  410. void CProtoBufSharedObjectBase::Dump( const ::google::protobuf::Message & msg )
  411. {
  412. // print line by line to get round our limited emitinfo buffer
  413. CUtlStringList lines;
  414. V_SplitString( msg.DebugString().c_str(), "\n", lines );
  415. for ( int i = 0; i < lines.Count(); i++ )
  416. {
  417. EmitInfo( SPEW_SHAREDOBJ, SPEW_ALWAYS, LOG_ALWAYS, "%s\n", lines[i] );
  418. }
  419. }
  420. //----------------------------------------------------------------------------
  421. // Purpose: Dumps a debug string for the object
  422. //----------------------------------------------------------------------------
  423. void CProtoBufSharedObjectBase::Dump() const
  424. {
  425. Dump( *GetPObject() );
  426. }
  427. //=============================================================================
  428. //----------------------------------------------------------------------------
  429. // Purpose: Parses the message bits for creating this object from the message.
  430. // This will be called on the client/gameserver when it first learns
  431. // about the item.
  432. //----------------------------------------------------------------------------
  433. bool CProtoBufSharedObjectBase::BParseFromMessage( const CUtlBuffer & buffer )
  434. {
  435. ::google::protobuf::Message & msg = *GetPObject();
  436. return msg.ParseFromArray( buffer.Base(), buffer.TellMaxPut() );
  437. }
  438. //----------------------------------------------------------------------------
  439. // Purpose: Parses the message bits for creating this object from the message.
  440. // This will be called on the client/gameserver when it first learns
  441. // about the item.
  442. //----------------------------------------------------------------------------
  443. bool CProtoBufSharedObjectBase::BParseFromMessage( const std::string &buffer )
  444. {
  445. ::google::protobuf::Message & msg = *GetPObject();
  446. return msg.ParseFromString( buffer );
  447. }
  448. //----------------------------------------------------------------------------
  449. // Purpose: Overrides all the fields in msgLocal that are present in the
  450. // network message
  451. //----------------------------------------------------------------------------
  452. bool CProtoBufSharedObjectBase::BUpdateFromNetwork( const CSharedObject & objUpdate )
  453. {
  454. ::google::protobuf::Message & msg = *GetPObject();
  455. const CProtoBufSharedObjectBase & pbobjUpdate = (const CProtoBufSharedObjectBase &)objUpdate;
  456. // merge the update onto the local message
  457. msg.CopyFrom( *pbobjUpdate.GetPObject() );
  458. return true;
  459. }
  460. #ifdef GC
  461. //----------------------------------------------------------------------------
  462. // Purpose: Static help class that seralizes to a buffer
  463. //----------------------------------------------------------------------------
  464. bool CProtoBufSharedObjectBase::SerializeToBuffer( const ::google::protobuf::Message & msg, CUtlBuffer & bufOutput )
  465. {
  466. uint32 unSize = msg.ByteSize();
  467. bufOutput.Clear();
  468. bufOutput.EnsureCapacity( unSize );
  469. msg.SerializeWithCachedSizesToArray( (uint8*)bufOutput.Base() );
  470. bufOutput.SeekPut( CUtlBuffer::SEEK_HEAD, unSize );
  471. return true;
  472. }
  473. //----------------------------------------------------------------------------
  474. // Purpose: Adds the relevant message bits to create this object to the
  475. // message. This will be called whenever a subscriber is added.
  476. //----------------------------------------------------------------------------
  477. bool CProtoBufSharedObjectBase::BAddToMessage( CUtlBuffer & bufOutput ) const
  478. {
  479. const ::google::protobuf::Message & msg = *GetPObject();
  480. SerializeToBuffer( msg, bufOutput );
  481. return true;
  482. }
  483. //----------------------------------------------------------------------------
  484. // Purpose: Adds the relevant message bits to create this object to the
  485. // message. This will be called whenever a subscriber is added.
  486. //----------------------------------------------------------------------------
  487. bool CProtoBufSharedObjectBase::BAddToMessage( std::string *pBuffer ) const
  488. {
  489. const ::google::protobuf::Message & msg = *GetPObject();
  490. return msg.SerializeToString( pBuffer );
  491. }
  492. //----------------------------------------------------------------------------
  493. // Purpose: Parses the message bits for creating this object from the message.
  494. // This will be called on the client/gameserver when it first learns
  495. // about the item.
  496. //----------------------------------------------------------------------------
  497. bool CProtoBufSharedObjectBase::BParseFromMemcached( CUtlBuffer & buffer )
  498. {
  499. ::google::protobuf::Message & msg = *GetPObject();
  500. return msg.ParseFromArray( buffer.Base(), buffer.TellMaxPut() );
  501. }
  502. //----------------------------------------------------------------------------
  503. // Purpose: Adds the relevant message bits to create this object to the
  504. // message. This will be called whenever a subscriber is added.
  505. //----------------------------------------------------------------------------
  506. bool CProtoBufSharedObjectBase::BAddToMemcached( CUtlBuffer & bufOutput ) const
  507. {
  508. const ::google::protobuf::Message & msg = *GetPObject();
  509. SerializeToBuffer( msg, bufOutput );
  510. return true;
  511. }
  512. /*
  513. //----------------------------------------------------------------------------
  514. // Purpose: Adds all the information required for this object on the client
  515. //----------------------------------------------------------------------------
  516. bool CProtoBufSharedObjectBase::BAppendToMessage( CUtlBuffer & bufOutput ) const
  517. {
  518. const ::google::protobuf::Message & msg = *GetPObject();
  519. uint32 unSize = msg.ByteSize();
  520. bufOutput.EnsureCapacity( bufOutput.Size() + unSize );
  521. msg.SerializeWithCachedSizesToArray( (uint8*)bufOutput.Base() + bufOutput.TellPut() );
  522. bufOutput.SeekPut( CUtlBuffer::SEEK_HEAD, bufOutput.TellPut() + unSize );
  523. return true;
  524. }
  525. //----------------------------------------------------------------------------
  526. // Purpose: Adds all the information required for this object on the client
  527. //----------------------------------------------------------------------------
  528. bool CProtoBufSharedObjectBase::BAppendToMessage( std::string *pBuffer ) const
  529. {
  530. const ::google::protobuf::Message & msg = *GetPObject();
  531. msg.AppendToString( pBuffer );
  532. return true;
  533. }
  534. */
  535. //----------------------------------------------------------------------------
  536. ::google::protobuf::Message *CProtoBufSharedObjectBase::BuildDestroyToMessage( const ::google::protobuf::Message & msg )
  537. {
  538. const ::google::protobuf::Descriptor *pDescriptor = msg.GetDescriptor();
  539. ::google::protobuf::Message *pMessageToSend = msg.New();
  540. for( int nField = 0; nField < pDescriptor->field_count(); nField++ )
  541. {
  542. const ::google::protobuf::FieldDescriptor *pFieldDescriptor = pDescriptor->field( nField );
  543. if( !IsKeyField( pFieldDescriptor ) )
  544. continue;
  545. CopyProtoBufField( *pMessageToSend, msg, pFieldDescriptor, pFieldDescriptor );
  546. }
  547. return pMessageToSend;
  548. }
  549. //----------------------------------------------------------------------------
  550. // Purpose: Adds just the key fields to the message
  551. //----------------------------------------------------------------------------
  552. bool CProtoBufSharedObjectBase::BAddDestroyToMessage( CUtlBuffer & bufDestroy ) const
  553. {
  554. const ::google::protobuf::Message & msg = *GetPObject();
  555. ::google::protobuf::Message *pMessageToSend = BuildDestroyToMessage( msg );
  556. SerializeToBuffer( *pMessageToSend, bufDestroy );
  557. delete pMessageToSend;
  558. return true;
  559. }
  560. //----------------------------------------------------------------------------
  561. // Purpose: Adds just the key fields to the message
  562. //----------------------------------------------------------------------------
  563. bool CProtoBufSharedObjectBase::BAddDestroyToMessage( std::string *pBuffer ) const
  564. {
  565. const ::google::protobuf::Message & msg = *GetPObject();
  566. ::google::protobuf::Message *pMessageToSend = BuildDestroyToMessage( msg );
  567. pMessageToSend->SerializeToString( pBuffer );
  568. delete pMessageToSend;
  569. return true;
  570. }
  571. #endif //GC
  572. //----------------------------------------------------------------------------
  573. // Purpose: Copy the data from the specified schema shared object into this.
  574. // Both objects must be of the same type.
  575. //----------------------------------------------------------------------------
  576. void CProtoBufSharedObjectBase::Copy( const CSharedObject & soRHS )
  577. {
  578. Assert( GetTypeID() == soRHS.GetTypeID() );
  579. const CProtoBufSharedObjectBase & soRHSBase = (CProtoBufSharedObjectBase &)soRHS;
  580. GetPObject()->CopyFrom( *soRHSBase.GetPObject() );
  581. }
  582. //----------------------------------------------------------------------------
  583. // Purpose: Claims all memory for the object.
  584. //----------------------------------------------------------------------------
  585. #ifdef DBGFLAG_VALIDATE
  586. void CProtoBufSharedObjectBase::Validate( CValidator &validator, const char *pchName )
  587. {
  588. CSharedObject::Validate( validator, pchName );
  589. // these are INSIDE the function instead of outside so the interface
  590. // doesn't change
  591. VALIDATE_SCOPE();
  592. }
  593. #endif
  594. } // namespace GCSDK