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.

584 lines
16 KiB

  1. //========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #ifndef DATATABLE_RECV_H
  9. #define DATATABLE_RECV_H
  10. #ifdef _WIN32
  11. #pragma once
  12. #endif
  13. #include "dt_common.h"
  14. #include "tier0/dbg.h"
  15. #define ADDRESSPROXY_NONE -1
  16. class RecvTable;
  17. class RecvProp;
  18. // This is passed into RecvProxy functions.
  19. class CRecvProxyData
  20. {
  21. public:
  22. const RecvProp *m_pRecvProp; // The property it's receiving.
  23. DVariant m_Value; // The value given to you to store.
  24. int m_iElement; // Which array element you're getting.
  25. int m_ObjectID; // The object being referred to.
  26. };
  27. //-----------------------------------------------------------------------------
  28. // pStruct = the base structure of the datatable this variable is in (like C_BaseEntity)
  29. // pOut = the variable that this this proxy represents (like C_BaseEntity::m_SomeValue).
  30. //
  31. // Convert the network-standard-type value in m_Value into your own format in pStruct/pOut.
  32. //-----------------------------------------------------------------------------
  33. typedef void (*RecvVarProxyFn)( const CRecvProxyData *pData, void *pStruct, void *pOut );
  34. // ------------------------------------------------------------------------ //
  35. // ArrayLengthRecvProxies are optionally used to get the length of the
  36. // incoming array when it changes.
  37. // ------------------------------------------------------------------------ //
  38. typedef void (*ArrayLengthRecvProxyFn)( void *pStruct, int objectID, int currentArrayLength );
  39. // NOTE: DataTable receive proxies work differently than the other proxies.
  40. // pData points at the object + the recv table's offset.
  41. // pOut should be set to the location of the object to unpack the data table into.
  42. // If the parent object just contains the child object, the default proxy just does *pOut = pData.
  43. // If the parent object points at the child object, you need to dereference the pointer here.
  44. // NOTE: don't ever return null from a DataTable receive proxy function. Bad things will happen.
  45. typedef void (*DataTableRecvVarProxyFn)(const RecvProp *pProp, void **pOut, void *pData, int objectID);
  46. // This is used to fork over the standard proxy functions to the engine so it can
  47. // make some optimizations.
  48. class CStandardRecvProxies
  49. {
  50. public:
  51. CStandardRecvProxies();
  52. RecvVarProxyFn m_Int32ToInt8;
  53. RecvVarProxyFn m_Int32ToInt16;
  54. RecvVarProxyFn m_Int32ToInt32;
  55. RecvVarProxyFn m_Int64ToInt64;
  56. RecvVarProxyFn m_FloatToFloat;
  57. RecvVarProxyFn m_VectorToVector;
  58. };
  59. extern CStandardRecvProxies g_StandardRecvProxies;
  60. class CRecvDecoder;
  61. class RecvProp
  62. {
  63. // This info comes from the receive data table.
  64. public:
  65. RecvProp();
  66. void InitArray( int nElements, int elementStride );
  67. int GetNumElements() const;
  68. void SetNumElements( int nElements );
  69. int GetElementStride() const;
  70. void SetElementStride( int stride );
  71. int GetFlags() const;
  72. const char* GetName() const;
  73. SendPropType GetType() const;
  74. RecvTable* GetDataTable() const;
  75. void SetDataTable( RecvTable *pTable );
  76. RecvVarProxyFn GetProxyFn() const;
  77. void SetProxyFn( RecvVarProxyFn fn );
  78. DataTableRecvVarProxyFn GetDataTableProxyFn() const;
  79. void SetDataTableProxyFn( DataTableRecvVarProxyFn fn );
  80. int GetOffset() const;
  81. void SetOffset( int o );
  82. // Arrays only.
  83. RecvProp* GetArrayProp() const;
  84. void SetArrayProp( RecvProp *pProp );
  85. // Arrays only.
  86. void SetArrayLengthProxy( ArrayLengthRecvProxyFn proxy );
  87. ArrayLengthRecvProxyFn GetArrayLengthProxy() const;
  88. bool IsInsideArray() const;
  89. void SetInsideArray();
  90. // Some property types bind more data to the prop in here.
  91. const void* GetExtraData() const;
  92. void SetExtraData( const void *pData );
  93. // If it's one of the numbered "000", "001", etc properties in an array, then
  94. // these can be used to get its array property name for debugging.
  95. const char* GetParentArrayPropName();
  96. void SetParentArrayPropName( const char *pArrayPropName );
  97. public:
  98. char *m_pVarName;
  99. SendPropType m_RecvType;
  100. int m_Flags;
  101. int m_StringBufferSize;
  102. private:
  103. bool m_bInsideArray; // Set to true by the engine if this property sits inside an array.
  104. // Extra data that certain special property types bind to the property here.
  105. const void *m_pExtraData;
  106. // If this is an array (DPT_Array).
  107. RecvProp *m_pArrayProp;
  108. ArrayLengthRecvProxyFn m_ArrayLengthProxy;
  109. RecvVarProxyFn m_ProxyFn;
  110. DataTableRecvVarProxyFn m_DataTableProxyFn; // For RDT_DataTable.
  111. RecvTable *m_pDataTable; // For RDT_DataTable.
  112. int m_Offset;
  113. int m_ElementStride;
  114. int m_nElements;
  115. // If it's one of the numbered "000", "001", etc properties in an array, then
  116. // these can be used to get its array property name for debugging.
  117. const char *m_pParentArrayPropName;
  118. };
  119. class RecvTable
  120. {
  121. public:
  122. typedef RecvProp PropType;
  123. RecvTable();
  124. RecvTable( RecvProp *pProps, int nProps, char *pNetTableName );
  125. ~RecvTable();
  126. void Construct( RecvProp *pProps, int nProps, char *pNetTableName );
  127. int GetNumProps();
  128. RecvProp* GetProp( int i );
  129. const char* GetName() const;
  130. // Used by the engine while initializing array props.
  131. void SetInitialized( bool bInitialized );
  132. bool IsInitialized() const;
  133. // Used by the engine.
  134. void SetInMainList( bool bInList );
  135. bool IsInMainList() const;
  136. public:
  137. // Properties described in a table.
  138. RecvProp *m_pProps;
  139. int m_nProps;
  140. // The decoder. NOTE: this covers each RecvTable AND all its children (ie: its children
  141. // will have their own decoders that include props for all their children).
  142. CRecvDecoder *m_pDecoder;
  143. char *m_pNetTableName; // The name matched between client and server.
  144. private:
  145. bool m_bInitialized;
  146. bool m_bInMainList;
  147. };
  148. inline int RecvTable::GetNumProps()
  149. {
  150. return m_nProps;
  151. }
  152. inline RecvProp* RecvTable::GetProp( int i )
  153. {
  154. Assert( i >= 0 && i < m_nProps );
  155. return &m_pProps[i];
  156. }
  157. inline const char* RecvTable::GetName() const
  158. {
  159. return m_pNetTableName;
  160. }
  161. inline void RecvTable::SetInitialized( bool bInitialized )
  162. {
  163. m_bInitialized = bInitialized;
  164. }
  165. inline bool RecvTable::IsInitialized() const
  166. {
  167. return m_bInitialized;
  168. }
  169. inline void RecvTable::SetInMainList( bool bInList )
  170. {
  171. m_bInMainList = bInList;
  172. }
  173. inline bool RecvTable::IsInMainList() const
  174. {
  175. return m_bInMainList;
  176. }
  177. // ------------------------------------------------------------------------------------------------------ //
  178. // See notes on BEGIN_SEND_TABLE for a description. These macros work similarly.
  179. // ------------------------------------------------------------------------------------------------------ //
  180. #define BEGIN_RECV_TABLE(className, tableName) \
  181. BEGIN_RECV_TABLE_NOBASE(className, tableName) \
  182. RecvPropDataTable("baseclass", 0, 0, className::BaseClass::m_pClassRecvTable, DataTableRecvProxy_StaticDataTable),
  183. #define BEGIN_RECV_TABLE_NOBASE(className, tableName) \
  184. template <typename T> int ClientClassInit(T *); \
  185. namespace tableName { \
  186. struct ignored; \
  187. } \
  188. template <> int ClientClassInit<tableName::ignored>(tableName::ignored *); \
  189. namespace tableName { \
  190. RecvTable g_RecvTable; \
  191. int g_RecvTableInit = ClientClassInit((tableName::ignored *)NULL); \
  192. } \
  193. template <> int ClientClassInit<tableName::ignored>(tableName::ignored *) \
  194. { \
  195. typedef className currentRecvDTClass; \
  196. char *pRecvTableName = #tableName; \
  197. RecvTable &RecvTable = tableName::g_RecvTable; \
  198. static RecvProp RecvProps[] = { \
  199. RecvPropInt("should_never_see_this", 0, sizeof(int)), // It adds a dummy property at the start so you can define "empty" SendTables.
  200. #define END_RECV_TABLE() \
  201. }; \
  202. RecvTable.Construct(RecvProps+1, sizeof(RecvProps) / sizeof(RecvProp) - 1, pRecvTableName); \
  203. return 1; \
  204. }
  205. #define RECVINFO(varName) #varName, offsetof(currentRecvDTClass, varName), sizeof(((currentRecvDTClass*)0)->varName)
  206. #define RECVINFO_NAME(varName, remoteVarName) #remoteVarName, offsetof(currentRecvDTClass, varName), sizeof(((currentRecvDTClass*)0)->varName)
  207. #define RECVINFO_STRING(varName) #varName, offsetof(currentRecvDTClass, varName), STRINGBUFSIZE(currentRecvDTClass, varName)
  208. #define RECVINFO_BASECLASS(tableName) RecvPropDataTable("this", 0, 0, &REFERENCE_RECV_TABLE(tableName))
  209. #define RECVINFO_ARRAY(varName) #varName, offsetof(currentRecvDTClass, varName), sizeof(((currentRecvDTClass*)0)->varName[0]), sizeof(((currentRecvDTClass*)0)->varName)/sizeof(((currentRecvDTClass*)0)->varName[0])
  210. // Just specify the name and offset. Used for strings and data tables.
  211. #define RECVINFO_NOSIZE(varName) #varName, offsetof(currentRecvDTClass, varName)
  212. #define RECVINFO_DT(varName) RECVINFO_NOSIZE(varName)
  213. #define RECVINFO_DTNAME(varName,remoteVarName) #remoteVarName, offsetof(currentRecvDTClass, varName)
  214. void RecvProxy_FloatToFloat ( const CRecvProxyData *pData, void *pStruct, void *pOut );
  215. void RecvProxy_VectorToVector( const CRecvProxyData *pData, void *pStruct, void *pOut );
  216. void RecvProxy_VectorXYToVectorXY( const CRecvProxyData *pData, void *pStruct, void *pOut );
  217. void RecvProxy_QuaternionToQuaternion( const CRecvProxyData *pData, void *pStruct, void *pOut );
  218. void RecvProxy_Int32ToInt8 ( const CRecvProxyData *pData, void *pStruct, void *pOut );
  219. void RecvProxy_Int32ToInt16 ( const CRecvProxyData *pData, void *pStruct, void *pOut );
  220. void RecvProxy_StringToString( const CRecvProxyData *pData, void *pStruct, void *pOut );
  221. void RecvProxy_Int32ToInt32 ( const CRecvProxyData *pData, void *pStruct, void *pOut );
  222. void RecvProxy_Int64ToInt64 ( const CRecvProxyData *pData, void *pStruct, void *pOut );
  223. void RecvProxy_Int32ToColor32( const CRecvProxyData *pData, void *pStruct, void *pOut );
  224. // StaticDataTable does *pOut = pData.
  225. void DataTableRecvProxy_StaticDataTable(const RecvProp *pProp, void **pOut, void *pData, int objectID);
  226. // PointerDataTable does *pOut = *((void**)pData) (ie: pData is a pointer to the object to decode into).
  227. void DataTableRecvProxy_PointerDataTable(const RecvProp *pProp, void **pOut, void *pData, int objectID);
  228. RecvProp RecvPropFloat(
  229. char *pVarName,
  230. int offset,
  231. int sizeofVar=SIZEOF_IGNORE, // Handled by RECVINFO macro, but set to SIZEOF_IGNORE if you don't want to bother.
  232. int flags=0,
  233. RecvVarProxyFn varProxy=RecvProxy_FloatToFloat
  234. );
  235. RecvProp RecvPropVector(
  236. char *pVarName,
  237. int offset,
  238. int sizeofVar=SIZEOF_IGNORE, // Handled by RECVINFO macro, but set to SIZEOF_IGNORE if you don't want to bother.
  239. int flags=0,
  240. RecvVarProxyFn varProxy=RecvProxy_VectorToVector
  241. );
  242. RecvProp RecvPropVectorXY(
  243. char *pVarName,
  244. int offset,
  245. int sizeofVar=SIZEOF_IGNORE, // Handled by RECVINFO macro, but set to SIZEOF_IGNORE if you don't want to bother.
  246. int flags=0,
  247. RecvVarProxyFn varProxy=RecvProxy_VectorXYToVectorXY
  248. );
  249. // This is here so the RecvTable can look more like the SendTable.
  250. #define RecvPropQAngles RecvPropVector
  251. #if 0 // We can't ship this since it changes the size of DTVariant to be 20 bytes instead of 16 and that breaks MODs!!!
  252. RecvProp RecvPropQuaternion(
  253. char *pVarName,
  254. int offset,
  255. int sizeofVar=SIZEOF_IGNORE, // Handled by RECVINFO macro, but set to SIZEOF_IGNORE if you don't want to bother.
  256. int flags=0,
  257. RecvVarProxyFn varProxy=RecvProxy_QuaternionToQuaternion
  258. );
  259. #endif
  260. RecvProp RecvPropInt(
  261. char *pVarName,
  262. int offset,
  263. int sizeofVar=SIZEOF_IGNORE, // Handled by RECVINFO macro, but set to SIZEOF_IGNORE if you don't want to bother.
  264. int flags=0,
  265. RecvVarProxyFn varProxy=0
  266. );
  267. RecvProp RecvPropString(
  268. char *pVarName,
  269. int offset,
  270. int bufferSize,
  271. int flags=0,
  272. RecvVarProxyFn varProxy=RecvProxy_StringToString
  273. );
  274. RecvProp RecvPropDataTable(
  275. char *pVarName,
  276. int offset,
  277. int flags,
  278. RecvTable *pTable,
  279. DataTableRecvVarProxyFn varProxy=DataTableRecvProxy_StaticDataTable
  280. );
  281. RecvProp RecvPropArray3(
  282. char *pVarName,
  283. int offset,
  284. int sizeofVar,
  285. int elements,
  286. RecvProp pArrayProp,
  287. DataTableRecvVarProxyFn varProxy=DataTableRecvProxy_StaticDataTable
  288. );
  289. // Use the macro to let it automatically generate a table name. You shouldn't
  290. // ever need to reference the table name. If you want to exclude this array, then
  291. // reference the name of the variable in varTemplate.
  292. RecvProp InternalRecvPropArray(
  293. const int elementCount,
  294. const int elementStride,
  295. char *pName,
  296. ArrayLengthRecvProxyFn proxy
  297. );
  298. //
  299. // Use this to match a SendPropArray_AllAtOnce
  300. //
  301. #define RecvPropArray_AllAtOnce( arrayName, propDefinition ) \
  302. RecvPropArray( propDefinition, arrayName )
  303. //
  304. // Use this to match a SendPropArray_UniqueElements
  305. //
  306. #define RecvPropArray_UniqueElements( arrayName, propDefinition ) \
  307. RecvPropArray3( RECVINFO_ARRAY( m_nValues ), propDefinition )
  308. //
  309. // Use this if you want to completely manage the way the array data is stored.
  310. // You'll need to provide a proxy inside varTemplate that looks for 'iElement'
  311. // to figure out where to store the specified element.
  312. //
  313. #define RecvPropVirtualArray( arrayLengthProxy, maxArrayLength, varTemplate, propertyName ) \
  314. varTemplate, \
  315. InternalRecvPropArray( \
  316. maxArrayLength, \
  317. 0, \
  318. #propertyName, \
  319. arrayLengthProxy \
  320. )
  321. // Use this and pass the array name and it will figure out the count and stride automatically.
  322. #define RecvPropVariableLengthArray( arrayLengthProxy, varTemplate, arrayName ) \
  323. varTemplate, \
  324. InternalRecvPropArray( \
  325. sizeof(((currentRecvDTClass*)0)->arrayName) / PROPSIZEOF(currentRecvDTClass, arrayName[0]), \
  326. PROPSIZEOF(currentRecvDTClass, arrayName[0]), \
  327. #arrayName, \
  328. arrayLengthProxy \
  329. )
  330. // Use this and pass the array name and it will figure out the count and stride automatically.
  331. #define RecvPropArray( varTemplate, arrayName ) \
  332. RecvPropVariableLengthArray( 0, varTemplate, arrayName )
  333. // Use this one to specify the element count and stride manually.
  334. #define RecvPropArray2( arrayLengthProxy, varTemplate, elementCount, elementStride, arrayName ) \
  335. varTemplate, \
  336. InternalRecvPropArray( elementCount, elementStride, #arrayName, arrayLengthProxy )
  337. // ---------------------------------------------------------------------------------------- //
  338. // Inlines.
  339. // ---------------------------------------------------------------------------------------- //
  340. inline void RecvProp::InitArray( int nElements, int elementStride )
  341. {
  342. m_RecvType = DPT_Array;
  343. m_nElements = nElements;
  344. m_ElementStride = elementStride;
  345. }
  346. inline int RecvProp::GetNumElements() const
  347. {
  348. return m_nElements;
  349. }
  350. inline void RecvProp::SetNumElements( int nElements )
  351. {
  352. m_nElements = nElements;
  353. }
  354. inline int RecvProp::GetElementStride() const
  355. {
  356. return m_ElementStride;
  357. }
  358. inline void RecvProp::SetElementStride( int stride )
  359. {
  360. m_ElementStride = stride;
  361. }
  362. inline int RecvProp::GetFlags() const
  363. {
  364. return m_Flags;
  365. }
  366. inline const char* RecvProp::GetName() const
  367. {
  368. return m_pVarName;
  369. }
  370. inline SendPropType RecvProp::GetType() const
  371. {
  372. return m_RecvType;
  373. }
  374. inline RecvTable* RecvProp::GetDataTable() const
  375. {
  376. return m_pDataTable;
  377. }
  378. inline void RecvProp::SetDataTable( RecvTable *pTable )
  379. {
  380. m_pDataTable = pTable;
  381. }
  382. inline RecvVarProxyFn RecvProp::GetProxyFn() const
  383. {
  384. return m_ProxyFn;
  385. }
  386. inline void RecvProp::SetProxyFn( RecvVarProxyFn fn )
  387. {
  388. m_ProxyFn = fn;
  389. }
  390. inline DataTableRecvVarProxyFn RecvProp::GetDataTableProxyFn() const
  391. {
  392. return m_DataTableProxyFn;
  393. }
  394. inline void RecvProp::SetDataTableProxyFn( DataTableRecvVarProxyFn fn )
  395. {
  396. m_DataTableProxyFn = fn;
  397. }
  398. inline int RecvProp::GetOffset() const
  399. {
  400. return m_Offset;
  401. }
  402. inline void RecvProp::SetOffset( int o )
  403. {
  404. m_Offset = o;
  405. }
  406. inline RecvProp* RecvProp::GetArrayProp() const
  407. {
  408. return m_pArrayProp;
  409. }
  410. inline void RecvProp::SetArrayProp( RecvProp *pProp )
  411. {
  412. m_pArrayProp = pProp;
  413. }
  414. inline void RecvProp::SetArrayLengthProxy( ArrayLengthRecvProxyFn proxy )
  415. {
  416. m_ArrayLengthProxy = proxy;
  417. }
  418. inline ArrayLengthRecvProxyFn RecvProp::GetArrayLengthProxy() const
  419. {
  420. return m_ArrayLengthProxy;
  421. }
  422. inline bool RecvProp::IsInsideArray() const
  423. {
  424. return m_bInsideArray;
  425. }
  426. inline void RecvProp::SetInsideArray()
  427. {
  428. m_bInsideArray = true;
  429. }
  430. inline const void* RecvProp::GetExtraData() const
  431. {
  432. return m_pExtraData;
  433. }
  434. inline void RecvProp::SetExtraData( const void *pData )
  435. {
  436. m_pExtraData = pData;
  437. }
  438. inline const char* RecvProp::GetParentArrayPropName()
  439. {
  440. return m_pParentArrayPropName;
  441. }
  442. inline void RecvProp::SetParentArrayPropName( const char *pArrayPropName )
  443. {
  444. m_pParentArrayPropName = pArrayPropName;
  445. }
  446. #endif // DATATABLE_RECV_H