340 lines
12 KiB
C++
340 lines
12 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================//
|
|
|
|
#ifndef PREDICTIONCOPY_H
|
|
#define PREDICTIONCOPY_H
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
#include <memory.h>
|
|
#include "datamap.h"
|
|
#include "ehandle.h"
|
|
#include "tier1/utlstring.h"
|
|
|
|
#if defined(CLIENT_DLL)
|
|
class C_BaseEntity;
|
|
typedef CHandle<C_BaseEntity> EHANDLE;
|
|
|
|
#if defined(_DEBUG)
|
|
// #define COPY_CHECK_STRESSTEST
|
|
class IGameSystem;
|
|
IGameSystem *GetPredictionCopyTester(void);
|
|
#endif
|
|
|
|
#else
|
|
class CBaseEntity;
|
|
typedef CHandle<CBaseEntity> 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); // Copy an int
|
|
void CopyBool(difftype_t dt, bool *outvalue, const bool *invalue,
|
|
int count); // Copy a bool
|
|
void CopyFloat(difftype_t dt, float *outvalue, const float *invalue,
|
|
int count); // Copy a float
|
|
void CopyString(difftype_t dt, char *outstring,
|
|
const char *instring); // Copy a null-terminated string
|
|
void CopyVector(difftype_t dt, Vector &outValue,
|
|
const Vector &inValue); // Copy a vector
|
|
void CopyVector(difftype_t dt, Vector *outValue, const Vector *inValue,
|
|
int count); // Copy a vector array
|
|
void CopyQuaternion(difftype_t dt, Quaternion &outValue,
|
|
const Quaternion &inValue); // Copy a quaternion
|
|
void CopyQuaternion(difftype_t dt, Quaternion *outValue,
|
|
const Quaternion *inValue,
|
|
int count); // Copy a quaternion array
|
|
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) // Copy a binary data block
|
|
{
|
|
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); // Compare an int
|
|
difftype_t CompareBool(bool *outvalue, const bool *invalue,
|
|
int count); // Compare a bool
|
|
difftype_t CompareFloat(float *outvalue, const float *invalue,
|
|
int count); // Compare a float
|
|
difftype_t CompareData(int size, char *outdata,
|
|
const char *indata); // Compare a binary data block
|
|
difftype_t CompareString(
|
|
char *outstring,
|
|
const char *instring); // Compare a null-terminated string
|
|
difftype_t CompareVector(Vector &outValue,
|
|
const Vector &inValue); // Compare a vector
|
|
difftype_t CompareVector(Vector *outValue, const Vector *inValue,
|
|
int count); // Compare a vector array
|
|
difftype_t CompareQuaternion(
|
|
Quaternion &outValue,
|
|
const Quaternion &inValue); // Compare a Quaternion
|
|
difftype_t CompareQuaternion(Quaternion *outValue,
|
|
const Quaternion *inValue,
|
|
int count); // Compare a Quaternion array
|
|
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); // Compare an int
|
|
void DescribeBool(difftype_t dt, bool *outvalue, const bool *invalue,
|
|
int count); // Compare a bool
|
|
void DescribeFloat(difftype_t dt, float *outvalue, const float *invalue,
|
|
int count); // Compare a float
|
|
void DescribeData(difftype_t dt, int size, char *outdata,
|
|
const char *indata); // Compare a binary data block
|
|
void DescribeString(
|
|
difftype_t dt, char *outstring,
|
|
const char *instring); // Compare a null-terminated string
|
|
void DescribeVector(difftype_t dt, Vector &outValue,
|
|
const Vector &inValue); // Compare a vector
|
|
void DescribeVector(difftype_t dt, Vector *outValue, const Vector *inValue,
|
|
int count); // Compare a vector array
|
|
void DescribeQuaternion(difftype_t dt, Quaternion &outValue,
|
|
const Quaternion &inValue); // Compare a Quaternion
|
|
void DescribeQuaternion(difftype_t dt, Quaternion *outValue,
|
|
const Quaternion *inValue,
|
|
int count); // Compare a Quaternion array
|
|
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); // Compare an int
|
|
void WatchBool(difftype_t dt, bool *outvalue, const bool *invalue,
|
|
int count); // Compare a bool
|
|
void WatchFloat(difftype_t dt, float *outvalue, const float *invalue,
|
|
int count); // Compare a float
|
|
void WatchData(difftype_t dt, int size, char *outdata,
|
|
const char *indata); // Compare a binary data block
|
|
void WatchString(difftype_t dt, char *outstring,
|
|
const char *instring); // Compare a null-terminated string
|
|
void WatchVector(difftype_t dt, Vector &outValue,
|
|
const Vector &inValue); // Compare a vector
|
|
void WatchVector(difftype_t dt, Vector *outValue, const Vector *inValue,
|
|
int count); // Compare a vector array
|
|
void WatchQuaternion(difftype_t dt, Quaternion &outValue,
|
|
const Quaternion &inValue); // Compare a Quaternion
|
|
void WatchQuaternion(difftype_t dt, Quaternion *outValue,
|
|
const Quaternion *inValue,
|
|
int count); // Compare a Quaternion array
|
|
void WatchEHandle(difftype_t dt, EHANDLE *outvalue, EHANDLE const *invalue,
|
|
int count);
|
|
|
|
// Report function
|
|
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);
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Simply dumps all data fields in object
|
|
//-----------------------------------------------------------------------------
|
|
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,
|
|
};
|
|
|
|
// Returns field size
|
|
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;
|
|
// First 128 bytes of data is all we will consider
|
|
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);
|
|
}
|
|
|
|
// Only calls Start/End if passed in entity matches entity to track
|
|
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 // !CLIENT_DLL
|
|
#endif // PREDICTIONCOPY_H
|