//========= Copyright © 1996-2005, 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 "isaverestore.h" #include "utlvector.h" #include "filesystem.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, const int *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 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, void **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; } virtual int ScanAheadForHammerID(); virtual void SkipEntityData(); 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 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 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