Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/core/achievements.h
7471 views
1
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
3
4
#pragma once
5
6
#include "common/small_string.h"
7
#include "common/types.h"
8
9
#include <array>
10
#include <functional>
11
#include <mutex>
12
#include <optional>
13
#include <span>
14
#include <string>
15
#include <utility>
16
#include <vector>
17
18
class Error;
19
class ProgressCallback;
20
class StateWrapper;
21
class CDImage;
22
23
struct Settings;
24
25
namespace Achievements {
26
27
enum class LoginRequestReason
28
{
29
UserInitiated,
30
TokenInvalid,
31
};
32
33
inline constexpr size_t GAME_HASH_LENGTH = 16;
34
using GameHash = std::array<u8, GAME_HASH_LENGTH>;
35
36
struct HashDatabaseEntry
37
{
38
GameHash hash;
39
u32 game_id;
40
u32 num_achievements;
41
};
42
43
class ProgressDatabase
44
{
45
public:
46
struct Entry
47
{
48
u32 game_id;
49
u16 num_achievements_unlocked;
50
u16 num_hc_achievements_unlocked;
51
};
52
53
ProgressDatabase();
54
~ProgressDatabase();
55
56
bool Load(Error* error);
57
58
const Entry* LookupGame(u32 game_id) const;
59
60
private:
61
std::vector<Entry> m_entries;
62
};
63
64
/// Acquires the achievements lock. Must be held when accessing any achievement state from another thread.
65
std::unique_lock<std::recursive_mutex> GetLock();
66
67
/// Returns the achievements game hash for a given disc.
68
std::optional<GameHash> GetGameHash(CDImage* image);
69
std::optional<GameHash> GetGameHash(const std::string_view executable_name, std::span<const u8> executable_data);
70
71
/// Returns the number of achievements for a given hash.
72
const HashDatabaseEntry* LookupGameHash(const GameHash& hash);
73
74
/// Converts a game hash to a string for display. If the hash is nullopt, returns "[NO HASH]".
75
TinyString GameHashToString(const std::optional<GameHash>& hash);
76
77
/// Initializes the RetroAchievments client.
78
bool Initialize();
79
80
/// Updates achievements settings.
81
void UpdateSettings(const Settings& old_config);
82
83
/// Shuts down the RetroAchievements client.
84
void Shutdown();
85
86
/// Call to refresh the all-progress database.
87
bool RefreshAllProgressDatabase(ProgressCallback* progress, Error* error);
88
89
/// Called when the system is start. Engages hardcore mode if enabled.
90
void OnSystemStarting(CDImage* image, bool disable_hardcore_mode);
91
92
/// Called when the system is shutting down. If this returns false, the shutdown should be aborted.
93
void OnSystemDestroyed();
94
95
/// Called when the system is being reset. Resets the internal state of all achievement tracking.
96
void OnSystemReset();
97
98
/// Called when the system changes game.
99
void GameChanged(CDImage* image);
100
101
/// Called once a frame at vsync time on the CPU thread.
102
void FrameUpdate();
103
104
/// Called when the system is paused, because FrameUpdate() won't be getting called.
105
void IdleUpdate();
106
107
/// Returns true if idle updates are necessary (e.g. outstanding requests).
108
bool NeedsIdleUpdate();
109
110
/// Saves/loads state.
111
bool DoState(StateWrapper& sw);
112
113
/// Attempts to log in to RetroAchievements using the specified credentials.
114
/// If the login is successful, the token returned by the server will be saved.
115
bool Login(const char* username, const char* password, Error* error);
116
117
/// Logs out of RetroAchievements, clearing any credentials.
118
void Logout();
119
120
/// Forces hardcore mode off until next reset.
121
void DisableHardcoreMode(bool show_message, bool display_game_summary);
122
123
/// Prompts the user to disable hardcore mode. Invokes callback with result.
124
void ConfirmHardcoreModeDisableAsync(std::string_view trigger, std::function<void(bool)> callback);
125
126
/// Returns true if hardcore mode is active, and functionality should be restricted.
127
bool IsHardcoreModeActive();
128
129
/// RAIntegration only exists for Windows, so no point checking it on other platforms.
130
bool IsUsingRAIntegration();
131
bool IsRAIntegrationAvailable();
132
133
/// Returns true if the achievement system is active. Achievements can be active without a valid client.
134
bool IsActive();
135
136
/// Returns true if RetroAchievements game data has been loaded.
137
bool HasActiveGame();
138
139
/// Returns the RetroAchievements ID for the current game.
140
u32 GetGameID();
141
142
/// Returns true if the current game has any achievements or leaderboards.
143
bool HasAchievementsOrLeaderboards();
144
145
/// Returns true if the current game has any leaderboards.
146
bool HasAchievements();
147
148
/// Returns true if the current game has any leaderboards.
149
bool HasLeaderboards();
150
151
/// Returns true if the game supports rich presence.
152
bool HasRichPresence();
153
154
/// Returns the current rich presence string.
155
/// Should be called with the lock held.
156
const std::string& GetRichPresenceString();
157
158
/// Returns the URL for the current icon of the game
159
const std::string& GetGameIconURL();
160
161
/// Returns the path for the current icon of the game
162
const std::string& GetGameIconPath();
163
164
/// Returns the RetroAchievements title for the current game.
165
/// Should be called with the lock held.
166
const std::string& GetGameTitle();
167
168
/// Returns the path for the game that is current hashed/running.
169
const std::string& GetGamePath();
170
171
/// Returns true if the user has been successfully logged in.
172
bool IsLoggedIn();
173
174
/// Returns true if the user has been successfully logged in, or the request is in progress.
175
bool IsLoggedInOrLoggingIn();
176
177
/// Returns the logged-in user name.
178
const char* GetLoggedInUserName();
179
180
/// Returns the path to the user's profile avatar.
181
/// Should be called with the lock held.
182
const std::string& GetLoggedInUserBadgePath();
183
184
/// Returns a summary of the user's points.
185
/// Should be called with the lock held.
186
SmallString GetLoggedInUserPointsSummary();
187
188
/// Returns the path to the local cache for the specified badge name.
189
std::string GetGameBadgePath(std::string_view badge_name);
190
191
/// Downloads game icons from RetroAchievements for all games that have an achievements_game_id.
192
/// This fetches the game badge images that are normally downloaded when a game is opened.
193
bool DownloadGameIcons(ProgressCallback* progress, Error* error);
194
195
/// Returns 0 if pausing is allowed, otherwise the number of frames until pausing is allowed.
196
u32 GetPauseThrottleFrames();
197
198
/// Returns the number of unlocks that have not been synchronized with the server.
199
u32 GetPendingUnlockCount();
200
201
/// The name of the RetroAchievements icon, which can be used in notifications.
202
extern const char* const RA_LOGO_ICON_NAME;
203
204
} // namespace Achievements
205
206
/// Functions implemented in the frontend.
207
namespace Host {
208
209
/// Called if the big picture UI requests achievements login, or token login fails.
210
void OnAchievementsLoginRequested(Achievements::LoginRequestReason reason);
211
212
/// Called when achievements login completes.
213
void OnAchievementsLoginSuccess(const char* display_name, u32 points, u32 sc_points, u32 unread_messages);
214
215
/// Called when achievements login completes or they are disabled.
216
void OnAchievementsActiveChanged(bool active);
217
218
/// Called whenever hardcore mode is toggled.
219
void OnAchievementsHardcoreModeChanged(bool enabled);
220
221
#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION
222
223
/// Called when the RAIntegration menu changes.
224
void OnRAIntegrationMenuChanged();
225
226
#endif
227
228
} // namespace Host
229
230