aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/shared/achievement_saverestore.cpp
blob: b9de1e2d793c24c43207efd6b44fc7c95e5c390e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//========= 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