mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 08:09:26 +01:00
Refactor leaderboard entry calls to use rc_client
Leaderboard entry calls are asyncronous and use a callback. Logic remains the same, but the callback populates the list that the UI grabs values from.
This commit is contained in:
parent
c57be0efca
commit
fa2210f80d
@ -359,11 +359,17 @@ AchievementManager::GetAchievementProgress(AchievementId achievement_id, u32* va
|
|||||||
}
|
}
|
||||||
|
|
||||||
const AchievementManager::LeaderboardStatus*
|
const AchievementManager::LeaderboardStatus*
|
||||||
AchievementManager::GetLeaderboardInfo(AchievementManager::AchievementId leaderboard_id) const
|
AchievementManager::GetLeaderboardInfo(AchievementManager::AchievementId leaderboard_id)
|
||||||
{
|
{
|
||||||
if (m_leaderboard_map.count(leaderboard_id) < 1)
|
if (const auto leaderboard_iter = m_leaderboard_map.find(leaderboard_id);
|
||||||
return nullptr;
|
leaderboard_iter != m_leaderboard_map.end())
|
||||||
return &m_leaderboard_map.at(leaderboard_id);
|
{
|
||||||
|
if (leaderboard_iter->second.entries.size() == 0)
|
||||||
|
FetchBoardInfo(leaderboard_id);
|
||||||
|
return &leaderboard_iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
AchievementManager::RichPresence AchievementManager::GetRichPresence() const
|
AchievementManager::RichPresence AchievementManager::GetRichPresence() const
|
||||||
@ -617,92 +623,39 @@ void AchievementManager::LoginCallback(int result, const char* error_message, rc
|
|||||||
AchievementManager::GetInstance().FetchPlayerBadge();
|
AchievementManager::GetInstance().FetchPlayerBadge();
|
||||||
}
|
}
|
||||||
|
|
||||||
AchievementManager::ResponseType AchievementManager::FetchBoardInfo(AchievementId leaderboard_id)
|
void AchievementManager::FetchBoardInfo(AchievementId leaderboard_id)
|
||||||
{
|
{
|
||||||
std::string username = Config::Get(Config::RA_USERNAME);
|
u32* callback_data_1 = new u32(leaderboard_id);
|
||||||
LeaderboardStatus lboard{};
|
u32* callback_data_2 = new u32(leaderboard_id);
|
||||||
|
rc_client_begin_fetch_leaderboard_entries(m_client, leaderboard_id, 1, 4,
|
||||||
|
LeaderboardEntriesCallback, callback_data_1);
|
||||||
|
rc_client_begin_fetch_leaderboard_entries_around_user(
|
||||||
|
m_client, leaderboard_id, 4, LeaderboardEntriesCallback, callback_data_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AchievementManager::LeaderboardEntriesCallback(int result, const char* error_message,
|
||||||
|
rc_client_leaderboard_entry_list_t* list,
|
||||||
|
rc_client_t* client, void* userdata)
|
||||||
|
{
|
||||||
|
if (result != RC_OK)
|
||||||
{
|
{
|
||||||
rc_api_fetch_leaderboard_info_response_t board_info{};
|
WARN_LOG_FMT(ACHIEVEMENTS, "Failed to fetch leaderboard entries.");
|
||||||
const rc_api_fetch_leaderboard_info_request_t fetch_board_request = {
|
return;
|
||||||
.leaderboard_id = leaderboard_id, .count = 4, .first_entry = 1, .username = nullptr};
|
|
||||||
const ResponseType r_type =
|
|
||||||
Request<rc_api_fetch_leaderboard_info_request_t, rc_api_fetch_leaderboard_info_response_t>(
|
|
||||||
fetch_board_request, &board_info, rc_api_init_fetch_leaderboard_info_request,
|
|
||||||
rc_api_process_fetch_leaderboard_info_response);
|
|
||||||
if (r_type != ResponseType::SUCCESS)
|
|
||||||
{
|
|
||||||
ERROR_LOG_FMT(ACHIEVEMENTS, "Failed to fetch info for leaderboard ID {}.", leaderboard_id);
|
|
||||||
rc_api_destroy_fetch_leaderboard_info_response(&board_info);
|
|
||||||
return r_type;
|
|
||||||
}
|
|
||||||
lboard.name = board_info.title;
|
|
||||||
lboard.description = board_info.description;
|
|
||||||
lboard.entries.clear();
|
|
||||||
for (u32 i = 0; i < board_info.num_entries; ++i)
|
|
||||||
{
|
|
||||||
const auto& org_entry = board_info.entries[i];
|
|
||||||
auto dest_entry = LeaderboardEntry{
|
|
||||||
.username = org_entry.username,
|
|
||||||
.rank = org_entry.rank,
|
|
||||||
};
|
|
||||||
if (rc_runtime_format_lboard_value(dest_entry.score.data(), FORMAT_SIZE, org_entry.score,
|
|
||||||
board_info.format) == 0)
|
|
||||||
{
|
|
||||||
ERROR_LOG_FMT(ACHIEVEMENTS, "Failed to format leaderboard score {}.", org_entry.score);
|
|
||||||
strncpy(dest_entry.score.data(), fmt::format("{}", org_entry.score).c_str(), FORMAT_SIZE);
|
|
||||||
}
|
|
||||||
lboard.entries.insert_or_assign(org_entry.index, std::move(dest_entry));
|
|
||||||
}
|
|
||||||
rc_api_destroy_fetch_leaderboard_info_response(&board_info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 leaderboard_id = *reinterpret_cast<u32*>(userdata);
|
||||||
|
delete userdata;
|
||||||
|
auto& leaderboard = AchievementManager::GetInstance().m_leaderboard_map[leaderboard_id];
|
||||||
|
for (size_t ix = 0; ix < list->num_entries; ix++)
|
||||||
{
|
{
|
||||||
// Retrieve, if exists, the player's entry, the two entries above the player, and the two
|
std::lock_guard lg{AchievementManager::GetInstance().GetLock()};
|
||||||
// entries below the player, for a total of five entries. Technically I only need one entry
|
const auto& response_entry = list->entries[ix];
|
||||||
// below, but the API is ambiguous what happens if an even number and a username are provided.
|
auto& map_entry = leaderboard.entries[response_entry.index];
|
||||||
rc_api_fetch_leaderboard_info_response_t board_info{};
|
map_entry.username.assign(response_entry.user);
|
||||||
const rc_api_fetch_leaderboard_info_request_t fetch_board_request = {
|
memcpy(map_entry.score.data(), response_entry.display, FORMAT_SIZE);
|
||||||
.leaderboard_id = leaderboard_id,
|
map_entry.rank = response_entry.rank;
|
||||||
.count = 5,
|
|
||||||
.first_entry = 0,
|
|
||||||
.username = username.c_str()};
|
|
||||||
const ResponseType r_type =
|
|
||||||
Request<rc_api_fetch_leaderboard_info_request_t, rc_api_fetch_leaderboard_info_response_t>(
|
|
||||||
fetch_board_request, &board_info, rc_api_init_fetch_leaderboard_info_request,
|
|
||||||
rc_api_process_fetch_leaderboard_info_response);
|
|
||||||
if (r_type != ResponseType::SUCCESS)
|
|
||||||
{
|
|
||||||
ERROR_LOG_FMT(ACHIEVEMENTS, "Failed to fetch info for leaderboard ID {}.", leaderboard_id);
|
|
||||||
rc_api_destroy_fetch_leaderboard_info_response(&board_info);
|
|
||||||
return r_type;
|
|
||||||
}
|
|
||||||
for (u32 i = 0; i < board_info.num_entries; ++i)
|
|
||||||
{
|
|
||||||
const auto& org_entry = board_info.entries[i];
|
|
||||||
auto dest_entry = LeaderboardEntry{
|
|
||||||
.username = org_entry.username,
|
|
||||||
.rank = org_entry.rank,
|
|
||||||
};
|
|
||||||
if (rc_runtime_format_lboard_value(dest_entry.score.data(), FORMAT_SIZE, org_entry.score,
|
|
||||||
board_info.format) == 0)
|
|
||||||
{
|
|
||||||
ERROR_LOG_FMT(ACHIEVEMENTS, "Failed to format leaderboard score {}.", org_entry.score);
|
|
||||||
strncpy(dest_entry.score.data(), fmt::format("{}", org_entry.score).c_str(), FORMAT_SIZE);
|
|
||||||
}
|
|
||||||
lboard.entries.insert_or_assign(org_entry.index, std::move(dest_entry));
|
|
||||||
if (org_entry.username == username)
|
|
||||||
lboard.player_index = org_entry.index;
|
|
||||||
}
|
|
||||||
rc_api_destroy_fetch_leaderboard_info_response(&board_info);
|
|
||||||
}
|
}
|
||||||
|
AchievementManager::GetInstance().m_update_callback();
|
||||||
{
|
|
||||||
std::lock_guard lg{m_lock};
|
|
||||||
m_leaderboard_map.insert_or_assign(leaderboard_id, std::move(lboard));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ResponseType::SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementManager::GenerateRichPresence(const Core::CPUThreadGuard& guard)
|
void AchievementManager::GenerateRichPresence(const Core::CPUThreadGuard& guard)
|
||||||
@ -807,12 +760,14 @@ void AchievementManager::HandleLeaderboardStartedEvent(const rc_client_event_t*
|
|||||||
OSD::AddMessage(fmt::format("Attempting leaderboard: {} - {}", client_event->leaderboard->title,
|
OSD::AddMessage(fmt::format("Attempting leaderboard: {} - {}", client_event->leaderboard->title,
|
||||||
client_event->leaderboard->description),
|
client_event->leaderboard->description),
|
||||||
OSD::Duration::VERY_LONG, OSD::Color::GREEN);
|
OSD::Duration::VERY_LONG, OSD::Color::GREEN);
|
||||||
|
AchievementManager::GetInstance().FetchBoardInfo(client_event->leaderboard->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementManager::HandleLeaderboardFailedEvent(const rc_client_event_t* client_event)
|
void AchievementManager::HandleLeaderboardFailedEvent(const rc_client_event_t* client_event)
|
||||||
{
|
{
|
||||||
OSD::AddMessage(fmt::format("Failed leaderboard: {}", client_event->leaderboard->title),
|
OSD::AddMessage(fmt::format("Failed leaderboard: {}", client_event->leaderboard->title),
|
||||||
OSD::Duration::VERY_LONG, OSD::Color::RED);
|
OSD::Duration::VERY_LONG, OSD::Color::RED);
|
||||||
|
AchievementManager::GetInstance().FetchBoardInfo(client_event->leaderboard->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementManager::HandleLeaderboardSubmittedEvent(const rc_client_event_t* client_event)
|
void AchievementManager::HandleLeaderboardSubmittedEvent(const rc_client_event_t* client_event)
|
||||||
@ -821,6 +776,7 @@ void AchievementManager::HandleLeaderboardSubmittedEvent(const rc_client_event_t
|
|||||||
client_event->leaderboard->tracker_value,
|
client_event->leaderboard->tracker_value,
|
||||||
client_event->leaderboard->title),
|
client_event->leaderboard->title),
|
||||||
OSD::Duration::VERY_LONG, OSD::Color::YELLOW);
|
OSD::Duration::VERY_LONG, OSD::Color::YELLOW);
|
||||||
|
AchievementManager::GetInstance().FetchBoardInfo(client_event->leaderboard->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementManager::HandleLeaderboardTrackerUpdateEvent(const rc_client_event_t* client_event)
|
void AchievementManager::HandleLeaderboardTrackerUpdateEvent(const rc_client_event_t* client_event)
|
||||||
|
@ -143,7 +143,7 @@ public:
|
|||||||
const UnlockStatus* GetUnlockStatus(AchievementId achievement_id) const;
|
const UnlockStatus* GetUnlockStatus(AchievementId achievement_id) const;
|
||||||
AchievementManager::ResponseType GetAchievementProgress(AchievementId achievement_id, u32* value,
|
AchievementManager::ResponseType GetAchievementProgress(AchievementId achievement_id, u32* value,
|
||||||
u32* target);
|
u32* target);
|
||||||
const LeaderboardStatus* GetLeaderboardInfo(AchievementId leaderboard_id) const;
|
const LeaderboardStatus* GetLeaderboardInfo(AchievementId leaderboard_id);
|
||||||
RichPresence GetRichPresence() const;
|
RichPresence GetRichPresence() const;
|
||||||
bool IsDisabled() const { return m_disabled; };
|
bool IsDisabled() const { return m_disabled; };
|
||||||
void SetDisabled(bool disabled);
|
void SetDisabled(bool disabled);
|
||||||
@ -177,7 +177,7 @@ private:
|
|||||||
static void LoginCallback(int result, const char* error_message, rc_client_t* client,
|
static void LoginCallback(int result, const char* error_message, rc_client_t* client,
|
||||||
void* userdata);
|
void* userdata);
|
||||||
|
|
||||||
ResponseType FetchBoardInfo(AchievementId leaderboard_id);
|
void FetchBoardInfo(AchievementId leaderboard_id);
|
||||||
|
|
||||||
std::unique_ptr<DiscIO::Volume>& GetLoadingVolume() { return m_loading_volume; };
|
std::unique_ptr<DiscIO::Volume>& GetLoadingVolume() { return m_loading_volume; };
|
||||||
|
|
||||||
@ -189,6 +189,10 @@ private:
|
|||||||
void* userdata);
|
void* userdata);
|
||||||
void DisplayWelcomeMessage();
|
void DisplayWelcomeMessage();
|
||||||
|
|
||||||
|
static void LeaderboardEntriesCallback(int result, const char* error_message,
|
||||||
|
rc_client_leaderboard_entry_list_t* list,
|
||||||
|
rc_client_t* client, void* userdata);
|
||||||
|
|
||||||
static void HandleAchievementTriggeredEvent(const rc_client_event_t* client_event);
|
static void HandleAchievementTriggeredEvent(const rc_client_event_t* client_event);
|
||||||
static void HandleLeaderboardStartedEvent(const rc_client_event_t* client_event);
|
static void HandleLeaderboardStartedEvent(const rc_client_event_t* client_event);
|
||||||
static void HandleLeaderboardFailedEvent(const rc_client_event_t* client_event);
|
static void HandleLeaderboardFailedEvent(const rc_client_event_t* client_event);
|
||||||
|
@ -44,42 +44,47 @@ void AchievementLeaderboardWidget::UpdateData(bool clean_all)
|
|||||||
auto& instance = AchievementManager::GetInstance();
|
auto& instance = AchievementManager::GetInstance();
|
||||||
if (!instance.IsGameLoaded())
|
if (!instance.IsGameLoaded())
|
||||||
return;
|
return;
|
||||||
|
auto* client = instance.GetClient();
|
||||||
|
auto* leaderboard_list =
|
||||||
|
rc_client_create_leaderboard_list(client, RC_CLIENT_LEADERBOARD_LIST_GROUPING_NONE);
|
||||||
|
|
||||||
rc_api_fetch_game_data_response_t* game_data;
|
u32 row = 0;
|
||||||
|
for (u32 bucket = 0; bucket < leaderboard_list->num_buckets; bucket++)
|
||||||
{
|
{
|
||||||
std::lock_guard lg{AchievementManager::GetInstance().GetLock()};
|
const auto& leaderboard_bucket = leaderboard_list->buckets[bucket];
|
||||||
game_data = instance.GetGameData();
|
for (u32 board = 0; board < leaderboard_bucket.num_leaderboards; board++)
|
||||||
}
|
|
||||||
for (u32 row = 0; row < game_data->num_leaderboards; row += 2)
|
|
||||||
{
|
|
||||||
const auto* leaderboard = game_data->leaderboards + (row / 2);
|
|
||||||
m_leaderboard_order[leaderboard->id] = row;
|
|
||||||
QLabel* a_title = new QLabel(QString::fromUtf8(leaderboard->title));
|
|
||||||
QLabel* a_description = new QLabel(QString::fromUtf8(leaderboard->description));
|
|
||||||
QVBoxLayout* a_col_left = new QVBoxLayout();
|
|
||||||
a_col_left->addWidget(a_title);
|
|
||||||
a_col_left->addWidget(a_description);
|
|
||||||
if (row > 0)
|
|
||||||
{
|
{
|
||||||
QFrame* a_divider = new QFrame();
|
const auto* leaderboard = leaderboard_bucket.leaderboards[board];
|
||||||
a_divider->setFrameShape(QFrame::HLine);
|
m_leaderboard_order[leaderboard->id] = row;
|
||||||
m_common_layout->addWidget(a_divider, row - 1, 0);
|
QLabel* a_title = new QLabel(QString::fromUtf8(leaderboard->title));
|
||||||
}
|
QLabel* a_description = new QLabel(QString::fromUtf8(leaderboard->description));
|
||||||
m_common_layout->addLayout(a_col_left, row, 0);
|
QVBoxLayout* a_col_left = new QVBoxLayout();
|
||||||
for (size_t ix = 0; ix < 4; ix++)
|
a_col_left->addWidget(a_title);
|
||||||
{
|
a_col_left->addWidget(a_description);
|
||||||
QVBoxLayout* a_col = new QVBoxLayout();
|
|
||||||
for (size_t jx = 0; jx < 3; jx++)
|
|
||||||
a_col->addWidget(new QLabel(QStringLiteral("---")));
|
|
||||||
if (row > 0)
|
if (row > 0)
|
||||||
{
|
{
|
||||||
QFrame* a_divider = new QFrame();
|
QFrame* a_divider = new QFrame();
|
||||||
a_divider->setFrameShape(QFrame::HLine);
|
a_divider->setFrameShape(QFrame::HLine);
|
||||||
m_common_layout->addWidget(a_divider, row - 1, static_cast<int>(ix) + 1);
|
m_common_layout->addWidget(a_divider, row - 1, 0);
|
||||||
}
|
}
|
||||||
m_common_layout->addLayout(a_col, row, static_cast<int>(ix) + 1);
|
m_common_layout->addLayout(a_col_left, row, 0);
|
||||||
|
for (size_t ix = 0; ix < 4; ix++)
|
||||||
|
{
|
||||||
|
QVBoxLayout* a_col = new QVBoxLayout();
|
||||||
|
for (size_t jx = 0; jx < 3; jx++)
|
||||||
|
a_col->addWidget(new QLabel(QStringLiteral("---")));
|
||||||
|
if (row > 0)
|
||||||
|
{
|
||||||
|
QFrame* a_divider = new QFrame();
|
||||||
|
a_divider->setFrameShape(QFrame::HLine);
|
||||||
|
m_common_layout->addWidget(a_divider, row - 1, static_cast<int>(ix) + 1);
|
||||||
|
}
|
||||||
|
m_common_layout->addLayout(a_col, row, static_cast<int>(ix) + 1);
|
||||||
|
}
|
||||||
|
row += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rc_client_destroy_leaderboard_list(leaderboard_list);
|
||||||
}
|
}
|
||||||
for (auto row : m_leaderboard_order)
|
for (auto row : m_leaderboard_order)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user