From c8d8ca2ff7c33ec9dca6dc40092b4bb092ae923c Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Sun, 1 Oct 2023 23:21:59 -0400 Subject: [PATCH] Added Disabled flag to Achievement Manager The Disabled state sits between Game Closed and completely Shutdown - stronger than the former, as it refuses to let a game be opened again until AchievementManager is restored (which only happens upon a fresh core boot) but it isn't completely shut down and will still allow the player to be logged in and access the achievement settings and their (global) achievement header. --- Source/Core/Core/AchievementManager.cpp | 62 ++++++++++++++++++- Source/Core/Core/AchievementManager.h | 3 + Source/Core/Core/BootManager.cpp | 4 ++ Source/Core/Core/ConfigManager.cpp | 5 ++ .../Achievements/AchievementHeaderWidget.cpp | 11 ++++ .../Achievements/AchievementHeaderWidget.h | 1 + 6 files changed, 84 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index 424446647f..e41cc43eb5 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -100,6 +100,13 @@ void AchievementManager::HashGame(const std::string& file_path, const ResponseCa callback(AchievementManager::ResponseType::MANAGER_NOT_INITIALIZED); return; } + if (m_disabled) + { + INFO_LOG_FMT(ACHIEVEMENTS, "Achievement Manager is disabled until core is rebooted."); + OSD::AddMessage("Achievements are disabled until you restart emulation.", + OSD::Duration::VERY_LONG, OSD::Color::RED); + return; + } m_system = &Core::System::GetInstance(); m_queue.EmplaceItem([this, callback, file_path] { Hash new_hash; @@ -122,6 +129,12 @@ void AchievementManager::HashGame(const std::string& file_path, const ResponseCa } { std::lock_guard lg{m_lock}; + if (m_disabled) + { + INFO_LOG_FMT(ACHIEVEMENTS, "Achievements disabled while hash was resolving."); + callback(AchievementManager::ResponseType::EXPIRED_CONTEXT); + return; + } m_game_hash = std::move(new_hash); } LoadGameSync(callback); @@ -142,13 +155,32 @@ void AchievementManager::HashGame(const DiscIO::Volume* volume, const ResponseCa INFO_LOG_FMT(ACHIEVEMENTS, "New volume is empty."); return; } + if (m_disabled) + { + INFO_LOG_FMT(ACHIEVEMENTS, "Achievement Manager is disabled until core is rebooted."); + OSD::AddMessage("Achievements are disabled until core is rebooted.", OSD::Duration::VERY_LONG, + OSD::Color::RED); + return; + } + // Need to SetDisabled outside a lock because it uses m_lock internally. + bool disable = false; { std::lock_guard lg{m_lock}; if (m_loading_volume.get() != nullptr) { - return; + disable = true; } - m_loading_volume = DiscIO::CreateVolume(volume->GetBlobReader().CopyReader()); + else + { + m_loading_volume = DiscIO::CreateVolume(volume->GetBlobReader().CopyReader()); + } + } + if (disable) + { + INFO_LOG_FMT(ACHIEVEMENTS, "Disabling Achievement Manager due to hash spam."); + SetDisabled(true); + callback(AchievementManager::ResponseType::EXPIRED_CONTEXT); + return; } m_system = &Core::System::GetInstance(); struct FilereaderState @@ -177,6 +209,12 @@ void AchievementManager::HashGame(const DiscIO::Volume* volume, const ResponseCa } { std::lock_guard lg{m_lock}; + if (m_disabled) + { + INFO_LOG_FMT(ACHIEVEMENTS, "Achievements disabled while hash was resolving."); + callback(AchievementManager::ResponseType::EXPIRED_CONTEXT); + return; + } m_game_hash = std::move(new_hash); m_loading_volume.reset(); } @@ -197,6 +235,7 @@ void AchievementManager::LoadGameSync(const ResponseCallback& callback) INFO_LOG_FMT(ACHIEVEMENTS, "No RetroAchievements data found for this game."); OSD::AddMessage("No RetroAchievements data found for this game.", OSD::Duration::VERY_LONG, OSD::Color::RED); + SetDisabled(true); callback(resolve_hash_response); return; } @@ -773,6 +812,25 @@ AchievementManager::RichPresence AchievementManager::GetRichPresence() return rich_presence; } +void AchievementManager::SetDisabled(bool disable) +{ + { + std::lock_guard lg{m_lock}; + m_disabled = disable; + } + if (disable) + { + INFO_LOG_FMT(ACHIEVEMENTS, "Achievement Manager has been disabled."); + OSD::AddMessage("Please close all games to re-enable achievements.", OSD::Duration::VERY_LONG, + OSD::Color::RED); + CloseGame(); + } + else + { + INFO_LOG_FMT(ACHIEVEMENTS, "Achievement Manager has been re-enabled."); + } +}; + void AchievementManager::CloseGame() { { diff --git a/Source/Core/Core/AchievementManager.h b/Source/Core/Core/AchievementManager.h index afbe083cd1..9e994cc59e 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -136,6 +136,8 @@ public: u32* target); const std::unordered_map& GetLeaderboardsInfo() const; RichPresence GetRichPresence(); + bool IsDisabled() const { return m_disabled; }; + void SetDisabled(bool disabled); void CloseGame(); void Logout(); @@ -193,6 +195,7 @@ private: bool m_is_runtime_initialized = false; UpdateCallback m_update_callback; std::unique_ptr m_loading_volume; + bool m_disabled = false; std::string m_display_name; u32 m_player_score = 0; BadgeStatus m_player_badge; diff --git a/Source/Core/Core/BootManager.cpp b/Source/Core/Core/BootManager.cpp index 3ddde2ce9c..b45ffb7254 100644 --- a/Source/Core/Core/BootManager.cpp +++ b/Source/Core/Core/BootManager.cpp @@ -164,6 +164,10 @@ bool BootCore(std::unique_ptr boot, const WindowSystemInfo& wsi) } } +#ifdef USE_RETRO_ACHIEVEMENTS + AchievementManager::GetInstance()->SetDisabled(false); +#endif // USE_RETRO_ACHIEVEMENTS + const bool load_ipl = !StartUp.bWii && !Config::Get(Config::MAIN_SKIP_IPL) && std::holds_alternative(boot->parameters); if (load_ipl) diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index 27b7b2a51b..fa1fa2a7a0 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -30,6 +30,7 @@ #include "Common/StringUtil.h" #include "Common/Version.h" +#include "Core/AchievementManager.h" #include "Core/Boot/Boot.h" #include "Core/CommonTitles.h" #include "Core/Config/DefaultLocale.h" @@ -168,6 +169,10 @@ void SConfig::SetRunningGameMetadata(const std::string& game_id, const std::stri if (!was_changed) return; +#ifdef USE_RETRO_ACHIEVEMENTS + AchievementManager::GetInstance()->SetDisabled(true); +#endif // USE_RETRO_ACHIEVEMENTS + if (game_id == "00000000") { m_title_name.clear(); diff --git a/Source/Core/DolphinQt/Achievements/AchievementHeaderWidget.cpp b/Source/Core/DolphinQt/Achievements/AchievementHeaderWidget.cpp index c984fdda0f..3cd42b6e3b 100644 --- a/Source/Core/DolphinQt/Achievements/AchievementHeaderWidget.cpp +++ b/Source/Core/DolphinQt/Achievements/AchievementHeaderWidget.cpp @@ -37,6 +37,11 @@ AchievementHeaderWidget::AchievementHeaderWidget(QWidget* parent) : QWidget(pare m_game_progress_hard = new QProgressBar(); m_game_progress_soft = new QProgressBar(); m_rich_presence = new QLabel(); + m_locked_warning = new QLabel(); + + m_locked_warning->setText(tr("Achievements have been disabled.
Please close all running " + "games to re-enable achievements.")); + m_locked_warning->setStyleSheet(QStringLiteral("QLabel { color : red; }")); QSizePolicy sp_retain = m_game_progress_hard->sizePolicy(); sp_retain.setRetainSizeWhenHidden(true); @@ -54,6 +59,7 @@ AchievementHeaderWidget::AchievementHeaderWidget(QWidget* parent) : QWidget(pare text_col->addWidget(m_game_progress_hard); text_col->addWidget(m_game_progress_soft); text_col->addWidget(m_rich_presence); + text_col->addWidget(m_locked_warning); QHBoxLayout* header_layout = new QHBoxLayout(); header_layout->addLayout(icon_col); header_layout->addLayout(text_col); @@ -148,6 +154,7 @@ void AchievementHeaderWidget::UpdateData() QString::fromUtf8(AchievementManager::GetInstance()->GetRichPresence().data())); if (!m_rich_presence->isVisible()) m_rich_presence->setVisible(Config::Get(Config::RA_RICH_PRESENCE_ENABLED)); + m_locked_warning->setVisible(false); } else { @@ -157,6 +164,10 @@ void AchievementHeaderWidget::UpdateData() m_game_progress_hard->setVisible(false); m_game_progress_soft->setVisible(false); m_rich_presence->setVisible(false); + if (AchievementManager::GetInstance()->IsDisabled()) + { + m_locked_warning->setVisible(true); + } } } diff --git a/Source/Core/DolphinQt/Achievements/AchievementHeaderWidget.h b/Source/Core/DolphinQt/Achievements/AchievementHeaderWidget.h index 2c4f939ceb..7a644bd763 100644 --- a/Source/Core/DolphinQt/Achievements/AchievementHeaderWidget.h +++ b/Source/Core/DolphinQt/Achievements/AchievementHeaderWidget.h @@ -30,6 +30,7 @@ private: QProgressBar* m_game_progress_hard; QProgressBar* m_game_progress_soft; QLabel* m_rich_presence; + QLabel* m_locked_warning; QGroupBox* m_header_box; };