source-engine/game/shared/achievement_saverestore.cpp
2023-10-03 17:23:56 +03:00

161 lines
4.7 KiB
C++

//========= Copyright © 1996-2005, 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->StartBlock( "Achievements" );
int iTotalAchievements = pAchievementMgr->GetAchievementCount();
short nSaveCount = 0;
// count how many achievements should be saved.
for ( int i = 0; i < iTotalAchievements; i++ )
{
// We only save games in SP games so the assumption of SINGLE_PLAYER_SLOT is valid
IAchievement *pAchievement = pAchievementMgr->GetAchievementByIndex( i, SINGLE_PLAYER_SLOT );
if ( pAchievement->ShouldSaveWithGame() )
{
nSaveCount++;
}
}
// Write # of saved achievements
pSave->WriteShort( &nSaveCount );
// Write out each achievement
for ( int i = 0; i < iTotalAchievements; i++ )
{
// We only save games in SP games so the assumption of SINGLE_PLAYER_SLOT is valid
IAchievement *pAchievement = pAchievementMgr->GetAchievementByIndex( i, SINGLE_PLAYER_SLOT );
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
// We only save games in SP games so the assumption of SINGLE_PLAYER_SLOT is valid
CBaseAchievement *pAchievement = pAchievementMgr->GetAchievementByID( iAchievementID, SINGLE_PLAYER_SLOT );
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