From 6f3a608e929d2973a5766197d4a5aae1c8f4fc06 Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Sat, 24 Feb 2024 12:00:09 -0500 Subject: [PATCH] Add active leaderboard tracker to achievement manager The active leaderboard data (leaderboards currently being attempted, which get displayed on screen) is now tracked. When a leaderboard is started its value is added to a vector (sorted by start frame). There are a separate set of client events specifically to handle leaderboard trackers, that are used to populate and manage this vector. The top portion of this vector (by RetroAchievement standards, the first four items) is exposed to be displayed on screen. --- Source/Core/Core/AchievementManager.cpp | 47 +++++++++++++++++++++++++ Source/Core/Core/AchievementManager.h | 6 ++++ 2 files changed, 53 insertions(+) diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index d9987015e1..f3e4b41ba6 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -402,6 +402,16 @@ const AchievementManager::NamedIconMap& AchievementManager::GetChallengeIcons() return m_active_challenges; } +std::vector AchievementManager::GetActiveLeaderboards() const +{ + std::vector display_values; + for (u32 ix = 0; ix < MAX_DISPLAYED_LBOARDS && ix < m_active_leaderboards.size(); ix++) + { + display_values.push_back(std::string(m_active_leaderboards[ix].display)); + } + return display_values; +} + void AchievementManager::CloseGame() { { @@ -409,6 +419,7 @@ void AchievementManager::CloseGame() if (rc_client_get_game_info(m_client)) { m_active_challenges.clear(); + m_active_leaderboards.clear(); m_game_badge.name.clear(); m_unlocked_badges.clear(); m_locked_badges.clear(); @@ -827,6 +838,33 @@ void AchievementManager::HandleLeaderboardSubmittedEvent(const rc_client_event_t OSD::Duration::VERY_LONG, OSD::Color::YELLOW); } +void AchievementManager::HandleLeaderboardTrackerUpdateEvent(const rc_client_event_t* client_event) +{ + auto& active_leaderboards = AchievementManager::GetInstance().m_active_leaderboards; + for (auto& leaderboard : active_leaderboards) + { + if (leaderboard.id == client_event->leaderboard_tracker->id) + { + strncpy(leaderboard.display, client_event->leaderboard_tracker->display, + RC_CLIENT_LEADERBOARD_DISPLAY_SIZE); + } + } +} + +void AchievementManager::HandleLeaderboardTrackerShowEvent(const rc_client_event_t* client_event) +{ + AchievementManager::GetInstance().m_active_leaderboards.push_back( + *client_event->leaderboard_tracker); +} + +void AchievementManager::HandleLeaderboardTrackerHideEvent(const rc_client_event_t* client_event) +{ + auto& active_leaderboards = AchievementManager::GetInstance().m_active_leaderboards; + std::erase_if(active_leaderboards, [client_event](const auto& leaderboard) { + return leaderboard.id == client_event->leaderboard_tracker->id; + }); +} + // Every RetroAchievements API call, with only a partial exception for fetch_image, follows // the same design pattern (here, X is the name of the call): // Create a specific rc_api_X_request_t struct and populate with the necessary values @@ -1023,6 +1061,15 @@ void AchievementManager::EventHandlerV2(const rc_client_event_t* event, rc_clien case RC_CLIENT_EVENT_LEADERBOARD_SUBMITTED: HandleLeaderboardSubmittedEvent(event); break; + case RC_CLIENT_EVENT_LEADERBOARD_TRACKER_UPDATE: + HandleLeaderboardTrackerUpdateEvent(event); + break; + case RC_CLIENT_EVENT_LEADERBOARD_TRACKER_SHOW: + HandleLeaderboardTrackerShowEvent(event); + break; + case RC_CLIENT_EVENT_LEADERBOARD_TRACKER_HIDE: + HandleLeaderboardTrackerHideEvent(event); + break; default: INFO_LOG_FMT(ACHIEVEMENTS, "Event triggered of unhandled type {}", event->type); break; diff --git a/Source/Core/Core/AchievementManager.h b/Source/Core/Core/AchievementManager.h index acc87fcdb2..a833de0be9 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -73,6 +73,7 @@ public: using RichPresence = std::array; using Badge = std::vector; using NamedIconMap = std::map, std::less<>>; + static constexpr size_t MAX_DISPLAYED_LBOARDS = 4; struct BadgeStatus { @@ -146,6 +147,7 @@ public: bool IsDisabled() const { return m_disabled; }; void SetDisabled(bool disabled); const NamedIconMap& GetChallengeIcons() const; + std::vector GetActiveLeaderboards() const; void CloseGame(); void Logout(); @@ -190,6 +192,9 @@ private: static void HandleLeaderboardStartedEvent(const rc_client_event_t* client_event); static void HandleLeaderboardFailedEvent(const rc_client_event_t* client_event); static void HandleLeaderboardSubmittedEvent(const rc_client_event_t* client_event); + static void HandleLeaderboardTrackerUpdateEvent(const rc_client_event_t* client_event); + static void HandleLeaderboardTrackerShowEvent(const rc_client_event_t* client_event); + static void HandleLeaderboardTrackerHideEvent(const rc_client_event_t* client_event); template ResponseType Request(RcRequest rc_request, RcResponse* rc_response, @@ -224,6 +229,7 @@ private: std::unordered_map m_unlock_map; std::unordered_map m_leaderboard_map; NamedIconMap m_active_challenges; + std::vector m_active_leaderboards; Common::WorkQueueThread> m_queue; Common::WorkQueueThread> m_image_queue;