diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index 231cbd5502..fc5008c1fc 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -92,18 +92,21 @@ bool AchievementManager::HasAPIToken() const return !Config::Get(Config::RA_API_TOKEN).empty(); } -void AchievementManager::HashGame(const std::string& file_path, const ResponseCallback& callback) +void AchievementManager::LoadGame(const std::string& file_path, const DiscIO::Volume* volume) { if (!Config::Get(Config::RA_ENABLED) || !HasAPIToken()) { - callback(ResponseType::NOT_ENABLED); return; } - if (!m_is_runtime_initialized) + if (file_path.empty() && volume == nullptr) + { + WARN_LOG_FMT(ACHIEVEMENTS, "Called Load Game without a game."); + return; + } + if (!m_client) { ERROR_LOG_FMT(ACHIEVEMENTS, - "Attempted to load game achievements without Achievement Manager initialized."); - callback(ResponseType::MANAGER_NOT_INITIALIZED); + "Attempted to load game achievements without achievement client initialized."); return; } if (m_disabled) @@ -113,295 +116,32 @@ void AchievementManager::HashGame(const std::string& file_path, const ResponseCa OSD::Duration::VERY_LONG, OSD::Color::RED); return; } - m_system = &Core::System::GetInstance(); - m_queue.EmplaceItem([this, callback, file_path] { - Hash new_hash; - { - std::lock_guard lg{m_filereader_lock}; - rc_hash_filereader volume_reader{ - .open = &AchievementManager::FilereaderOpenByFilepath, - .seek = &AchievementManager::FilereaderSeek, - .tell = &AchievementManager::FilereaderTell, - .read = &AchievementManager::FilereaderRead, - .close = &AchievementManager::FilereaderClose, - }; - rc_hash_init_custom_filereader(&volume_reader); - if (!rc_hash_generate_from_file(new_hash.data(), RC_CONSOLE_GAMECUBE, file_path.c_str())) - { - ERROR_LOG_FMT(ACHIEVEMENTS, "Unable to generate achievement hash from game file {}.", - file_path); - callback(ResponseType::MALFORMED_OBJECT); - } - } - { - std::lock_guard lg{m_lock}; - if (m_disabled) - { - INFO_LOG_FMT(ACHIEVEMENTS, "Achievements disabled while hash was resolving."); - callback(ResponseType::EXPIRED_CONTEXT); - return; - } - m_game_hash = std::move(new_hash); - } - LoadGameSync(callback); - }); -} - -void AchievementManager::HashGame(const DiscIO::Volume* volume, const ResponseCallback& callback) -{ - if (!Config::Get(Config::RA_ENABLED) || !HasAPIToken()) - { - callback(ResponseType::NOT_ENABLED); - return; - } - if (!m_is_runtime_initialized) - { - ERROR_LOG_FMT(ACHIEVEMENTS, - "Attempted to load game achievements without Achievement Manager initialized."); - callback(ResponseType::MANAGER_NOT_INITIALIZED); - return; - } - if (volume == nullptr) - { - 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 = true; + if (volume) { std::lock_guard lg{m_lock}; if (!m_loading_volume) { m_loading_volume = DiscIO::CreateVolume(volume->GetBlobReader().CopyReader()); - disable = false; } } - if (disable) - { - INFO_LOG_FMT(ACHIEVEMENTS, "Disabling Achievement Manager due to hash spam."); - SetDisabled(true); - callback(ResponseType::EXPIRED_CONTEXT); - return; - } - m_system = &Core::System::GetInstance(); - m_queue.EmplaceItem([this, callback] { - Hash new_hash; - { - std::lock_guard lg{m_filereader_lock}; - rc_hash_filereader volume_reader{ - .open = &AchievementManager::FilereaderOpenByVolume, - .seek = &AchievementManager::FilereaderSeek, - .tell = &AchievementManager::FilereaderTell, - .read = &AchievementManager::FilereaderRead, - .close = &AchievementManager::FilereaderClose, - }; - rc_hash_init_custom_filereader(&volume_reader); - if (!rc_hash_generate_from_file(new_hash.data(), RC_CONSOLE_GAMECUBE, "")) - { - ERROR_LOG_FMT(ACHIEVEMENTS, "Unable to generate achievement hash from volume."); - callback(ResponseType::MALFORMED_OBJECT); - return; - } - } - { - std::lock_guard lg{m_lock}; - if (m_disabled) - { - INFO_LOG_FMT(ACHIEVEMENTS, "Achievements disabled while hash was resolving."); - callback(ResponseType::EXPIRED_CONTEXT); - return; - } - m_game_hash = std::move(new_hash); - m_loading_volume.reset(); - } - LoadGameSync(callback); - }); -} - -void AchievementManager::LoadGameSync(const ResponseCallback& callback) -{ - if (!Config::Get(Config::RA_ENABLED) || !HasAPIToken()) - { - callback(ResponseType::NOT_ENABLED); - return; - } - u32 new_game_id = 0; - Hash current_hash; - { - std::lock_guard lg{m_lock}; - current_hash = m_game_hash; - } - const auto resolve_hash_response = ResolveHash(current_hash, &new_game_id); - if (resolve_hash_response != ResponseType::SUCCESS || new_game_id == 0) - { - 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; - } - u32 old_game_id; - { - std::lock_guard lg{m_lock}; - old_game_id = m_game_id; - } - if (new_game_id == old_game_id) - { - INFO_LOG_FMT(ACHIEVEMENTS, "Alternate hash resolved for current game {}.", old_game_id); - callback(ResponseType::SUCCESS); - return; - } - else if (old_game_id != 0) - { - INFO_LOG_FMT(ACHIEVEMENTS, "Swapping game {} for game {}; achievements disabled.", old_game_id, - new_game_id); - OSD::AddMessage("Achievements are now disabled. Please close emulation to re-enable.", - OSD::Duration::VERY_LONG, OSD::Color::RED); - SetDisabled(true); - callback(ResponseType::EXPIRED_CONTEXT); - return; - } - { - std::lock_guard lg{m_lock}; - m_game_id = new_game_id; - } - - const auto start_session_response = StartRASession(); - if (start_session_response != ResponseType::SUCCESS) - { - WARN_LOG_FMT(ACHIEVEMENTS, "Failed to connect to RetroAchievements server."); - OSD::AddMessage("Failed to connect to RetroAchievements server.", OSD::Duration::VERY_LONG, - OSD::Color::RED); - callback(start_session_response); - return; - } - - const auto fetch_game_data_response = FetchGameData(); - if (fetch_game_data_response != ResponseType::SUCCESS) - { - ERROR_LOG_FMT(ACHIEVEMENTS, "Unable to retrieve data from RetroAchievements server."); - OSD::AddMessage("Unable to retrieve data from RetroAchievements server.", - OSD::Duration::VERY_LONG, OSD::Color::RED); - return; - } - INFO_LOG_FMT(ACHIEVEMENTS, "Loading achievements for {}.", m_game_data.title); - - // Claim the lock, then queue the fetch unlock data calls, then initialize the unlock map in - // ActivateDeactiveAchievements. This allows the calls to process while initializing the - // unlock map but then forces them to wait until it's initialized before making modifications to - // it. - { - std::lock_guard lg{m_lock}; - m_is_game_loaded = true; - m_framecount = 0; - LoadUnlockData([](ResponseType r_type) {}); - ActivateDeactivateAchievements(); - ActivateDeactivateLeaderboards(); - ActivateDeactivateRichPresence(); - } - FetchBadges(); - // Reset this to zero so that RP immediately triggers on the first frame - m_last_ping_time = 0; - INFO_LOG_FMT(ACHIEVEMENTS, "RetroAchievements successfully loaded for {}.", m_game_data.title); - - m_update_callback(); - callback(fetch_game_data_response); + std::lock_guard lg{m_filereader_lock}; + rc_hash_filereader volume_reader{ + .open = (volume) ? &AchievementManager::FilereaderOpenByVolume : + &AchievementManager::FilereaderOpenByFilepath, + .seek = &AchievementManager::FilereaderSeek, + .tell = &AchievementManager::FilereaderTell, + .read = &AchievementManager::FilereaderRead, + .close = &AchievementManager::FilereaderClose, + }; + rc_hash_init_custom_filereader(&volume_reader); + rc_client_begin_identify_and_load_game(m_client, RC_CONSOLE_GAMECUBE, file_path.c_str(), NULL, 0, + LoadGameCallback, NULL); } bool AchievementManager::IsGameLoaded() const { - return m_is_game_loaded; -} - -void AchievementManager::LoadUnlockData(const ResponseCallback& callback) -{ - if (!Config::Get(Config::RA_ENABLED) || !HasAPIToken()) - { - callback(ResponseType::NOT_ENABLED); - return; - } - m_queue.EmplaceItem([this, callback] { - const auto hardcore_unlock_response = FetchUnlockData(true); - if (hardcore_unlock_response != ResponseType::SUCCESS) - { - ERROR_LOG_FMT(ACHIEVEMENTS, - "Failed to fetch hardcore unlock data; skipping softcore unlock."); - callback(hardcore_unlock_response); - return; - } - - callback(FetchUnlockData(false)); - m_update_callback(); - }); -} - -void AchievementManager::ActivateDeactivateAchievements() -{ - std::lock_guard lg{m_lock}; - if (!Config::Get(Config::RA_ENABLED) || !HasAPIToken()) - return; - bool enabled = Config::Get(Config::RA_ACHIEVEMENTS_ENABLED); - bool unofficial = Config::Get(Config::RA_UNOFFICIAL_ENABLED); - bool encore = Config::Get(Config::RA_ENCORE_ENABLED); - for (u32 ix = 0; ix < m_game_data.num_achievements; ix++) - { - auto iter = - m_unlock_map.insert({m_game_data.achievements[ix].id, - UnlockStatus{.game_data_index = ix, - .points = m_game_data.achievements[ix].points, - .category = m_game_data.achievements[ix].category}}); - ActivateDeactivateAchievement(iter.first->first, enabled, unofficial, encore); - } - INFO_LOG_FMT(ACHIEVEMENTS, "Achievements (de)activated."); -} - -void AchievementManager::ActivateDeactivateLeaderboards() -{ - std::lock_guard lg{m_lock}; - if (!Config::Get(Config::RA_ENABLED) || !HasAPIToken()) - return; - bool leaderboards_enabled = - Config::Get(Config::RA_LEADERBOARDS_ENABLED) && Config::Get(Config::RA_HARDCORE_ENABLED); - for (u32 ix = 0; ix < m_game_data.num_leaderboards; ix++) - { - auto leaderboard = m_game_data.leaderboards[ix]; - u32 leaderboard_id = leaderboard.id; - if (m_is_game_loaded && leaderboards_enabled) - { - rc_runtime_activate_lboard(&m_runtime, leaderboard_id, leaderboard.definition, nullptr, 0); - m_queue.EmplaceItem([this, leaderboard_id] { - FetchBoardInfo(leaderboard_id); - m_update_callback(); - }); - } - else - { - rc_runtime_deactivate_lboard(&m_runtime, m_game_data.leaderboards[ix].id); - } - } - INFO_LOG_FMT(ACHIEVEMENTS, "Leaderboards (de)activated."); -} - -void AchievementManager::ActivateDeactivateRichPresence() -{ - std::lock_guard lg{m_lock}; - if (!Config::Get(Config::RA_ENABLED) || !HasAPIToken()) - return; - rc_runtime_activate_richpresence( - &m_runtime, - (m_is_game_loaded && Config::Get(Config::RA_RICH_PRESENCE_ENABLED)) ? - m_game_data.rich_presence_script : - "", - nullptr, 0); - INFO_LOG_FMT(ACHIEVEMENTS, "Rich presence (de)activated."); + auto* game_info = rc_client_get_game_info(m_client); + return game_info && game_info->id != 0; } void AchievementManager::FetchBadges() @@ -910,14 +650,9 @@ void AchievementManager::CloseGame() { { std::lock_guard lg{m_lock}; - if (m_is_game_loaded) + if (rc_client_get_game_info(m_client)) { - m_is_game_loaded = false; m_active_challenges.clear(); - ActivateDeactivateAchievements(); - ActivateDeactivateLeaderboards(); - ActivateDeactivateRichPresence(); - m_game_id = 0; m_game_badge.name.clear(); m_unlock_map.clear(); m_leaderboard_map.clear(); @@ -925,6 +660,7 @@ void AchievementManager::CloseGame() m_game_data = {}; m_queue.Cancel(); m_image_queue.Cancel(); + rc_client_unload_game(m_client); m_system = nullptr; } } @@ -1070,157 +806,6 @@ void AchievementManager::LoginCallback(int result, const char* error_message, rc Config::SetBaseOrCurrent(Config::RA_API_TOKEN, user->token); } -AchievementManager::ResponseType AchievementManager::ResolveHash(const Hash& game_hash, - u32* game_id) -{ - rc_api_resolve_hash_response_t hash_data{}; - std::string username, api_token; - { - std::lock_guard lg{m_lock}; - username = Config::Get(Config::RA_USERNAME); - api_token = Config::Get(Config::RA_API_TOKEN); - } - rc_api_resolve_hash_request_t resolve_hash_request = { - .username = username.c_str(), .api_token = api_token.c_str(), .game_hash = game_hash.data()}; - ResponseType r_type = Request( - resolve_hash_request, &hash_data, rc_api_init_resolve_hash_request, - rc_api_process_resolve_hash_response); - if (r_type == ResponseType::SUCCESS) - { - *game_id = hash_data.game_id; - INFO_LOG_FMT(ACHIEVEMENTS, "Hashed game ID {} for RetroAchievements.", *game_id); - } - else - { - INFO_LOG_FMT(ACHIEVEMENTS, "Hash {} not recognized by RetroAchievements.", game_hash.data()); - } - rc_api_destroy_resolve_hash_response(&hash_data); - return r_type; -} - -AchievementManager::ResponseType AchievementManager::StartRASession() -{ - rc_api_start_session_request_t start_session_request; - rc_api_start_session_response_t session_data{}; - std::string username, api_token; - { - std::lock_guard lg{m_lock}; - username = Config::Get(Config::RA_USERNAME); - api_token = Config::Get(Config::RA_API_TOKEN); - start_session_request = { - .username = username.c_str(), .api_token = api_token.c_str(), .game_id = m_game_id}; - } - ResponseType r_type = Request( - start_session_request, &session_data, rc_api_init_start_session_request, - rc_api_process_start_session_response); - rc_api_destroy_start_session_response(&session_data); - return r_type; -} - -AchievementManager::ResponseType AchievementManager::FetchGameData() -{ - rc_api_fetch_game_data_request_t fetch_data_request; - rc_api_request_t api_request; - Common::HttpRequest http_request; - std::string username, api_token; - u32 game_id; - { - std::lock_guard lg{m_lock}; - username = Config::Get(Config::RA_USERNAME); - api_token = Config::Get(Config::RA_API_TOKEN); - game_id = m_game_id; - } - fetch_data_request = { - .username = username.c_str(), .api_token = api_token.c_str(), .game_id = game_id}; - if (rc_api_init_fetch_game_data_request(&api_request, &fetch_data_request) != RC_OK || - !api_request.post_data) - { - ERROR_LOG_FMT(ACHIEVEMENTS, "Invalid API request for game data."); - return ResponseType::INVALID_REQUEST; - } - auto http_response = http_request.Post(api_request.url, api_request.post_data); - rc_api_destroy_request(&api_request); - if (!http_response.has_value() || http_response->size() == 0) - { - WARN_LOG_FMT(ACHIEVEMENTS, - "RetroAchievements connection failed while fetching game data for ID {}. \nURL: " - "{} \npost_data: {}", - game_id, api_request.url, - api_request.post_data == nullptr ? "NULL" : api_request.post_data); - return ResponseType::CONNECTION_FAILED; - } - std::lock_guard lg{m_lock}; - const std::string response_str(http_response->begin(), http_response->end()); - if (rc_api_process_fetch_game_data_response(&m_game_data, response_str.c_str()) != RC_OK) - { - ERROR_LOG_FMT(ACHIEVEMENTS, - "Failed to process HTTP response fetching game data for ID {}. \nURL: {} " - "\npost_data: {} \nresponse: {}", - game_id, api_request.url, - api_request.post_data == nullptr ? "NULL" : api_request.post_data, response_str); - rc_api_destroy_fetch_game_data_response(&m_game_data); - m_game_data = {}; - return ResponseType::MALFORMED_OBJECT; - } - if (!m_game_data.response.succeeded) - { - WARN_LOG_FMT( - ACHIEVEMENTS, - "Invalid RetroAchievements credentials fetching game data for ID {}; logging out user {}", - game_id, username); - // Logout technically does this via a CloseGame call, but doing this now prevents the activate - // methods from thinking they have something to do. - rc_api_destroy_fetch_game_data_response(&m_game_data); - m_game_data = {}; - Logout(); - return ResponseType::INVALID_CREDENTIALS; - } - if (game_id != m_game_id) - { - INFO_LOG_FMT(ACHIEVEMENTS, - "Attempted to retrieve game data for ID {}; running game is now ID {}", game_id, - m_game_id); - rc_api_destroy_fetch_game_data_response(&m_game_data); - m_game_data = {}; - return ResponseType::EXPIRED_CONTEXT; - } - INFO_LOG_FMT(ACHIEVEMENTS, "Retrieved game data for ID {}.", game_id); - return ResponseType::SUCCESS; -} - -AchievementManager::ResponseType AchievementManager::FetchUnlockData(bool hardcore) -{ - rc_api_fetch_user_unlocks_response_t unlock_data{}; - std::string username = Config::Get(Config::RA_USERNAME); - std::string api_token = Config::Get(Config::RA_API_TOKEN); - rc_api_fetch_user_unlocks_request_t fetch_unlocks_request = {.username = username.c_str(), - .api_token = api_token.c_str(), - .game_id = m_game_id, - .hardcore = hardcore}; - ResponseType r_type = - Request( - fetch_unlocks_request, &unlock_data, rc_api_init_fetch_user_unlocks_request, - rc_api_process_fetch_user_unlocks_response); - if (r_type == ResponseType::SUCCESS) - { - std::lock_guard lg{m_lock}; - bool enabled = Config::Get(Config::RA_ACHIEVEMENTS_ENABLED); - bool unofficial = Config::Get(Config::RA_UNOFFICIAL_ENABLED); - bool encore = Config::Get(Config::RA_ENCORE_ENABLED); - for (AchievementId ix = 0; ix < unlock_data.num_achievement_ids; ix++) - { - auto it = m_unlock_map.find(unlock_data.achievement_ids[ix]); - if (it == m_unlock_map.end()) - continue; - it->second.remote_unlock_status = - hardcore ? UnlockStatus::UnlockType::HARDCORE : UnlockStatus::UnlockType::SOFTCORE; - ActivateDeactivateAchievement(unlock_data.achievement_ids[ix], enabled, unofficial, encore); - } - } - rc_api_destroy_fetch_user_unlocks_response(&unlock_data); - return r_type; -} - AchievementManager::ResponseType AchievementManager::FetchBoardInfo(AchievementId leaderboard_id) { std::string username = Config::Get(Config::RA_USERNAME); @@ -1440,6 +1025,27 @@ AchievementManager::PingRichPresence(const RichPresence& rich_presence) return r_type; } +void AchievementManager::LoadGameCallback(int result, const char* error_message, + rc_client_t* client, void* userdata) +{ + if (result != RC_OK) + { + WARN_LOG_FMT(ACHIEVEMENTS, "Failed to load data for current game."); + return; + } + + auto* game = rc_client_get_game_info(client); + if (!game) + { + ERROR_LOG_FMT(ACHIEVEMENTS, "Failed to retrieve game information from client."); + return; + } + INFO_LOG_FMT(ACHIEVEMENTS, "Loaded data for game ID {}.", game->id); + + AchievementManager::GetInstance().FetchBadges(); + AchievementManager::GetInstance().m_system = &Core::System::GetInstance(); +} + void AchievementManager::DisplayWelcomeMessage() { std::lock_guard lg{m_lock}; diff --git a/Source/Core/Core/AchievementManager.h b/Source/Core/Core/AchievementManager.h index b385e9ed30..7412913fa6 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -119,14 +119,9 @@ public: void SetUpdateCallback(UpdateCallback callback); void Login(const std::string& password); bool HasAPIToken() const; - void HashGame(const std::string& file_path, const ResponseCallback& callback); - void HashGame(const DiscIO::Volume* volume, const ResponseCallback& callback); + void LoadGame(const std::string& file_path, const DiscIO::Volume* volume); bool IsGameLoaded() const; - void LoadUnlockData(const ResponseCallback& callback); - void ActivateDeactivateAchievements(); - void ActivateDeactivateLeaderboards(); - void ActivateDeactivateRichPresence(); void FetchBadges(); void DoFrame(); @@ -173,11 +168,7 @@ private: static void LoginCallback(int result, const char* error_message, rc_client_t* client, void* userdata); - ResponseType ResolveHash(const Hash& game_hash, u32* game_id); - void LoadGameSync(const ResponseCallback& callback); - ResponseType StartRASession(); - ResponseType FetchGameData(); - ResponseType FetchUnlockData(bool hardcore); + ResponseType FetchBoardInfo(AchievementId leaderboard_id); std::unique_ptr& GetLoadingVolume() { return m_loading_volume; }; @@ -189,6 +180,8 @@ private: ResponseType SubmitLeaderboard(AchievementId leaderboard_id, int value); ResponseType PingRichPresence(const RichPresence& rich_presence); + static void LoadGameCallback(int result, const char* error_message, rc_client_t* client, + void* userdata); void DisplayWelcomeMessage(); void HandleAchievementTriggeredEvent(const rc_runtime_event_t* runtime_event); diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp index 538308ef4f..d57f4e74bb 100644 --- a/Source/Core/Core/Boot/Boot.cpp +++ b/Source/Core/Core/Boot/Boot.cpp @@ -576,8 +576,7 @@ bool CBoot::BootUp(Core::System& system, const Core::CPUThreadGuard& guard, } #ifdef USE_RETRO_ACHIEVEMENTS - AchievementManager::GetInstance().HashGame(executable.path, - [](AchievementManager::ResponseType r_type) {}); + AchievementManager::GetInstance().LoadGame(executable.path, nullptr); #endif // USE_RETRO_ACHIEVEMENTS if (!executable.reader->LoadIntoMemory(system)) diff --git a/Source/Core/Core/HW/DVD/DVDInterface.cpp b/Source/Core/Core/HW/DVD/DVDInterface.cpp index adf16777ab..fefa5f2d2d 100644 --- a/Source/Core/Core/HW/DVD/DVDInterface.cpp +++ b/Source/Core/Core/HW/DVD/DVDInterface.cpp @@ -399,8 +399,7 @@ void DVDInterface::SetDisc(std::unique_ptr disc, } #ifdef USE_RETRO_ACHIEVEMENTS - AchievementManager::GetInstance().HashGame(disc.get(), - [](AchievementManager::ResponseType r_type) {}); + AchievementManager::GetInstance().LoadGame("", disc.get()); #endif // USE_RETRO_ACHIEVEMENTS // Assume that inserting a disc requires having an empty disc before diff --git a/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp b/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp index 01e1470175..040b26ca31 100644 --- a/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp +++ b/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp @@ -268,19 +268,16 @@ void AchievementSettingsWidget::Logout() void AchievementSettingsWidget::ToggleAchievements() { SaveSettings(); - AchievementManager::GetInstance().ActivateDeactivateAchievements(); } void AchievementSettingsWidget::ToggleLeaderboards() { SaveSettings(); - AchievementManager::GetInstance().ActivateDeactivateLeaderboards(); } void AchievementSettingsWidget::ToggleRichPresence() { SaveSettings(); - AchievementManager::GetInstance().ActivateDeactivateRichPresence(); } void AchievementSettingsWidget::ToggleHardcore() @@ -311,13 +308,11 @@ void AchievementSettingsWidget::ToggleBadges() void AchievementSettingsWidget::ToggleUnofficial() { SaveSettings(); - AchievementManager::GetInstance().ActivateDeactivateAchievements(); } void AchievementSettingsWidget::ToggleEncore() { SaveSettings(); - AchievementManager::GetInstance().ActivateDeactivateAchievements(); } #endif // USE_RETRO_ACHIEVEMENTS