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.

575 lines
16 KiB

  1. //========= Copyright 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_FloatToFloat;
  56. RecvVarProxyFn m_VectorToVector;
  57. #ifdef SUPPORTS_INT64
  58. RecvVarProxyFn m_Int64ToInt64;
  59. #endif
  60. };
  61. extern CStandardRecvProxies g_StandardRecvProxies;
  62. class CRecvDecoder;
  63. class RecvProp
  64. {
  65. // This info comes from the receive data table.
  66. public:
  67. RecvProp();
  68. void InitArray( int nElements, int elementStride );
  69. int GetNumElements() const;
  70. void SetNumElements( int nElements );
  71. int GetElementStride() const;
  72. void SetElementStride( int stride );
  73. int GetFlags() const;
  74. const char* GetName() const;
  75. SendPropType GetType() const;
  76. RecvTable* GetDataTable() const;
  77. void SetDataTable( RecvTable *pTable );
  78. RecvVarProxyFn GetProxyFn() const;
  79. void SetProxyFn( RecvVarProxyFn fn );
  80. DataTableRecvVarProxyFn GetDataTableProxyFn() const;
  81. void SetDataTableProxyFn( DataTableRecvVarProxyFn fn );
  82. int GetOffset() const;
  83. void SetOffset( int o );
  84. // Arrays only.
  85. RecvProp* GetArrayProp() const;
  86. void SetArrayProp( RecvProp *pProp );
  87. // Arrays only.
  88. void SetArrayLengthProxy( ArrayLengthRecvProxyFn proxy );
  89. ArrayLengthRecvProxyFn GetArrayLengthProxy() const;
  90. bool IsInsideArray() const;
  91. void SetInsideArray();
  92. // Some property types bind more data to the prop in here.
  93. const void* GetExtraData() const;
  94. void SetExtraData( const void *pData );
  95. // If it's one of the numbered "000", "001", etc properties in an array, then
  96. // these can be used to get its array property name for debugging.
  97. const char* GetParentArrayPropName();
  98. void SetParentArrayPropName( const char *pArrayPropName );
  99. public:
  100. const char *m_pVarName;
  101. SendPropType m_RecvType;
  102. int m_Flags;
  103. int m_StringBufferSize;
  104. private:
  105. bool m_bInsideArray; // Set to true by the engine if this property sits inside an array.
  106. // Extra data that certain special property types bind to the property here.
  107. const void *m_pExtraData;
  108. // If this is an array (DPT_Array).
  109. RecvProp *m_pArrayProp;
  110. ArrayLengthRecvProxyFn m_ArrayLengthProxy;
  111. RecvVarProxyFn m_ProxyFn;
  112. DataTableRecvVarProxyFn m_DataTableProxyFn; // For RDT_DataTable.
  113. RecvTable *m_pDataTable; // For RDT_DataTable.
  114. int m_Offset;
  115. int m_ElementStride;
  116. int m_nElements;
  117. // If it's one of the numbered "000", "001", etc properties in an array, then
  118. // these can be used to get its array property name for debugging.
  119. const char *m_pParentArrayPropName;
  120. };
  121. class RecvTable
  122. {
  123. public:
  124. typedef RecvProp PropType;
  125. RecvTable();
  126. RecvTable( RecvProp *pProps, int nProps, const char *pNetTableName );
  127. ~RecvTable();
  128. void Construct( RecvProp *pProps, int nProps, const char *pNetTableName );
  129. int GetNumProps();
  130. RecvProp* GetProp( int i );
  131. const char* GetName();
  132. // Used by the engine while initializing array props.
  133. void SetInitialized( bool bInitialized );
  134. bool IsInitialized() const;
  135. // Used by the engine.
  136. void SetInMainList( bool bInList );
  137. bool IsInMainList() const;
  138. public:
  139. // Properties described in a table.
  140. RecvProp *m_pProps;
  141. int m_nProps;
  142. // The decoder. NOTE: this covers each RecvTable AND all its children (ie: its children
  143. // will have their own decoders that include props for all their children).
  144. CRecvDecoder *m_pDecoder;
  145. const char *m_pNetTableName; // The name matched between client and server.
  146. private:
  147. bool m_bInitialized;
  148. bool m_bInMainList;
  149. };
  150. inline int RecvTable::GetNumProps()
  151. {
  152. return m_nProps;
  153. }
  154. inline RecvProp* RecvTable::GetProp( int i )
  155. {
  156. Assert( i >= 0 && i < m_nProps );
  157. return &m_pProps[i];
  158. }
  159. inline const char* RecvTable::GetName()
  160. {
  161. return m_pNetTableName;
  162. }
  163. inline void RecvTable::SetInitialized( bool bInitialized )
  164. {
  165. m_bInitialized = bInitialized;
  166. }
  167. inline bool RecvTable::IsInitialized() const
  168. {
  169. return m_bInitialized;
  170. }
  171. inline void RecvTable::SetInMainList( bool bInList )
  172. {
  173. m_bInMainList = bInList;
  174. }
  175. inline bool RecvTable::IsInMainList() const
  176. {
  177. return m_bInMainList;
  178. }
  179. // ------------------------------------------------------------------------------------------------------ //
  180. // See notes on BEGIN_SEND_TABLE for a description. These macros work similarly.
  181. // ------------------------------------------------------------------------------------------------------ //
  182. #define BEGIN_RECV_TABLE(className, tableName) \
  183. BEGIN_RECV_TABLE_NOBASE(className, tableName) \
  184. RecvPropDataTable("baseclass", 0, 0, className::BaseClass::m_pClassRecvTable, DataTableRecvProxy_StaticDataTable),
  185. #define BEGIN_RECV_TABLE_NOBASE(className, tableName) \
  186. template <typename T> int ClientClassInit(T *); \
  187. namespace tableName { \
  188. struct ignored; \
  189. } \
  190. template <> int ClientClassInit<tableName::ignored>(tableName::ignored *); \
  191. namespace tableName { \
  192. RecvTable g_RecvTable; \
  193. int g_RecvTableInit = ClientClassInit((tableName::ignored *)NULL); \
  194. } \
  195. template <> int ClientClassInit<tableName::ignored>(tableName::ignored *) \
  196. { \
  197. typedef className currentRecvDTClass; \
  198. const char *pRecvTableName = #tableName; \
  199. RecvTable &RecvTable = tableName::g_RecvTable; \
  200. static RecvProp RecvProps[] = { \
  201. RecvPropInt("should_never_see_this", 0, sizeof(int)), // It adds a dummy property at the start so you can define "empty" SendTables.
  202. #define END_RECV_TABLE() \
  203. }; \
  204. RecvTable.Construct(RecvProps+1, sizeof(RecvProps) / sizeof(RecvProp) - 1, pRecvTableName); \
  205. return 1; \
  206. }
  207. // Normal offset of is invalid on non-array-types, this is dubious as hell. The rest of the codebase converted to the
  208. // legit offsetof from the C headers, so we'll use the old impl here to avoid exposing temptation to others
  209. #define _hacky_dtrecv_offsetof(s,m) ((size_t)&(((s *)0)->m))
  210. #define RECVINFO(varName) #varName, _hacky_dtrecv_offsetof(currentRecvDTClass, varName), sizeof(((currentRecvDTClass*)0)->varName)
  211. #define RECVINFO_NAME(varName, remoteVarName) #remoteVarName, _hacky_dtrecv_offsetof(currentRecvDTClass, varName), sizeof(((currentRecvDTClass*)0)->varName)
  212. #define RECVINFO_STRING(varName) #varName, _hacky_dtrecv_offsetof(currentRecvDTClass, varName), STRINGBUFSIZE(currentRecvDTClass, varName)
  213. #define RECVINFO_BASECLASS(tableName) RecvPropDataTable("this", 0, 0, &REFERENCE_RECV_TABLE(tableName))
  214. #define RECVINFO_ARRAY(varName) #varName, _hacky_dtrecv_offsetof(currentRecvDTClass, varName), sizeof(((currentRecvDTClass*)0)->varName[0]), sizeof(((currentRecvDTClass*)0)->varName)/sizeof(((currentRecvDTClass*)0)->varName[0])
  215. // Just specify the name and offset. Used for strings and data tables.
  216. #define RECVINFO_NOSIZE(varName) #varName, _hacky_dtrecv_offsetof(currentRecvDTClass, varName)
  217. #define RECVINFO_DT(varName) RECVINFO_NOSIZE(varName)
  218. #define RECVINFO_DTNAME(varName,remoteVarName) #remoteVarName, _hacky_dtrecv_offsetof(currentRecvDTClass, varName)
  219. void RecvProxy_FloatToFloat ( const CRecvProxyData *pData, void *pStruct, void *pOut );
  220. void RecvProxy_VectorToVector( const CRecvProxyData *pData, void *pStruct, void *pOut );
  221. void RecvProxy_VectorXYToVectorXY( const CRecvProxyData *pData, void *pStruct, void *pOut );
  222. void RecvProxy_QuaternionToQuaternion( const CRecvProxyData *pData, void *pStruct, void *pOut );
  223. void RecvProxy_Int32ToInt8 ( const CRecvProxyData *pData, void *pStruct, void *pOut );
  224. void RecvProxy_Int32ToInt16 ( const CRecvProxyData *pData, void *pStruct, void *pOut );
  225. void RecvProxy_StringToString( const CRecvProxyData *pData, void *pStruct, void *pOut );
  226. void RecvProxy_Int32ToInt32 ( const CRecvProxyData *pData, void *pStruct, void *pOut );
  227. #ifdef SUPPORTS_INT64
  228. void RecvProxy_Int64ToInt64 ( const CRecvProxyData *pData, void *pStruct, void *pOut );
  229. #endif
  230. // StaticDataTable does *pOut = pData.
  231. void DataTableRecvProxy_StaticDataTable(const RecvProp *pProp, void **pOut, void *pData, int objectID);
  232. // PointerDataTable does *pOut = *((void**)pData) (ie: pData is a pointer to the object to decode into).
  233. void DataTableRecvProxy_PointerDataTable(const RecvProp *pProp, void **pOut, void *pData, int objectID);
  234. RecvProp RecvPropFloat(
  235. const char *pVarName,
  236. int offset,
  237. int sizeofVar=SIZEOF_IGNORE, // Handled by RECVINFO macro, but set to SIZEOF_IGNORE if you don't want to bother.
  238. int flags=0,
  239. RecvVarProxyFn varProxy=RecvProxy_FloatToFloat
  240. );
  241. RecvProp RecvPropVector(
  242. const char *pVarName,
  243. int offset,
  244. int sizeofVar=SIZEOF_IGNORE, // Handled by RECVINFO macro, but set to SIZEOF_IGNORE if you don't want to bother.
  245. int flags=0,
  246. RecvVarProxyFn varProxy=RecvProxy_VectorToVector
  247. );
  248. RecvProp RecvPropVectorXY(
  249. const char *pVarName,
  250. int offset,
  251. int sizeofVar=SIZEOF_IGNORE, // Handled by RECVINFO macro, but set to SIZEOF_IGNORE if you don't want to bother.
  252. int flags=0,
  253. RecvVarProxyFn varProxy=RecvProxy_VectorXYToVectorXY
  254. );
  255. // This is here so the RecvTable can look more like the SendTable.
  256. #define RecvPropQAngles RecvPropVector
  257. #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!!!
  258. RecvProp RecvPropQuaternion(
  259. const char *pVarName,
  260. int offset,
  261. int sizeofVar=SIZEOF_IGNORE, // Handled by RECVINFO macro, but set to SIZEOF_IGNORE if you don't want to bother.
  262. int flags=0,
  263. RecvVarProxyFn varProxy=RecvProxy_QuaternionToQuaternion
  264. );
  265. #endif
  266. RecvProp RecvPropInt(
  267. const char *pVarName,
  268. int offset,
  269. int sizeofVar=SIZEOF_IGNORE, // Handled by RECVINFO macro, but set to SIZEOF_IGNORE if you don't want to bother.
  270. int flags=0,
  271. RecvVarProxyFn varProxy=0
  272. );
  273. RecvProp RecvPropString(
  274. const char *pVarName,
  275. int offset,
  276. int bufferSize,
  277. int flags=0,
  278. RecvVarProxyFn varProxy=RecvProxy_StringToString
  279. );
  280. RecvProp RecvPropDataTable(
  281. const char *pVarName,
  282. int offset,
  283. int flags,
  284. RecvTable *pTable,
  285. DataTableRecvVarProxyFn varProxy=DataTableRecvProxy_StaticDataTable
  286. );
  287. RecvProp RecvPropArray3(
  288. const char *pVarName,
  289. int offset,
  290. int sizeofVar,
  291. int elements,
  292. RecvProp pArrayProp,
  293. DataTableRecvVarProxyFn varProxy=DataTableRecvProxy_StaticDataTable
  294. );
  295. // Use the macro to let it automatically generate a table name. You shouldn't
  296. // ever need to reference the table name. If you want to exclude this array, then
  297. // reference the name of the variable in varTemplate.
  298. RecvProp InternalRecvPropArray(
  299. const int elementCount,
  300. const int elementStride,
  301. const char *pName,
  302. ArrayLengthRecvProxyFn proxy
  303. );
  304. //
  305. // Use this if you want to completely manage the way the array data is stored.
  306. // You'll need to provide a proxy inside varTemplate that looks for 'iElement'
  307. // to figure out where to store the specified element.
  308. //
  309. #define RecvPropVirtualArray( arrayLengthProxy, maxArrayLength, varTemplate, propertyName ) \
  310. varTemplate, \
  311. InternalRecvPropArray( \
  312. maxArrayLength, \
  313. 0, \
  314. #propertyName, \
  315. arrayLengthProxy \
  316. )
  317. // Use this and pass the array name and it will figure out the count and stride automatically.
  318. #define RecvPropVariableLengthArray( arrayLengthProxy, varTemplate, arrayName ) \
  319. varTemplate, \
  320. InternalRecvPropArray( \
  321. sizeof(((currentRecvDTClass*)0)->arrayName) / PROPSIZEOF(currentRecvDTClass, arrayName[0]), \
  322. PROPSIZEOF(currentRecvDTClass, arrayName[0]), \
  323. #arrayName, \
  324. arrayLengthProxy \
  325. )
  326. // Use this and pass the array name and it will figure out the count and stride automatically.
  327. #define RecvPropArray( varTemplate, arrayName ) \
  328. RecvPropVariableLengthArray( 0, varTemplate, arrayName )
  329. // Use this one to specify the element count and stride manually.
  330. #define RecvPropArray2( arrayLengthProxy, varTemplate, elementCount, elementStride, arrayName ) \
  331. varTemplate, \
  332. InternalRecvPropArray( elementCount, elementStride, #arrayName, arrayLengthProxy )
  333. // ---------------------------------------------------------------------------------------- //
  334. // Inlines.
  335. // ---------------------------------------------------------------------------------------- //
  336. inline void RecvProp::InitArray( int nElements, int elementStride )
  337. {
  338. m_RecvType = DPT_Array;
  339. m_nElements = nElements;
  340. m_ElementStride = elementStride;
  341. }
  342. inline int RecvProp::GetNumElements() const
  343. {
  344. return m_nElements;
  345. }
  346. inline void RecvProp::SetNumElements( int nElements )
  347. {
  348. m_nElements = nElements;
  349. }
  350. inline int RecvProp::GetElementStride() const
  351. {
  352. return m_ElementStride;
  353. }
  354. inline void RecvProp::SetElementStride( int stride )
  355. {
  356. m_ElementStride = stride;
  357. }
  358. inline int RecvProp::GetFlags() const
  359. {
  360. return m_Flags;
  361. }
  362. inline const char* RecvProp::GetName() const
  363. {
  364. return m_pVarName;
  365. }
  366. inline SendPropType RecvProp::GetType() const
  367. {
  368. return m_RecvType;
  369. }
  370. inline RecvTable* RecvProp::GetDataTable() const
  371. {
  372. return m_pDataTable;
  373. }
  374. inline void RecvProp::SetDataTable( RecvTable *pTable )
  375. {
  376. m_pDataTable = pTable;
  377. }
  378. inline RecvVarProxyFn RecvProp::GetProxyFn() const
  379. {
  380. return m_ProxyFn;
  381. }
  382. inline void RecvProp::SetProxyFn( RecvVarProxyFn fn )
  383. {
  384. m_ProxyFn = fn;
  385. }
  386. inline DataTableRecvVarProxyFn RecvProp::GetDataTableProxyFn() const
  387. {
  388. return m_DataTableProxyFn;
  389. }
  390. inline void RecvProp::SetDataTableProxyFn( DataTableRecvVarProxyFn fn )
  391. {
  392. m_DataTableProxyFn = fn;
  393. }
  394. inline int RecvProp::GetOffset() const
  395. {
  396. return m_Offset;
  397. }
  398. inline void RecvProp::SetOffset( int o )
  399. {
  400. m_Offset = o;
  401. }
  402. inline RecvProp* RecvProp::GetArrayProp() const
  403. {
  404. return m_pArrayProp;
  405. }
  406. inline void RecvProp::SetArrayProp( RecvProp *pProp )
  407. {
  408. m_pArrayProp = pProp;
  409. }
  410. inline void RecvProp::SetArrayLengthProxy( ArrayLengthRecvProxyFn proxy )
  411. {
  412. m_ArrayLengthProxy = proxy;
  413. }
  414. inline ArrayLengthRecvProxyFn RecvProp::GetArrayLengthProxy() const
  415. {
  416. return m_ArrayLengthProxy;
  417. }
  418. inline bool RecvProp::IsInsideArray() const
  419. {
  420. return m_bInsideArray;
  421. }
  422. inline void RecvProp::SetInsideArray()
  423. {
  424. m_bInsideArray = true;
  425. }
  426. inline const void* RecvProp::GetExtraData() const
  427. {
  428. return m_pExtraData;
  429. }
  430. inline void RecvProp::SetExtraData( const void *pData )
  431. {
  432. m_pExtraData = pData;
  433. }
  434. inline const char* RecvProp::GetParentArrayPropName()
  435. {
  436. return m_pParentArrayPropName;
  437. }
  438. inline void RecvProp::SetParentArrayPropName( const char *pArrayPropName )
  439. {
  440. m_pParentArrayPropName = pArrayPropName;
  441. }
  442. #endif // DATATABLE_RECV_H