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.

360 lines
14 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #ifndef PREDICTIONCOPY_H
  8. #define PREDICTIONCOPY_H
  9. #ifdef _WIN32
  10. #pragma once
  11. #endif
  12. #ifndef _PS3
  13. #include <memory.h>
  14. #endif
  15. #include "datamap.h"
  16. #include "ehandle.h"
  17. #include "tier1/utlstring.h"
  18. #include "tier1/utlrbtree.h"
  19. #include "tier1/utlstack.h"
  20. #if defined( CLIENT_DLL )
  21. class C_BaseEntity;
  22. typedef CHandle<C_BaseEntity> EHANDLE;
  23. // #define COPY_CHECK_STRESSTEST
  24. #if defined( COPY_CHECK_STRESSTEST )
  25. class IGameSystem;
  26. IGameSystem* GetPredictionCopyTester( void );
  27. #endif
  28. #else
  29. class CBaseEntity;
  30. typedef CHandle<CBaseEntity> EHANDLE;
  31. #endif
  32. typedef void ( *FN_FIELD_COMPARE )( const char *classname, const char *fieldname, const char *fieldtype,
  33. bool networked, bool noterrorchecked, bool differs, bool withintolerance, const char *value );
  34. // Each datamap_t is broken down into two flattened arrays of fields,
  35. // one for PC_NETWORKED_DATA and one for PC_NON_NETWORKED_ONLY (optimized_datamap_t::datamapinfo_t::flattenedoffsets_t)
  36. // Each flattened array is sorted by offset for better cache performance
  37. // Finally, contiguous "runs" off offsets are precomputed (optimized_datamap_t::datamapinfo_t::datacopyruns_t) for fast copy operations
  38. // A data run is a set of DEFINE_PRED_FIELD fields in a c++ object which are contiguous and can be processing
  39. // using a single memcpy operation
  40. struct datarun_t
  41. {
  42. datarun_t() : m_nStartFlatField( 0 ), m_nEndFlatField( 0 ), m_nLength( 0 )
  43. {
  44. for ( int i = 0 ; i < TD_OFFSET_COUNT; ++i )
  45. {
  46. m_nStartOffset[ i ] = 0;
  47. #ifdef _GAMECONSOLE
  48. // These are the offsets of the next run, for priming the L1 cache
  49. m_nPrefetchOffset[ i ] = 0;
  50. #endif
  51. }
  52. }
  53. // Indices of start/end fields in the flattened typedescription_t list
  54. int m_nStartFlatField;
  55. int m_nEndFlatField;
  56. // Offsets for run in the packed/unpacked data (I think the run starts need to be properly aligned)
  57. int m_nStartOffset[ TD_OFFSET_COUNT ];
  58. #ifdef _GAMECONSOLE
  59. // These are the offsets of the next run, for priming the L1 cache
  60. int m_nPrefetchOffset[ TD_OFFSET_COUNT ];
  61. #endif
  62. int m_nLength;
  63. };
  64. struct datacopyruns_t
  65. {
  66. public:
  67. CUtlVector< datarun_t > m_vecRuns;
  68. };
  69. struct flattenedoffsets_t
  70. {
  71. CUtlVector< typedescription_t > m_Flattened;
  72. int m_nPackedSize; // Contiguous memory to pack all of these together for TD_OFFSET_PACKED
  73. int m_nPackedStartOffset;
  74. };
  75. struct datamapinfo_t
  76. {
  77. // Flattened list, with FIELD_EMBEDDED, FTYPEDESC_PRIVATE,
  78. // and FTYPEDESC_OVERRIDE (overridden) fields removed
  79. flattenedoffsets_t m_Flat;
  80. datacopyruns_t m_CopyRuns;
  81. };
  82. struct optimized_datamap_t
  83. {
  84. // Optimized info for PC_NON_NETWORKED and PC_NETWORKED data
  85. datamapinfo_t m_Info[ PC_COPYTYPE_COUNT ];
  86. };
  87. class CPredictionCopy
  88. {
  89. public:
  90. typedef enum
  91. {
  92. DIFFERS = 0,
  93. IDENTICAL,
  94. WITHINTOLERANCE,
  95. } difftype_t;
  96. typedef enum
  97. {
  98. TRANSFERDATA_COPYONLY = 0, // Data copying only (uses runs)
  99. TRANSFERDATA_ERRORCHECK_NOSPEW, // Checks for errors, returns after first error found
  100. TRANSFERDATA_ERRORCHECK_SPEW, // checks for errors, reports all errors to console
  101. TRANSFERDATA_ERRORCHECK_DESCRIBE, // used by hud_pdump, dumps values, etc, for all fields
  102. } optype_t;
  103. CPredictionCopy( int type, byte *dest, bool dest_packed, const byte *src, bool src_packed,
  104. optype_t opType, FN_FIELD_COMPARE func = NULL );
  105. int TransferData( const char *operation, int entindex, datamap_t *dmap );
  106. static bool PrepareDataMap( datamap_t *dmap );
  107. static const typedescription_t *FindFlatFieldByName( const char *fieldname, const datamap_t *dmap );
  108. private:
  109. // Operations:
  110. void TransferDataCopyOnly( const datamap_t *dmap );
  111. void TransferDataErrorCheckNoSpew( char const *pchOperation, const datamap_t *dmap );
  112. void TransferDataErrorCheckSpew( char const *pchOperation, const datamap_t *dmap );
  113. void TransferDataDescribe( char const *pchOperation, const datamap_t *dmap );
  114. // Report function
  115. void ReportFieldsDiffer( const datamap_t *pCurrentMap, const typedescription_t *pField, PRINTF_FORMAT_STRING const char *fmt, ... );
  116. void OutputFieldDescription( const datamap_t *pCurrentMap, const typedescription_t *pField, difftype_t dt, PRINTF_FORMAT_STRING const char *fmt, ... );
  117. // Helper for TransferDataCopyOnly
  118. void CopyFlatFieldsUsingRuns( const datamap_t *pCurrentMap, int nPredictionCopyType );
  119. void CopyFlatFields( const datamap_t *pCurrentMap, int nPredictionCopyType );
  120. template< class T >
  121. FORCEINLINE void CopyField( difftype_t difftype, T *outvalue, const T *invalue, int count );
  122. // Helper for TransferDataErrorCheckNoSpew
  123. void ErrorCheckFlatFields_NoSpew( const datamap_t *pCurrentMap, int nPredictionCopyType );
  124. template< class T >
  125. FORCEINLINE void ProcessField_Compare_NoSpew( const datamap_t *pCurrentMap, const typedescription_t *pField, const T *pOutputData, const T *pInputData, int fieldSize );
  126. // Helper for TransferDataErrorCheckSpew
  127. void ErrorCheckFlatFields_Spew( const datamap_t *pCurrentMap, int nPredictionCopyType );
  128. template< class T >
  129. FORCEINLINE void ProcessField_Compare_Spew( const datamap_t *pCurrentMap, const typedescription_t *pField, const T *pOutputData, const T *pInputData, int fieldSize );
  130. // Helper for TransferDataDescribe
  131. void DescribeFields( const CUtlVector< const datamap_t * > &vecGroups, const datamap_t *pCurrentMap, int nPredictionCopyType );
  132. // Main entry point
  133. template< class T >
  134. FORCEINLINE void ProcessField_Describe( const datamap_t *pCurrentMap, const typedescription_t *pField, const T *pOutputData, const T *pInputData, int fieldSize );
  135. // Helpers for entity field watcher
  136. void DetermineWatchField( const char *operation, int entindex, const datamap_t *dmap );
  137. void WatchMsg( const typedescription_t *pField, PRINTF_FORMAT_STRING const char *fmt, ... );
  138. void DumpWatchField( const typedescription_t *pField, const byte *outvalue, int count );
  139. template< class T >
  140. FORCEINLINE void WatchField( const typedescription_t *pField, const T *outvalue, int count );
  141. // Helper for ErrorCheck ops
  142. template< class T >
  143. FORCEINLINE difftype_t CompareField( const typedescription_t *pField, const T *outvalue, const T *invalue, int count );
  144. // Used by TRANSFERDATA_ERRORCHECK_SPEW and by TRANSFERDATA_ERRORCHECK_DESCRIBE
  145. template< class T >
  146. FORCEINLINE void DescribeField( const datamap_t *pCurrentMap, const typedescription_t *pField, difftype_t difftype, const T *outvalue, const T *invalue, int count );
  147. private:
  148. optype_t m_OpType;
  149. int m_nType;
  150. byte *m_pDest;
  151. const byte *m_pSrc;
  152. int m_nDestOffsetIndex;
  153. int m_nSrcOffsetIndex;
  154. int m_nErrorCount;
  155. int m_nEntIndex;
  156. FN_FIELD_COMPARE m_FieldCompareFunc;
  157. const typedescription_t *m_pWatchField;
  158. char const *m_pOperation;
  159. CUtlStack< const typedescription_t * > m_FieldStack;
  160. };
  161. typedef void (*FN_FIELD_DESCRIPTION)( const char *classname, const char *fieldname, const char *fieldtype,
  162. bool networked, const char *value );
  163. //
  164. // Compare methods
  165. //
  166. // Specializations
  167. template<> FORCEINLINE CPredictionCopy::difftype_t CPredictionCopy::CompareField( const typedescription_t *pField, const float *outvalue, const float *invalue, int count );
  168. template<> FORCEINLINE CPredictionCopy::difftype_t CPredictionCopy::CompareField( const typedescription_t *pField, const Vector *outvalue, const Vector *invalue, int count );
  169. template<> FORCEINLINE CPredictionCopy::difftype_t CPredictionCopy::CompareField( const typedescription_t *pField, const Quaternion *outvalue, const Quaternion *invalue, int count );
  170. template<> FORCEINLINE CPredictionCopy::difftype_t CPredictionCopy::CompareField( const typedescription_t *pField, const char *outvalue, const char *invalue, int count );
  171. template<> FORCEINLINE CPredictionCopy::difftype_t CPredictionCopy::CompareField( const typedescription_t *pField, const EHANDLE *outvalue, const EHANDLE *invalue, int count );
  172. template<> FORCEINLINE CPredictionCopy::difftype_t CPredictionCopy::CompareField( const typedescription_t *pField, const color32 *outvalue, const color32 *invalue, int count );
  173. //
  174. // Describe Methods
  175. //
  176. // Specializations
  177. template<> FORCEINLINE void CPredictionCopy::DescribeField( const datamap_t *pCurrentMap, const typedescription_t *pField, difftype_t difftype, const short *outvalue, const short *invalue, int count );
  178. template<> FORCEINLINE void CPredictionCopy::DescribeField( const datamap_t *pCurrentMap, const typedescription_t *pField, difftype_t difftype, const int *outvalue, const int *invalue, int count );
  179. template<> FORCEINLINE void CPredictionCopy::DescribeField( const datamap_t *pCurrentMap, const typedescription_t *pField, difftype_t difftype, const bool *outvalue, const bool *invalue, int count );
  180. template<> FORCEINLINE void CPredictionCopy::DescribeField( const datamap_t *pCurrentMap, const typedescription_t *pField, difftype_t difftype, const float *outvalue, const float *invalue, int count );
  181. template<> FORCEINLINE void CPredictionCopy::DescribeField( const datamap_t *pCurrentMap, const typedescription_t *pField, difftype_t difftype, const char *outvalue, const char *invalue, int count );
  182. template<> FORCEINLINE void CPredictionCopy::DescribeField( const datamap_t *pCurrentMap, const typedescription_t *pField, difftype_t difftype, const Vector* outValue, const Vector *inValue, int count );
  183. template<> FORCEINLINE void CPredictionCopy::DescribeField( const datamap_t *pCurrentMap, const typedescription_t *pField, difftype_t difftype, const Quaternion* outValue, const Quaternion *inValue, int count );
  184. template<> FORCEINLINE void CPredictionCopy::DescribeField( const datamap_t *pCurrentMap, const typedescription_t *pField, difftype_t difftype, const EHANDLE *outvalue, const EHANDLE *invalue, int count );
  185. template<> FORCEINLINE void CPredictionCopy::DescribeField( const datamap_t *pCurrentMap, const typedescription_t *pField, difftype_t difftype, const color32 *outvalue, const color32 *invalue, int count );
  186. template<> FORCEINLINE void CPredictionCopy::DescribeField( const datamap_t *pCurrentMap, const typedescription_t *pField, difftype_t difftype, const uint8 *outvalue, const uint8 *invalue, int count );
  187. //
  188. // Watch Methods
  189. //
  190. // Specializations
  191. template<> FORCEINLINE void CPredictionCopy::WatchField( const typedescription_t *pField, const short *outvalue,int count );
  192. template<> FORCEINLINE void CPredictionCopy::WatchField( const typedescription_t *pField, const int *outvalue, int count );
  193. template<> FORCEINLINE void CPredictionCopy::WatchField( const typedescription_t *pField, const bool *outvalue, int count );
  194. template<> FORCEINLINE void CPredictionCopy::WatchField( const typedescription_t *pField, const float *outvalue, int count );
  195. template<> FORCEINLINE void CPredictionCopy::WatchField( const typedescription_t *pField, const Vector *outvalue, int count );
  196. template<> FORCEINLINE void CPredictionCopy::WatchField( const typedescription_t *pField, const Quaternion *outvalue, int count );
  197. template<> FORCEINLINE void CPredictionCopy::WatchField( const typedescription_t *pField, const EHANDLE *outvalue, int count );
  198. template<> FORCEINLINE void CPredictionCopy::WatchField( const typedescription_t *pField, const char *outvalue, int count );
  199. template<> FORCEINLINE void CPredictionCopy::WatchField( const typedescription_t *pField, const color32 *outvalue, int count );
  200. //
  201. // Copy Methods
  202. //
  203. // specializations
  204. template<> FORCEINLINE void CPredictionCopy::CopyField( difftype_t difftype, char *outvalue, const char *invalue, int count );
  205. template< class T >
  206. FORCEINLINE void CPredictionCopy::ProcessField_Compare_NoSpew( const datamap_t *pCurrentMap, const typedescription_t *pField, const T *pOutputData, const T *pInputData, int fieldSize )
  207. {
  208. difftype_t difftype = CompareField( pField, pOutputData, pInputData, fieldSize );
  209. if ( difftype == DIFFERS )
  210. {
  211. ++m_nErrorCount;
  212. }
  213. }
  214. template< class T >
  215. FORCEINLINE void CPredictionCopy::ProcessField_Compare_Spew( const datamap_t *pCurrentMap, const typedescription_t *pField, const T *pOutputData, const T *pInputData, int fieldSize )
  216. {
  217. difftype_t difftype = CompareField( pField, pOutputData, pInputData, fieldSize );
  218. DescribeField( pCurrentMap, pField, difftype, pOutputData, pInputData, fieldSize );
  219. }
  220. template< class T >
  221. FORCEINLINE void CPredictionCopy::ProcessField_Describe( const datamap_t *pCurrentMap, const typedescription_t *pField, const T *pOutputData, const T *pInputData, int fieldSize )
  222. {
  223. difftype_t difftype = CompareField( pField, pOutputData, pInputData, fieldSize );
  224. DescribeField( pCurrentMap, pField, difftype, pOutputData, pInputData, fieldSize );
  225. }
  226. #if defined( CLIENT_DLL )
  227. class CValueChangeTracker
  228. {
  229. public:
  230. CValueChangeTracker();
  231. void Reset();
  232. void StartTrack( char const *pchContext );
  233. void EndTrack();
  234. bool IsActive() const;
  235. void SetupTracking( C_BaseEntity *ent, char const *pchFieldName );
  236. void ClearTracking();
  237. void Spew();
  238. C_BaseEntity *GetEntity();
  239. private:
  240. enum
  241. {
  242. eChangeTrackerBufSize = 128,
  243. };
  244. // Returns field size
  245. void GetValue( char *buf, size_t bufsize );
  246. bool m_bActive : 1;
  247. bool m_bTracking : 1;
  248. EHANDLE m_hEntityToTrack;
  249. const typedescription_t *m_pTrackField;
  250. CUtlString m_strFieldName;
  251. CUtlString m_strContext;
  252. // First 128 bytes of data is all we will consider
  253. char m_OrigValueBuf[ eChangeTrackerBufSize ];
  254. CUtlVector< CUtlString > m_History;
  255. };
  256. extern CValueChangeTracker *g_pChangeTracker;
  257. class CValueChangeTrackerScope
  258. {
  259. public:
  260. CValueChangeTrackerScope( char const *pchContext )
  261. {
  262. m_bCallEndTrack = true;
  263. g_pChangeTracker->StartTrack( pchContext );
  264. }
  265. // Only calls Start/End if passed in entity matches entity to track
  266. CValueChangeTrackerScope( C_BaseEntity *pEntity, char const *pchContext )
  267. {
  268. m_bCallEndTrack = g_pChangeTracker->GetEntity() == pEntity;
  269. if ( m_bCallEndTrack )
  270. {
  271. g_pChangeTracker->StartTrack( pchContext );
  272. }
  273. }
  274. ~CValueChangeTrackerScope()
  275. {
  276. if ( m_bCallEndTrack )
  277. {
  278. g_pChangeTracker->EndTrack();
  279. }
  280. }
  281. private:
  282. bool m_bCallEndTrack;
  283. };
  284. #if defined( _DEBUG )
  285. #define PREDICTION_TRACKVALUECHANGESCOPE( context ) CValueChangeTrackerScope scope( context );
  286. #define PREDICTION_TRACKVALUECHANGESCOPE_ENTITY( entity, context ) CValueChangeTrackerScope scope( entity, context );
  287. #define PREDICTION_STARTTRACKVALUE( context ) g_pChangeTracker->StartTrack( context );
  288. #define PREDICTION_ENDTRACKVALUE() g_pChangeTracker->EndTrack();
  289. #define PREDICTION_SPEWVALUECHANGES() g_pChangeTracker->Spew();
  290. #else
  291. #define PREDICTION_TRACKVALUECHANGESCOPE( context )
  292. #define PREDICTION_TRACKVALUECHANGESCOPE_ENTITY( entity, context )
  293. #define PREDICTION_STARTTRACKVALUE( context )
  294. #define PREDICTION_ENDTRACKVALUE()
  295. #define PREDICTION_SPEWVALUECHANGES()
  296. #endif
  297. #endif // !CLIENT_DLL
  298. #endif // PREDICTIONCOPY_H