This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
2020-08-04 13:13:01 -04:00

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