#ifndef PREDICTIONCOPY_H #define PREDICTIONCOPY_H #ifdef _WIN32 #pragma once #endif #include #include "datamap.h" #include "ehandle.h" #include "utlstring.h" #if defined( CLIENT_DLL ) class C_BaseEntity; typedef CHandle EHANDLE; #if defined( _DEBUG ) class IGameSystem; IGameSystem* GetPredictionCopyTester(void); #endif #else class CBaseEntity; typedef CHandle EHANDLE; #endif enum { PC_EVERYTHING = 0, PC_NON_NETWORKED_ONLY, PC_NETWORKED_ONLY, }; #define PC_DATA_PACKED true #define PC_DATA_NORMAL false typedef void (*FN_FIELD_COMPARE)(const char* classname, const char* fieldname, const char* fieldtype, bool networked, bool noterrorchecked, bool differs, bool withintolerance, const char* value); class CPredictionCopy { public: typedef enum { DIFFERS = 0, IDENTICAL, WITHINTOLERANCE, } difftype_t; CPredictionCopy(int type, void* dest, bool dest_packed, void const* src, bool src_packed, bool counterrors = false, bool reporterrors = false, bool performcopy = true, bool describefields = false, FN_FIELD_COMPARE func = NULL); void CopyShort(difftype_t dt, short* outvalue, const short* invalue, int count); void CopyInt(difftype_t dt, int* outvalue, const int* invalue, int count); void CopyBool(difftype_t dt, bool* outvalue, const bool* invalue, int count); void CopyFloat(difftype_t dt, float* outvalue, const float* invalue, int count); void CopyString(difftype_t dt, char* outstring, const char* instring); void CopyVector(difftype_t dt, Vector& outValue, const Vector& inValue); void CopyVector(difftype_t dt, Vector* outValue, const Vector* inValue, int count); void CopyQuaternion(difftype_t dt, Quaternion& outValue, const Quaternion& inValue); void CopyQuaternion(difftype_t dt, Quaternion* outValue, const Quaternion* inValue, int count); void CopyEHandle(difftype_t dt, EHANDLE* outvalue, EHANDLE const* invalue, int count); void FORCEINLINE CopyData(difftype_t dt, int size, char* outdata, const char* indata) { if (!m_bPerformCopy) return; if (dt == IDENTICAL) return; memcpy(outdata, indata, size); } int TransferData(const char* operation, int entindex, datamap_t* dmap); private: void TransferData_R(int chaincount, datamap_t* dmap); void DetermineWatchField(const char* operation, int entindex, datamap_t* dmap); void DumpWatchField(typedescription_t* field); void WatchMsg(PRINTF_FORMAT_STRING const char* fmt, ...); difftype_t CompareShort(short* outvalue, const short* invalue, int count); difftype_t CompareInt(int* outvalue, const int* invalue, int count); difftype_t CompareBool(bool* outvalue, const bool* invalue, int count); difftype_t CompareFloat(float* outvalue, const float* invalue, int count); difftype_t CompareData(int size, char* outdata, const char* indata); difftype_t CompareString(char* outstring, const char* instring); difftype_t CompareVector(Vector& outValue, const Vector& inValue); difftype_t CompareVector(Vector* outValue, const Vector* inValue, int count); difftype_t CompareQuaternion(Quaternion& outValue, const Quaternion& inValue); difftype_t CompareQuaternion(Quaternion* outValue, const Quaternion* inValue, int count); difftype_t CompareEHandle(EHANDLE* outvalue, EHANDLE const* invalue, int count); void DescribeShort(difftype_t dt, short* outvalue, const short* invalue, int count); void DescribeInt(difftype_t dt, int* outvalue, const int* invalue, int count); void DescribeBool(difftype_t dt, bool* outvalue, const bool* invalue, int count); void DescribeFloat(difftype_t dt, float* outvalue, const float* invalue, int count); void DescribeData(difftype_t dt, int size, char* outdata, const char* indata); void DescribeString(difftype_t dt, char* outstring, const char* instring); void DescribeVector(difftype_t dt, Vector& outValue, const Vector& inValue); void DescribeVector(difftype_t dt, Vector* outValue, const Vector* inValue, int count); void DescribeQuaternion(difftype_t dt, Quaternion& outValue, const Quaternion& inValue); void DescribeQuaternion(difftype_t dt, Quaternion* outValue, const Quaternion* inValue, int count); void DescribeEHandle(difftype_t dt, EHANDLE* outvalue, EHANDLE const* invalue, int count); void WatchShort(difftype_t dt, short* outvalue, const short* invalue, int count); void WatchInt(difftype_t dt, int* outvalue, const int* invalue, int count); void WatchBool(difftype_t dt, bool* outvalue, const bool* invalue, int count); void WatchFloat(difftype_t dt, float* outvalue, const float* invalue, int count); void WatchData(difftype_t dt, int size, char* outdata, const char* indata); void WatchString(difftype_t dt, char* outstring, const char* instring); void WatchVector(difftype_t dt, Vector& outValue, const Vector& inValue); void WatchVector(difftype_t dt, Vector* outValue, const Vector* inValue, int count); void WatchQuaternion(difftype_t dt, Quaternion& outValue, const Quaternion& inValue); void WatchQuaternion(difftype_t dt, Quaternion* outValue, const Quaternion* inValue, int count); void WatchEHandle(difftype_t dt, EHANDLE* outvalue, EHANDLE const* invalue, int count); void ReportFieldsDiffer(PRINTF_FORMAT_STRING const char* fmt, ...); void DescribeFields(difftype_t dt, PRINTF_FORMAT_STRING const char* fmt, ...); bool CanCheck(void); void CopyFields(int chaincount, datamap_t* pMap, typedescription_t* pFields, int fieldCount); private: int m_nType; void* m_pDest; void const* m_pSrc; int m_nDestOffsetIndex; int m_nSrcOffsetIndex; bool m_bErrorCheck; bool m_bReportErrors; bool m_bDescribeFields; typedescription_t* m_pCurrentField; char const* m_pCurrentClassName; datamap_t* m_pCurrentMap; bool m_bShouldReport; bool m_bShouldDescribe; int m_nErrorCount; bool m_bPerformCopy; FN_FIELD_COMPARE m_FieldCompareFunc; typedescription_t* m_pWatchField; char const* m_pOperation; }; typedef void (*FN_FIELD_DESCRIPTION)(const char* classname, const char* fieldname, const char* fieldtype, bool networked, const char* value); class CPredictionDescribeData { public: CPredictionDescribeData(void const* src, bool src_packed, FN_FIELD_DESCRIPTION func = 0); void DescribeShort(const short* invalue, int count); void DescribeInt(const int* invalue, int count); void DescribeBool(const bool* invalue, int count); void DescribeFloat(const float* invalue, int count); void DescribeData(int size, const char* indata); void DescribeString(const char* instring); void DescribeVector(const Vector& inValue); void DescribeVector(const Vector* inValue, int count); void DescribeQuaternion(const Quaternion& inValue); void DescribeQuaternion(const Quaternion* inValue, int count); void DescribeEHandle(EHANDLE const* invalue, int count); void DumpDescription(datamap_t* pMap); private: void DescribeFields_R(int chain_count, datamap_t* pMap, typedescription_t* pFields, int fieldCount); void const* m_pSrc; int m_nSrcOffsetIndex; void Describe(PRINTF_FORMAT_STRING const char* fmt, ...); typedescription_t* m_pCurrentField; char const* m_pCurrentClassName; datamap_t* m_pCurrentMap; bool m_bShouldReport; FN_FIELD_DESCRIPTION m_FieldDescFunc; }; #if defined( CLIENT_DLL ) class CValueChangeTracker { public: CValueChangeTracker(); void Reset(); void StartTrack(char const* pchContext); void EndTrack(); bool IsActive() const; void SetupTracking(C_BaseEntity* ent, char const* pchFieldName); void ClearTracking(); void Spew(); C_BaseEntity* GetEntity(); private: enum { eChangeTrackerBufSize = 128, }; void GetValue(char* buf, size_t bufsize); bool m_bActive : 1; bool m_bTracking : 1; EHANDLE m_hEntityToTrack; CUtlVector< typedescription_t* > m_FieldStack; CUtlString m_strFieldName; CUtlString m_strContext; char m_OrigValueBuf[eChangeTrackerBufSize]; CUtlVector< CUtlString > m_History; }; extern CValueChangeTracker* g_pChangeTracker; class CValueChangeTrackerScope { public: CValueChangeTrackerScope(char const* pchContext) { m_bCallEndTrack = true; g_pChangeTracker->StartTrack(pchContext); } CValueChangeTrackerScope(C_BaseEntity* pEntity, char const* pchContext) { m_bCallEndTrack = g_pChangeTracker->GetEntity() == pEntity; if (m_bCallEndTrack) { g_pChangeTracker->StartTrack(pchContext); } } ~CValueChangeTrackerScope() { if (m_bCallEndTrack) { g_pChangeTracker->EndTrack(); } } private: bool m_bCallEndTrack; }; #if defined( _DEBUG ) #define PREDICTION_TRACKVALUECHANGESCOPE( context ) CValueChangeTrackerScope scope( context ); #define PREDICTION_TRACKVALUECHANGESCOPE_ENTITY( entity, context ) CValueChangeTrackerScope scope( entity, context ); #define PREDICTION_STARTTRACKVALUE( context ) g_pChangeTracker->StartTrack( context ); #define PREDICTION_ENDTRACKVALUE() g_pChangeTracker->EndTrack(); #define PREDICTION_SPEWVALUECHANGES() g_pChangeTracker->Spew(); #else #define PREDICTION_TRACKVALUECHANGESCOPE( context ) #define PREDICTION_TRACKVALUECHANGESCOPE_ENTITY( entity, context ) #define PREDICTION_STARTTRACKVALUE( context ) #define PREDICTION_ENDTRACKVALUE() #define PREDICTION_SPEWVALUECHANGES() #endif #endif #endif