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.

253 lines
5.3 KiB

  1. //========= Copyright � 1996-2008, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #if !defined( NO_ENTITY_PREDICTION )
  10. #include "igamesystem.h"
  11. #ifndef _PS3
  12. #ifdef WIN32
  13. #include <typeinfo.h>
  14. #else
  15. #include <typeinfo>
  16. #endif
  17. #endif
  18. #include "cdll_int.h"
  19. #ifndef _PS3
  20. #include <memory.h>
  21. #endif
  22. #include <stdarg.h>
  23. #include "tier0/dbg.h"
  24. #include "tier1/strtools.h"
  25. #include "predictioncopy.h"
  26. #include "engine/ivmodelinfo.h"
  27. #include "tier1/fmtstr.h"
  28. #include "utlvector.h"
  29. // memdbgon must be the last include file in a .cpp file!!!
  30. #include "tier0/memdbgon.h"
  31. CValueChangeTracker::CValueChangeTracker() :
  32. m_bActive( false ),
  33. m_bTracking( false ),
  34. m_pTrackField( NULL )
  35. {
  36. Q_memset( m_OrigValueBuf, 0, sizeof( m_OrigValueBuf ) );
  37. }
  38. C_BaseEntity *CValueChangeTracker::GetEntity()
  39. {
  40. return m_hEntityToTrack.Get();
  41. }
  42. void CValueChangeTracker::GetValue( char *buf, size_t bufsize )
  43. {
  44. buf[ 0 ] = 0;
  45. Assert( IsActive() );
  46. if ( !m_hEntityToTrack.Get() )
  47. return;
  48. if ( !m_pTrackField )
  49. return;
  50. void const *pInputData = ( const byte * )m_hEntityToTrack.Get() + m_pTrackField->flatOffset[ TD_OFFSET_NORMAL ];
  51. if ( !pInputData )
  52. return;
  53. int fieldType = m_pTrackField->fieldType;
  54. switch( fieldType )
  55. {
  56. default:
  57. case FIELD_EMBEDDED:
  58. case FIELD_MODELNAME:
  59. case FIELD_SOUNDNAME:
  60. case FIELD_CUSTOM:
  61. case FIELD_CLASSPTR:
  62. case FIELD_EDICT:
  63. case FIELD_POSITION_VECTOR:
  64. case FIELD_VOID:
  65. case FIELD_FUNCTION:
  66. {
  67. Assert( 0 );
  68. }
  69. break;
  70. case FIELD_FLOAT:
  71. case FIELD_TIME:
  72. Q_snprintf( buf, bufsize, "%f", *(float const *)pInputData );
  73. break;
  74. case FIELD_STRING:
  75. Q_snprintf( buf, bufsize, "%s", (char const*)pInputData );
  76. break;
  77. case FIELD_VECTOR:
  78. {
  79. const Vector *pVec = (const Vector *)pInputData;
  80. Q_snprintf( buf, bufsize, "%f %f %f", pVec->x, pVec->y, pVec->z );
  81. }
  82. break;
  83. case FIELD_QUATERNION:
  84. {
  85. const Quaternion *p = ( const Quaternion * )pInputData;
  86. Q_snprintf( buf, bufsize, "%f %f %f %f", p->x, p->y, p->z, p->w );
  87. }
  88. break;
  89. case FIELD_COLOR32:
  90. {
  91. const Color *color = ( const Color * )pInputData;
  92. Q_snprintf( buf, bufsize, "%d %d %d %d", color->r(), color->g(), color->b(), color->a() );
  93. }
  94. break;
  95. case FIELD_BOOLEAN:
  96. Q_snprintf( buf, bufsize, "%s", (*(const bool *)pInputData) ? "true" : "false" );
  97. break;
  98. case FIELD_INTEGER:
  99. case FIELD_TICK:
  100. case FIELD_MODELINDEX:
  101. Q_snprintf( buf, bufsize, "%i", *(const int*)pInputData );
  102. break;
  103. case FIELD_SHORT:
  104. Q_snprintf( buf, bufsize, "%i", (int)*(const short*)pInputData );
  105. break;
  106. case FIELD_CHARACTER:
  107. Q_snprintf( buf, bufsize, "%c", *(const char *)pInputData );
  108. break;
  109. case FIELD_EHANDLE:
  110. Q_snprintf( buf, bufsize, "eh 0x%p", (void const *)((const EHANDLE *)pInputData)->Get() );
  111. break;
  112. }
  113. }
  114. void CValueChangeTracker::StartTrack( char const *pchContext )
  115. {
  116. if ( !IsActive() )
  117. return;
  118. m_strContext = pchContext;
  119. // Grab current value into scratch buffer
  120. GetValue( m_OrigValueBuf, sizeof( m_OrigValueBuf ) );
  121. m_bTracking = true;
  122. }
  123. void CValueChangeTracker::EndTrack()
  124. {
  125. if ( !IsActive() )
  126. return;
  127. if ( !m_bTracking )
  128. return;
  129. m_bTracking = false;
  130. char final[ eChangeTrackerBufSize ];
  131. GetValue( final, sizeof( final ) );
  132. CUtlString *history = &m_History[ m_History.AddToTail() ];
  133. if ( Q_stricmp( final, m_OrigValueBuf ) )
  134. {
  135. history->Set( CFmtStr( "+++ %-20.20s: %s (was %s)", m_strContext.String(), final, m_OrigValueBuf ) );
  136. }
  137. else
  138. {
  139. history->Set( CFmtStr( " %-20.20s: %s", m_strContext.String(), final ) );
  140. }
  141. Msg( ":%s\n", history->String() );
  142. }
  143. void CValueChangeTracker::ClearTracking()
  144. {
  145. m_bActive = false;
  146. m_bTracking = false;
  147. m_hEntityToTrack = NULL;
  148. m_strFieldName = "";
  149. m_History.RemoveAll();
  150. m_pTrackField = NULL;
  151. }
  152. void CValueChangeTracker::SetupTracking( C_BaseEntity *ent, char const *pchFieldName )
  153. {
  154. ClearTracking();
  155. // Find the field
  156. datamap_t *dmap = ent->GetPredDescMap();
  157. if ( !dmap )
  158. {
  159. Msg( "No prediction datamap_t for entity %d/%s\n", ent->index, ent->GetClassname() );
  160. return;
  161. }
  162. CPredictionCopy::PrepareDataMap( dmap );
  163. m_pTrackField = CPredictionCopy::FindFlatFieldByName( pchFieldName, dmap );
  164. if ( !m_pTrackField )
  165. {
  166. Msg( "No field '%s' in datamap_t for entity %d/%s\n", pchFieldName, ent->index, ent->GetClassname() );
  167. return;
  168. }
  169. m_hEntityToTrack = ent;
  170. m_strFieldName = pchFieldName;
  171. m_bActive = true;
  172. }
  173. void CValueChangeTracker::Reset()
  174. {
  175. m_History.RemoveAll();
  176. }
  177. bool CValueChangeTracker::IsActive() const
  178. {
  179. return m_bActive;
  180. }
  181. void CValueChangeTracker::Spew()
  182. {
  183. if ( IsActive() )
  184. {
  185. for ( int i = 0 ; i < m_History.Count(); ++i )
  186. {
  187. Msg( "%s\n", m_History[ i ].String() );
  188. }
  189. }
  190. Reset();
  191. }
  192. static CValueChangeTracker g_ChangeTracker;
  193. CValueChangeTracker *g_pChangeTracker = &g_ChangeTracker;
  194. CON_COMMAND_F( cl_pred_track, "<entindex> <fieldname>: Track changes to entity index entindex, for field fieldname.", 0 )
  195. {
  196. g_pChangeTracker->ClearTracking();
  197. if ( args.ArgC() != 3 )
  198. {
  199. Msg( "cl_pred_track <entindex> <fieldname>\n" );
  200. return;
  201. }
  202. int iEntIndex = Q_atoi( args[1] );
  203. C_BaseEntity *ent = cl_entitylist->GetBaseEntity( iEntIndex );
  204. if ( !ent )
  205. {
  206. Msg( "cl_pred_track: Unknown ent index %d\n", iEntIndex );
  207. return;
  208. }
  209. g_pChangeTracker->SetupTracking( ent, args[2] );
  210. }
  211. #endif // NO_ENTITY_PREDICTION