413 lines
15 KiB
C++
413 lines
15 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose: Helper classes and functions for the save/restore system. These
|
|
// classes are internally structured to distinguish simple
|
|
// from
|
|
// complex types.
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================//
|
|
|
|
#ifndef SAVERESTORE_H
|
|
#define SAVERESTORE_H
|
|
|
|
#include "filesystem.h"
|
|
#include "isaverestore.h"
|
|
#include "utlvector.h"
|
|
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
//-------------------------------------
|
|
|
|
class CSaveRestoreData;
|
|
class CSaveRestoreSegment;
|
|
class CGameSaveRestoreInfo;
|
|
struct typedescription_t;
|
|
struct edict_t;
|
|
struct datamap_t;
|
|
class CBaseEntity;
|
|
struct interval_t;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// CSave
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
class CSave : public ISave {
|
|
public:
|
|
CSave(CSaveRestoreData *pdata);
|
|
|
|
//---------------------------------
|
|
// Logging
|
|
void StartLogging(const char *pszLogName);
|
|
void EndLogging(void);
|
|
|
|
//---------------------------------
|
|
bool IsAsync();
|
|
|
|
//---------------------------------
|
|
|
|
int GetWritePos() const;
|
|
void SetWritePos(int pos);
|
|
|
|
//---------------------------------
|
|
// Datamap based writing
|
|
//
|
|
|
|
int WriteAll(const void *pLeafObject, datamap_t *pLeafMap) {
|
|
return DoWriteAll(pLeafObject, pLeafMap, pLeafMap);
|
|
}
|
|
|
|
int WriteFields(const char *pname, const void *pBaseData, datamap_t *pMap,
|
|
typedescription_t *pFields, int fieldCount);
|
|
|
|
//---------------------------------
|
|
// Block support
|
|
//
|
|
|
|
virtual void StartBlock(const char *pszBlockName);
|
|
virtual void StartBlock();
|
|
virtual void EndBlock();
|
|
|
|
//---------------------------------
|
|
// Primitive types
|
|
//
|
|
|
|
void WriteShort(const short *value, int count = 1);
|
|
void WriteInt(const int *value, int count = 1); // Save an int
|
|
void WriteBool(const bool *value, int count = 1); // Save a bool
|
|
void WriteFloat(const float *value, int count = 1); // Save a float
|
|
void WriteData(const char *pdata, int size); // Save a binary data block
|
|
void WriteString(const char *pstring); // Save a null-terminated string
|
|
void WriteString(
|
|
const string_t *stringId,
|
|
int count = 1); // Save a null-terminated string (engine string)
|
|
void WriteVector(const Vector &value); // Save a vector
|
|
void WriteVector(const Vector *value,
|
|
int count = 1); // Save a vector array
|
|
void WriteQuaternion(const Quaternion &value); // Save a Quaternion
|
|
void WriteQuaternion(const Quaternion *value,
|
|
int count = 1); // Save a Quaternion array
|
|
void WriteVMatrix(const VMatrix *value,
|
|
int count = 1); // Save a vmatrix array
|
|
|
|
// Note: All of the following will write out both a header and the data. On
|
|
// restore, this needs to be cracked
|
|
void WriteShort(const char *pname, const short *value, int count = 1);
|
|
void WriteInt(const char *pname, const int *value,
|
|
int count = 1); // Save an int
|
|
void WriteBool(const char *pname, const bool *value,
|
|
int count = 1); // Save a bool
|
|
void WriteFloat(const char *pname, const float *value,
|
|
int count = 1); // Save a float
|
|
void WriteData(const char *pname, int size,
|
|
const char *pdata); // Save a binary data block
|
|
void WriteString(const char *pname,
|
|
const char *pstring); // Save a null-terminated string
|
|
void WriteString(
|
|
const char *pname, const string_t *stringId,
|
|
int count = 1); // Save a null-terminated string (engine string)
|
|
void WriteVector(const char *pname, const Vector &value); // Save a vector
|
|
void WriteVector(const char *pname, const Vector *value,
|
|
int count = 1); // Save a vector array
|
|
void WriteQuaternion(const char *pname,
|
|
const Quaternion &value); // Save a Quaternion
|
|
void WriteQuaternion(const char *pname, const Quaternion *value,
|
|
int count = 1); // Save a Quaternion array
|
|
void WriteVMatrix(const char *pname, const VMatrix *value, int count = 1);
|
|
//---------------------------------
|
|
// Game types
|
|
//
|
|
|
|
void WriteTime(const char *pname, const float *value,
|
|
int count = 1); // Save a float (timevalue)
|
|
void WriteTick(const char *pname, const int *value,
|
|
int count = 1); // Save a int (timevalue)
|
|
void WritePositionVector(
|
|
const char *pname,
|
|
const Vector &value); // Offset for landmark if necessary
|
|
void WritePositionVector(const char *pname, const Vector *value,
|
|
int count = 1); // array of pos vectors
|
|
void WriteFunction(datamap_t *pMap, const char *pname, inputfunc_t **value,
|
|
int count = 1); // Save a function pointer
|
|
|
|
void WriteEntityPtr(const char *pname, CBaseEntity **ppEntity,
|
|
int count = 1);
|
|
void WriteEdictPtr(const char *pname, edict_t **ppEdict, int count = 1);
|
|
void WriteEHandle(const char *pname, const EHANDLE *pEHandle,
|
|
int count = 1);
|
|
|
|
virtual void WriteTime(const float *value,
|
|
int count = 1); // Save a float (timevalue)
|
|
virtual void WriteTick(const int *value,
|
|
int count = 1); // Save a int (timevalue)
|
|
virtual void WritePositionVector(
|
|
const Vector &value); // Offset for landmark if necessary
|
|
virtual void WritePositionVector(const Vector *value,
|
|
int count = 1); // array of pos vectors
|
|
|
|
virtual void WriteEntityPtr(CBaseEntity **ppEntity, int count = 1);
|
|
virtual void WriteEdictPtr(edict_t **ppEdict, int count = 1);
|
|
virtual void WriteEHandle(const EHANDLE *pEHandle, int count = 1);
|
|
void WriteVMatrixWorldspace(const char *pname, const VMatrix *value,
|
|
int count = 1); // Save a vmatrix array
|
|
void WriteVMatrixWorldspace(const VMatrix *value,
|
|
int count = 1); // Save a vmatrix array
|
|
void WriteMatrix3x4Worldspace(const matrix3x4_t *value, int count);
|
|
void WriteMatrix3x4Worldspace(const char *pname, const matrix3x4_t *value,
|
|
int count);
|
|
|
|
void WriteInterval(const interval_t *value,
|
|
int count = 1); // Save an interval
|
|
void WriteInterval(const char *pname, const interval_t *value,
|
|
int count = 1);
|
|
|
|
//---------------------------------
|
|
|
|
int EntityIndex(const CBaseEntity *pEntity);
|
|
int EntityFlagsSet(int entityIndex, int flags);
|
|
|
|
CGameSaveRestoreInfo *GetGameSaveRestoreInfo() { return m_pGameInfo; }
|
|
|
|
private:
|
|
//---------------------------------
|
|
bool IsLogging(void);
|
|
void Log(const char *pName, fieldtype_t fieldType, void *value, int count);
|
|
|
|
//---------------------------------
|
|
|
|
void BufferField(const char *pname, int size, const char *pdata);
|
|
void BufferData(const char *pdata, int size);
|
|
void WriteHeader(const char *pname, int size);
|
|
|
|
int DoWriteAll(const void *pLeafObject, datamap_t *pLeafMap,
|
|
datamap_t *pCurMap);
|
|
bool WriteField(const char *pname, void *pData, datamap_t *pRootMap,
|
|
typedescription_t *pField);
|
|
|
|
bool WriteBasicField(const char *pname, void *pData, datamap_t *pRootMap,
|
|
typedescription_t *pField);
|
|
|
|
int DataEmpty(const char *pdata, int size);
|
|
void BufferString(char *pdata, int len);
|
|
|
|
int CountFieldsToSave(const void *pBaseData, typedescription_t *pFields,
|
|
int fieldCount);
|
|
bool ShouldSaveField(const void *pData, typedescription_t *pField);
|
|
|
|
//---------------------------------
|
|
// Game info methods
|
|
//
|
|
|
|
bool WriteGameField(const char *pname, void *pData, datamap_t *pRootMap,
|
|
typedescription_t *pField);
|
|
int EntityIndex(const edict_t *pentLookup);
|
|
|
|
//---------------------------------
|
|
|
|
CUtlVector<int> m_BlockStartStack;
|
|
|
|
// Stream data
|
|
CSaveRestoreSegment *m_pData;
|
|
|
|
// Game data
|
|
CGameSaveRestoreInfo *m_pGameInfo;
|
|
|
|
FileHandle_t m_hLogFile;
|
|
bool m_bAsync;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// CRestore
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
class CRestore : public IRestore {
|
|
public:
|
|
CRestore(CSaveRestoreData *pdata);
|
|
|
|
int GetReadPos() const;
|
|
void SetReadPos(int pos);
|
|
|
|
//---------------------------------
|
|
// Datamap based reading
|
|
//
|
|
|
|
int ReadAll(void *pLeafObject, datamap_t *pLeafMap) {
|
|
return DoReadAll(pLeafObject, pLeafMap, pLeafMap);
|
|
}
|
|
|
|
int ReadFields(const char *pname, void *pBaseData, datamap_t *pMap,
|
|
typedescription_t *pFields, int fieldCount);
|
|
void EmptyFields(void *pBaseData, typedescription_t *pFields,
|
|
int fieldCount);
|
|
|
|
//---------------------------------
|
|
// Block support
|
|
//
|
|
|
|
virtual void StartBlock(SaveRestoreRecordHeader_t *pHeader);
|
|
virtual void StartBlock(char szBlockName[SIZE_BLOCK_NAME_BUF]);
|
|
virtual void StartBlock();
|
|
virtual void EndBlock();
|
|
|
|
//---------------------------------
|
|
// Field header cracking
|
|
//
|
|
|
|
void ReadHeader(SaveRestoreRecordHeader_t *pheader);
|
|
int SkipHeader() {
|
|
SaveRestoreRecordHeader_t header;
|
|
ReadHeader(&header);
|
|
return header.size;
|
|
}
|
|
const char *StringFromHeaderSymbol(int symbol);
|
|
|
|
//---------------------------------
|
|
// Primitive types
|
|
//
|
|
|
|
short ReadShort(void);
|
|
int ReadShort(short *pValue, int count = 1, int nBytesAvailable = 0);
|
|
int ReadInt(int *pValue, int count = 1, int nBytesAvailable = 0);
|
|
int ReadInt(void);
|
|
int ReadBool(bool *pValue, int count = 1, int nBytesAvailable = 0);
|
|
int ReadFloat(float *pValue, int count = 1, int nBytesAvailable = 0);
|
|
int ReadData(char *pData, int size, int nBytesAvailable);
|
|
void ReadString(char *pDest, int nSizeDest,
|
|
int nBytesAvailable); // A null-terminated string
|
|
int ReadString(string_t *pString, int count = 1, int nBytesAvailable = 0);
|
|
int ReadVector(Vector *pValue);
|
|
int ReadVector(Vector *pValue, int count = 1, int nBytesAvailable = 0);
|
|
int ReadQuaternion(Quaternion *pValue);
|
|
int ReadQuaternion(Quaternion *pValue, int count = 1,
|
|
int nBytesAvailable = 0);
|
|
int ReadVMatrix(VMatrix *pValue, int count = 1, int nBytesAvailable = 0);
|
|
|
|
//---------------------------------
|
|
// Game types
|
|
//
|
|
|
|
int ReadTime(float *pValue, int count = 1, int nBytesAvailable = 0);
|
|
int ReadTick(int *pValue, int count = 1, int nBytesAvailable = 0);
|
|
int ReadPositionVector(Vector *pValue);
|
|
int ReadPositionVector(Vector *pValue, int count = 1,
|
|
int nBytesAvailable = 0);
|
|
int ReadFunction(datamap_t *pMap, inputfunc_t **pValue, int count = 1,
|
|
int nBytesAvailable = 0);
|
|
|
|
int ReadEntityPtr(CBaseEntity **ppEntity, int count = 1,
|
|
int nBytesAvailable = 0);
|
|
int ReadEdictPtr(edict_t **ppEdict, int count = 1, int nBytesAvailable = 0);
|
|
int ReadEHandle(EHANDLE *pEHandle, int count = 1, int nBytesAvailable = 0);
|
|
int ReadVMatrixWorldspace(VMatrix *pValue, int count = 1,
|
|
int nBytesAvailable = 0);
|
|
int ReadMatrix3x4Worldspace(matrix3x4_t *pValue, int nElems = 1,
|
|
int nBytesAvailable = 0);
|
|
int ReadInterval(interval_t *interval, int count = 1,
|
|
int nBytesAvailable = 0);
|
|
|
|
//---------------------------------
|
|
|
|
void SetGlobalMode(int global) { m_global = global; }
|
|
void PrecacheMode(bool mode) { m_precache = mode; }
|
|
bool GetPrecacheMode(void) { return m_precache; }
|
|
|
|
CGameSaveRestoreInfo *GetGameSaveRestoreInfo() { return m_pGameInfo; }
|
|
|
|
private:
|
|
//---------------------------------
|
|
// Read primitives
|
|
//
|
|
|
|
char *BufferPointer(void);
|
|
void BufferSkipBytes(int bytes);
|
|
|
|
int DoReadAll(void *pLeafObject, datamap_t *pLeafMap, datamap_t *pCurMap);
|
|
|
|
typedescription_t *FindField(const char *pszFieldName,
|
|
typedescription_t *pFields, int fieldCount,
|
|
int *pIterator);
|
|
void ReadField(const SaveRestoreRecordHeader_t &header, void *pDest,
|
|
datamap_t *pRootMap, typedescription_t *pField);
|
|
|
|
void ReadBasicField(const SaveRestoreRecordHeader_t &header, void *pDest,
|
|
datamap_t *pRootMap, typedescription_t *pField);
|
|
|
|
void BufferReadBytes(char *pOutput, int size);
|
|
|
|
template <typename T>
|
|
int ReadSimple(
|
|
T *pValue, int nElems,
|
|
int nBytesAvailable) // must be inline in class to keep MSVS happy
|
|
{
|
|
int desired = nElems * sizeof(T);
|
|
int actual;
|
|
|
|
if (nBytesAvailable == 0)
|
|
actual = desired;
|
|
else {
|
|
Assert(nBytesAvailable % sizeof(T) == 0);
|
|
actual = MIN(desired, nBytesAvailable);
|
|
}
|
|
|
|
BufferReadBytes((char *)pValue, actual);
|
|
|
|
if (actual < nBytesAvailable) BufferSkipBytes(nBytesAvailable - actual);
|
|
|
|
return (actual / sizeof(T));
|
|
}
|
|
|
|
bool ShouldReadField(typedescription_t *pField);
|
|
bool ShouldEmptyField(typedescription_t *pField);
|
|
|
|
//---------------------------------
|
|
// Game info methods
|
|
//
|
|
CBaseEntity *EntityFromIndex(int entityIndex);
|
|
void ReadGameField(const SaveRestoreRecordHeader_t &header, void *pDest,
|
|
datamap_t *pRootMap, typedescription_t *pField);
|
|
|
|
//---------------------------------
|
|
|
|
CUtlVector<int> m_BlockEndStack;
|
|
|
|
// Stream data
|
|
CSaveRestoreSegment *m_pData;
|
|
|
|
// Game data
|
|
CGameSaveRestoreInfo *m_pGameInfo;
|
|
int m_global; // Restoring a global entity?
|
|
bool m_precache;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// An interface passed into the OnSave method of all entities
|
|
//-----------------------------------------------------------------------------
|
|
abstract_class IEntitySaveUtils {
|
|
public:
|
|
// Adds a level transition save dependency
|
|
virtual void AddLevelTransitionSaveDependency(CBaseEntity * pEntity1,
|
|
CBaseEntity * pEntity2) = 0;
|
|
|
|
// Gets the # of dependencies for a particular entity
|
|
virtual int GetEntityDependencyCount(CBaseEntity * pEntity) = 0;
|
|
|
|
// Gets all dependencies for a particular entity
|
|
virtual int GetEntityDependencies(CBaseEntity * pEntity, int nCount,
|
|
CBaseEntity **ppEntList) = 0;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Singleton interface
|
|
//-----------------------------------------------------------------------------
|
|
IEntitySaveUtils *GetEntitySaveUtils();
|
|
|
|
//=============================================================================
|
|
|
|
#endif // SAVERESTORE_H
|