Achievements: Fix race in notifications

GS thread might not initialize fullscreen UI before data finishes
parsing.
This commit is contained in:
Stenzek 2023-01-28 13:57:41 +10:00 committed by refractionpcsx2
parent 1b40e4aaca
commit ed26368a3a
3 changed files with 28 additions and 17 deletions

View File

@ -105,14 +105,13 @@ void AchievementSettingsWidget::updateEnableState()
{ {
const bool enabled = m_dialog->getEffectiveBoolValue("Achievements", "Enabled", false); const bool enabled = m_dialog->getEffectiveBoolValue("Achievements", "Enabled", false);
const bool challenge = m_dialog->getEffectiveBoolValue("Achievements", "ChallengeMode", false); const bool challenge = m_dialog->getEffectiveBoolValue("Achievements", "ChallengeMode", false);
const bool notifications = m_dialog->getEffectiveBoolValue("Achievements", "Notifications", true);
m_ui.testMode->setEnabled(enabled); m_ui.testMode->setEnabled(enabled);
m_ui.unofficialTestMode->setEnabled(enabled); m_ui.unofficialTestMode->setEnabled(enabled);
m_ui.richPresence->setEnabled(enabled); m_ui.richPresence->setEnabled(enabled);
m_ui.challengeMode->setEnabled(enabled); m_ui.challengeMode->setEnabled(enabled);
m_ui.leaderboards->setEnabled(enabled && challenge); m_ui.leaderboards->setEnabled(enabled && challenge);
m_ui.notifications->setEnabled(enabled); m_ui.notifications->setEnabled(enabled);
m_ui.soundEffects->setEnabled(enabled && notifications); m_ui.soundEffects->setEnabled(enabled);
m_ui.primedIndicators->setEnabled(enabled); m_ui.primedIndicators->setEnabled(enabled);
} }

View File

@ -1033,7 +1033,7 @@ void Achievements::DownloadImage(std::string url, std::string cache_filename)
void Achievements::DisplayAchievementSummary() void Achievements::DisplayAchievementSummary()
{ {
if (FullscreenUI::IsInitialized() && EmuConfig.Achievements.Notifications) if (EmuConfig.Achievements.Notifications)
{ {
std::string title = s_game_title; std::string title = s_game_title;
if (ChallengeModeActive()) if (ChallengeModeActive())
@ -1056,24 +1056,30 @@ void Achievements::DisplayAchievementSummary()
summary.append("Leaderboard submission is enabled."); summary.append("Leaderboard submission is enabled.");
} }
ImGuiFullscreen::AddNotification(10.0f, std::move(title), std::move(summary), s_game_icon); GetMTGS().RunOnGSThread([title = std::move(title), summary = std::move(summary), icon = s_game_icon]() {
if (FullscreenUI::IsInitialized())
// Technically not going through the resource API, but since we're passing this to something else, we can't. ImGuiFullscreen::AddNotification(10.0f, std::move(title), std::move(summary), std::move(icon));
if (EmuConfig.Achievements.SoundEffects) });
Common::PlaySoundAsync(Path::Combine(EmuFolders::Resources, INFO_SOUND_NAME).c_str());
} }
// Technically not going through the resource API, but since we're passing this to something else, we can't.
if (EmuConfig.Achievements.SoundEffects)
Common::PlaySoundAsync(Path::Combine(EmuFolders::Resources, INFO_SOUND_NAME).c_str());
} }
void Achievements::DisplayMasteredNotification() void Achievements::DisplayMasteredNotification()
{ {
if (!FullscreenUI::IsInitialized() || !EmuConfig.Achievements.Notifications) if (!EmuConfig.Achievements.Notifications)
return; return;
std::string title(fmt::format("Mastered {}", s_game_title)); std::string title(fmt::format("Mastered {}", s_game_title));
std::string message(fmt::format( std::string message(fmt::format(
"{} achievements, {} points{}", GetAchievementCount(), GetCurrentPointsForGame(), s_challenge_mode ? " (Hardcore Mode)" : "")); "{} achievements, {} points{}", GetAchievementCount(), GetCurrentPointsForGame(), s_challenge_mode ? " (Hardcore Mode)" : ""));
ImGuiFullscreen::AddNotification(20.0f, std::move(title), std::move(message), s_game_icon); GetMTGS().RunOnGSThread([title = std::move(title), message = std::move(message), icon = s_game_icon]() {
if (FullscreenUI::IsInitialized())
ImGuiFullscreen::AddNotification(20.0f, std::move(title), std::move(message), std::move(icon));
});
} }
void Achievements::GetUserUnlocksCallback(s32 status_code, const std::string& content_type, Common::HTTPDownloader::Request::Data data) void Achievements::GetUserUnlocksCallback(s32 status_code, const std::string& content_type, Common::HTTPDownloader::Request::Data data)
@ -1796,7 +1802,10 @@ void Achievements::SubmitLeaderboardCallback(s32 status_code, const std::string&
std::string summary = fmt::format( std::string summary = fmt::format(
"Your Score: {} (Best: {})\nLeaderboard Position: {} of {}", submitted_score, best_score, response.new_rank, response.num_entries); "Your Score: {} (Best: {})\nLeaderboard Position: {} of {}", submitted_score, best_score, response.new_rank, response.num_entries);
ImGuiFullscreen::AddNotification(10.0f, lb->title, std::move(summary), s_game_icon); GetMTGS().RunOnGSThread([title = lb->title, summary = std::move(summary), icon = s_game_icon]() {
if (FullscreenUI::IsInitialized())
ImGuiFullscreen::AddNotification(10.0f, std::move(title), std::move(summary), std::move(icon));
});
} }
void Achievements::UnlockAchievement(u32 achievement_id, bool add_notification /* = true*/) void Achievements::UnlockAchievement(u32 achievement_id, bool add_notification /* = true*/)
@ -1819,7 +1828,7 @@ void Achievements::UnlockAchievement(u32 achievement_id, bool add_notification /
Console.WriteLn("Achievement %s (%u) for game %u unlocked", achievement->title.c_str(), achievement_id, s_game_id); Console.WriteLn("Achievement %s (%u) for game %u unlocked", achievement->title.c_str(), achievement_id, s_game_id);
if (FullscreenUI::IsInitialized() && EmuConfig.Achievements.Notifications) if (EmuConfig.Achievements.Notifications)
{ {
std::string title; std::string title;
switch (achievement->category) switch (achievement->category)
@ -1836,11 +1845,15 @@ void Achievements::UnlockAchievement(u32 achievement_id, bool add_notification /
break; break;
} }
ImGuiFullscreen::AddNotification(15.0f, std::move(title), achievement->description, GetAchievementBadgePath(*achievement)); GetMTGS().RunOnGSThread(
if (EmuConfig.Achievements.SoundEffects) [title = std::move(title), description = achievement->description, icon = GetAchievementBadgePath(*achievement)]() {
Common::PlaySoundAsync(Path::Combine(EmuFolders::Resources, UNLOCK_SOUND_NAME).c_str()); ImGuiFullscreen::AddNotification(15.0f, std::move(title), std::move(description), std::move(icon));
});
} }
if (EmuConfig.Achievements.SoundEffects)
Common::PlaySoundAsync(Path::Combine(EmuFolders::Resources, UNLOCK_SOUND_NAME).c_str());
if (IsMastered()) if (IsMastered())
DisplayMasteredNotification(); DisplayMasteredNotification();

