Skip to content

Commit 92b7cb9

Browse files
committed
Achievements: Prefetch next achievement badge on unlock/start
1 parent be8f38b commit 92b7cb9

File tree

1 file changed

+56
-2
lines changed

1 file changed

+56
-2
lines changed

src/core/achievements.cpp

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ static bool SaveStateToBuffer(std::span<u8> data);
135135
static std::string GetImageURL(const char* image_name, u32 type);
136136
static std::string GetLocalImagePath(const std::string_view image_name, u32 type);
137137
static void DownloadImage(std::string url, std::string cache_path);
138+
static void PrefetchNextAchievementBadge();
139+
static void PrefetchNextAchievementBadge(const rc_client_achievement_t* const last_cheevo);
138140

139141
static TinyString DecryptLoginToken(std::string_view encrypted_token, std::string_view username);
140142
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)
458460
s_state.http_downloader->CreateRequest(std::move(url), std::move(callback));
459461
}
460462

463+
void Achievements::PrefetchNextAchievementBadge()
464+
{
465+
if (!HasAchievements())
466+
return;
467+
468+
// Find most recent unlock.
469+
rc_client_achievement_list_t* const achievements =
470+
rc_client_create_achievement_list(Achievements::GetClient(), RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE_AND_UNOFFICIAL,
471+
RC_CLIENT_ACHIEVEMENT_LIST_GROUPING_PROGRESS);
472+
const rc_client_achievement_t* most_recent_unlock = nullptr;
473+
for (u32 i = 0; i < achievements->num_buckets; i++)
474+
{
475+
const rc_client_achievement_bucket_t& bucket = achievements->buckets[i];
476+
if (bucket.bucket_type != RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED &&
477+
bucket.bucket_type != RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED)
478+
{
479+
continue;
480+
}
481+
482+
for (u32 j = 0; j < bucket.num_achievements; j++)
483+
{
484+
const rc_client_achievement_t* const cheevo = bucket.achievements[j];
485+
if (!most_recent_unlock || cheevo->unlock_time > most_recent_unlock->unlock_time)
486+
most_recent_unlock = cheevo;
487+
}
488+
}
489+
rc_client_destroy_achievement_list(achievements);
490+
491+
if (most_recent_unlock)
492+
PrefetchNextAchievementBadge(most_recent_unlock);
493+
}
494+
495+
void Achievements::PrefetchNextAchievementBadge(const rc_client_achievement_t* const last_cheevo)
496+
{
497+
// Precache badge for the likely next achievement to avoid the badge load time.
498+
const rc_client_achievement_t* const next_cheevo =
499+
rc_client_get_next_achievement_info(s_state.client, last_cheevo, RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED);
500+
if (!next_cheevo)
501+
return;
502+
503+
VERBOSE_LOG("Prefetching badge for likely next achievement '{}' ({})", next_cheevo->title, next_cheevo->badge_url);
504+
GetAchievementBadgePath(next_cheevo, false);
505+
}
506+
461507
bool Achievements::IsActive()
462508
{
463509
return (s_state.client != nullptr);
@@ -1248,6 +1294,7 @@ void Achievements::ClientLoadGameCallback(int result, const char* error_message,
12481294

12491295
// update progress database on first load, in case it was played on another PC
12501296
UpdateGameSummary(true);
1297+
PrefetchNextAchievementBadge();
12511298

12521299
// needed for notifications
12531300
SoundEffectManager::EnsureInitialized();
@@ -1367,7 +1414,7 @@ void Achievements::HandleResetEvent(const rc_client_event_t* event)
13671414

13681415
void Achievements::HandleUnlockEvent(const rc_client_event_t* event)
13691416
{
1370-
const rc_client_achievement_t* cheevo = event->achievement;
1417+
const rc_client_achievement_t* const cheevo = event->achievement;
13711418
DebugAssert(cheevo);
13721419

13731420
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)
13911438
std::move(title), std::string(cheevo->description), std::move(note),
13921439
(cheevo->points > 0) ? FullscreenUI::AchievementNotificationNoteType::Text :
13931440
FullscreenUI::AchievementNotificationNoteType::None);
1441+
1442+
PrefetchNextAchievementBadge(cheevo);
13941443
}
13951444

13961445
if (g_settings.achievements_sound_effects)
@@ -1926,9 +1975,14 @@ std::string Achievements::GetAchievementBadgePath(const rc_client_achievement_t*
19261975
url = std::string(url_ptr);
19271976

19281977
if (url.empty()) [[unlikely]]
1929-
ReportFmtError("Acheivement {} with badge name {} has no badge URL", achievement->id, achievement->badge_name);
1978+
{
1979+
ReportFmtError("Achievement {} with badge name {} has no badge URL", achievement->id, achievement->badge_name);
1980+
}
19301981
else
1982+
{
1983+
DEV_LOG("Downloading badge for achievement {} from URL: {}", achievement->id, url);
19311984
DownloadImage(std::string(url), path);
1985+
}
19321986
}
19331987

19341988
return path;

0 commit comments

Comments
 (0)