mirror of
https://github.com/stenzek/duckstation.git
synced 2026-07-08 17:46:19 +00:00
Achievements: Prefetch next achievement badge on unlock/start
This commit is contained in:
@@ -135,6 +135,8 @@ static bool SaveStateToBuffer(std::span<u8> data);
|
||||
static std::string GetImageURL(const char* image_name, u32 type);
|
||||
static std::string GetLocalImagePath(const std::string_view image_name, u32 type);
|
||||
static void DownloadImage(std::string url, std::string cache_path);
|
||||
static void PrefetchNextAchievementBadge();
|
||||
static void PrefetchNextAchievementBadge(const rc_client_achievement_t* const last_cheevo);
|
||||
|
||||
static TinyString DecryptLoginToken(std::string_view encrypted_token, std::string_view username);
|
||||
static TinyString EncryptLoginToken(std::string_view token, std::string_view username);
|
||||
@@ -458,6 +460,50 @@ void Achievements::DownloadImage(std::string url, std::string cache_path)
|
||||
s_state.http_downloader->CreateRequest(std::move(url), std::move(callback));
|
||||
}
|
||||
|
||||
void Achievements::PrefetchNextAchievementBadge()
|
||||
{
|
||||
if (!HasAchievements())
|
||||
return;
|
||||
|
||||
// Find most recent unlock.
|
||||
rc_client_achievement_list_t* const achievements =
|
||||
rc_client_create_achievement_list(Achievements::GetClient(), RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE_AND_UNOFFICIAL,
|
||||
RC_CLIENT_ACHIEVEMENT_LIST_GROUPING_PROGRESS);
|
||||
const rc_client_achievement_t* most_recent_unlock = nullptr;
|
||||
for (u32 i = 0; i < achievements->num_buckets; i++)
|
||||
{
|
||||
const rc_client_achievement_bucket_t& bucket = achievements->buckets[i];
|
||||
if (bucket.bucket_type != RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED &&
|
||||
bucket.bucket_type != RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (u32 j = 0; j < bucket.num_achievements; j++)
|
||||
{
|
||||
const rc_client_achievement_t* const cheevo = bucket.achievements[j];
|
||||
if (!most_recent_unlock || cheevo->unlock_time > most_recent_unlock->unlock_time)
|
||||
most_recent_unlock = cheevo;
|
||||
}
|
||||
}
|
||||
rc_client_destroy_achievement_list(achievements);
|
||||
|
||||
if (most_recent_unlock)
|
||||
PrefetchNextAchievementBadge(most_recent_unlock);
|
||||
}
|
||||
|
||||
void Achievements::PrefetchNextAchievementBadge(const rc_client_achievement_t* const last_cheevo)
|
||||
{
|
||||
// Precache badge for the likely next achievement to avoid the badge load time.
|
||||
const rc_client_achievement_t* const next_cheevo =
|
||||
rc_client_get_next_achievement_info(s_state.client, last_cheevo, RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED);
|
||||
if (!next_cheevo)
|
||||
return;
|
||||
|
||||
VERBOSE_LOG("Prefetching badge for likely next achievement '{}' ({})", next_cheevo->title, next_cheevo->badge_url);
|
||||
GetAchievementBadgePath(next_cheevo, false);
|
||||
}
|
||||
|
||||
bool Achievements::IsActive()
|
||||
{
|
||||
return (s_state.client != nullptr);
|
||||
@@ -1248,6 +1294,7 @@ void Achievements::ClientLoadGameCallback(int result, const char* error_message,
|
||||
|
||||
// update progress database on first load, in case it was played on another PC
|
||||
UpdateGameSummary(true);
|
||||
PrefetchNextAchievementBadge();
|
||||
|
||||
// needed for notifications
|
||||
SoundEffectManager::EnsureInitialized();
|
||||
@@ -1367,7 +1414,7 @@ void Achievements::HandleResetEvent(const rc_client_event_t* event)
|
||||
|
||||
void Achievements::HandleUnlockEvent(const rc_client_event_t* event)
|
||||
{
|
||||
const rc_client_achievement_t* cheevo = event->achievement;
|
||||
const rc_client_achievement_t* const cheevo = event->achievement;
|
||||
DebugAssert(cheevo);
|
||||
|
||||
INFO_LOG("Achievement {} ({}) for game {} unlocked", cheevo->id, cheevo->title, s_state.game_id);
|
||||
@@ -1391,6 +1438,8 @@ void Achievements::HandleUnlockEvent(const rc_client_event_t* event)
|
||||
std::move(title), std::string(cheevo->description), std::move(note),
|
||||
(cheevo->points > 0) ? FullscreenUI::AchievementNotificationNoteType::Text :
|
||||
FullscreenUI::AchievementNotificationNoteType::None);
|
||||
|
||||
PrefetchNextAchievementBadge(cheevo);
|
||||
}
|
||||
|
||||
if (g_settings.achievements_sound_effects)
|
||||
@@ -1926,9 +1975,14 @@ std::string Achievements::GetAchievementBadgePath(const rc_client_achievement_t*
|
||||
url = std::string(url_ptr);
|
||||
|
||||
if (url.empty()) [[unlikely]]
|
||||
ReportFmtError("Acheivement {} with badge name {} has no badge URL", achievement->id, achievement->badge_name);
|
||||
{
|
||||
ReportFmtError("Achievement {} with badge name {} has no badge URL", achievement->id, achievement->badge_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEV_LOG("Downloading badge for achievement {} from URL: {}", achievement->id, url);
|
||||
DownloadImage(std::string(url), path);
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
|
||||
Reference in New Issue
Block a user