View File

@ -6759,7 +6759,6 @@ void FullscreenUI::DrawAchievementsSettingsPage(std::unique_lock<std::mutex>& se
const bool enabled = bsi->GetBoolValue("Achievements", "Enabled", false); const bool enabled = bsi->GetBoolValue("Achievements", "Enabled", false);
const bool challenge = bsi->GetBoolValue("Achievements", "ChallengeMode", false); const bool challenge = bsi->GetBoolValue("Achievements", "ChallengeMode", false);
const bool notifications = bsi->GetBoolValue("Achievements", "Notifications", true);
DrawToggleSetting(bsi, ICON_FA_USER_FRIENDS " Rich Presence", DrawToggleSetting(bsi, ICON_FA_USER_FRIENDS " Rich Presence",
"When enabled, rich presence information will be collected and sent to the server where supported.", "Achievements", "RichPresence", "When enabled, rich presence information will be collected and sent to the server where supported.", "Achievements", "RichPresence",
@ -6774,7 +6773,7 @@ void FullscreenUI::DrawAchievementsSettingsPage(std::unique_lock<std::mutex>& se
enabled); enabled);
DrawToggleSetting(bsi, ICON_FA_HEADPHONES " Sound Effects", DrawToggleSetting(bsi, ICON_FA_HEADPHONES " Sound Effects",
"Plays sound effects for events such as achievement unlocks and leaderboard submissions.", "Achievements", "SoundEffects", true, "Plays sound effects for events such as achievement unlocks and leaderboard submissions.", "Achievements", "SoundEffects", true,
enabled && notifications); enabled);
DrawToggleSetting(bsi, ICON_FA_MAGIC " Show Challenge Indicators", DrawToggleSetting(bsi, ICON_FA_MAGIC " Show Challenge Indicators",
"Shows icons in the lower-right corner of the screen when a challenge/primed achievement is active.", "Achievements", "Shows icons in the lower-right corner of the screen when a challenge/primed achievement is active.", "Achievements",
"PrimedIndicators", true, enabled); "PrimedIndicators", true, enabled);