You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
4.4 KiB
157 lines
4.4 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
|
|
#ifdef GAME_DLL |
|
|
|
#include "isaverestore.h" |
|
#include "saverestore_utlvector.h" |
|
#include "achievement_saverestore.h" |
|
#include "achievementmgr.h" |
|
#include "baseachievement.h" |
|
#include "utlmap.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
static short ACHIEVEMENT_SAVE_RESTORE_VERSION = 2; |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
class CAchievementSaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler |
|
{ |
|
public: |
|
const char *GetBlockName() |
|
{ |
|
return "Achievement"; |
|
} |
|
|
|
//--------------------------------- |
|
|
|
void Save( ISave *pSave ) |
|
{ |
|
CAchievementMgr *pAchievementMgr = dynamic_cast<CAchievementMgr *>( engine->GetAchievementMgr() ); |
|
if ( !pAchievementMgr ) |
|
return; |
|
|
|
// save global achievement mgr state to separate file if there have been any changes, so in case of a crash |
|
// the global state is consistent with last save game |
|
pAchievementMgr->SaveGlobalStateIfDirty( pSave->IsAsync() ); |
|
|
|
pSave->StartBlock( "Achievements" ); |
|
int iTotalAchievements = pAchievementMgr->GetAchievementCount(); |
|
short nSaveCount = 0; |
|
// count how many achievements should be saved. |
|
for ( int i = 0; i < iTotalAchievements; i++ ) |
|
{ |
|
IAchievement *pAchievement = pAchievementMgr->GetAchievementByIndex( i ); |
|
if ( pAchievement->ShouldSaveWithGame() ) |
|
{ |
|
nSaveCount++; |
|
} |
|
} |
|
// Write # of saved achievements |
|
pSave->WriteShort( &nSaveCount ); |
|
// Write out each achievement |
|
for ( int i = 0; i < iTotalAchievements; i++ ) |
|
{ |
|
IAchievement *pAchievement = pAchievementMgr->GetAchievementByIndex( i ); |
|
if ( pAchievement->ShouldSaveWithGame() ) |
|
{ |
|
CBaseAchievement *pBaseAchievement = dynamic_cast< CBaseAchievement * >( pAchievement ); |
|
if ( pBaseAchievement ) |
|
{ |
|
short iAchievementID = (short) pBaseAchievement->GetAchievementID(); |
|
// write the achievement ID |
|
pSave->WriteShort( &iAchievementID ); |
|
// write the achievement data |
|
pSave->WriteAll( pBaseAchievement, pBaseAchievement->GetDataDescMap() ); |
|
} |
|
} |
|
} |
|
pSave->EndBlock(); |
|
} |
|
|
|
//--------------------------------- |
|
|
|
void WriteSaveHeaders( ISave *pSave ) |
|
{ |
|
pSave->WriteShort( &ACHIEVEMENT_SAVE_RESTORE_VERSION ); |
|
} |
|
|
|
//--------------------------------- |
|
|
|
void ReadRestoreHeaders( IRestore *pRestore ) |
|
{ |
|
// No reason why any future version shouldn't try to retain backward compatability. The default here is to not do so. |
|
short version; |
|
pRestore->ReadShort( &version ); |
|
// only load if version matches and if we are loading a game, not a transition |
|
m_fDoLoad = ( ( version == ACHIEVEMENT_SAVE_RESTORE_VERSION ) && |
|
( ( MapLoad_LoadGame == gpGlobals->eLoadType ) || ( MapLoad_NewGame == gpGlobals->eLoadType ) ) |
|
); |
|
} |
|
|
|
//--------------------------------- |
|
|
|
void Restore( IRestore *pRestore, bool createPlayers ) |
|
{ |
|
CAchievementMgr *pAchievementMgr = dynamic_cast<CAchievementMgr *>( engine->GetAchievementMgr() ); |
|
if ( !pAchievementMgr ) |
|
return; |
|
|
|
if ( m_fDoLoad ) |
|
{ |
|
pAchievementMgr->PreRestoreSavedGame(); |
|
|
|
pRestore->StartBlock(); |
|
// read # of achievements |
|
int nSavedAchievements = pRestore->ReadShort(); |
|
|
|
while ( nSavedAchievements-- ) |
|
{ |
|
// read achievement ID |
|
int iAchievementID = pRestore->ReadShort(); |
|
// find the corresponding achievement object |
|
CBaseAchievement *pAchievement = pAchievementMgr->GetAchievementByID( iAchievementID ); |
|
Assert( pAchievement ); // It's a bug if we don't understand this achievement |
|
if ( pAchievement ) |
|
{ |
|
// read achievement data |
|
pRestore->ReadAll( pAchievement, pAchievement->GetDataDescMap() ); |
|
} |
|
else |
|
{ |
|
// if we don't recognize the achievement for some reason, read and discard the data and keep going |
|
CBaseAchievement ignored; |
|
pRestore->ReadAll( &ignored, ignored.GetDataDescMap() ); |
|
} |
|
} |
|
pRestore->EndBlock(); |
|
|
|
pAchievementMgr->PostRestoreSavedGame(); |
|
} |
|
} |
|
|
|
private: |
|
bool m_fDoLoad; |
|
}; |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
CAchievementSaveRestoreBlockHandler g_AchievementSaveRestoreBlockHandler; |
|
|
|
//------------------------------------- |
|
|
|
ISaveRestoreBlockHandler *GetAchievementSaveRestoreBlockHandler() |
|
{ |
|
return &g_AchievementSaveRestoreBlockHandler; |
|
} |
|
|
|
|
|
#endif // GAME_DLL
|