Achievements: Attempt relogin on system boot
And display an error notification if login fails, instead of invalidating the token.
This commit is contained in:
parent
0f76543685
commit
e43d7046ba
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 122.88 111.24"><defs><style>.cls-1{fill:#fec901;fill-rule:evenodd;}.cls-2{fill:#010101;}</style></defs><title>risk</title><path d="M2.5,85l43-74.41h0a22.59,22.59,0,0,1,8-8.35,15.72,15.72,0,0,1,16,0,22.52,22.52,0,0,1,7.93,8.38l.23.44,42.08,73.07a20.91,20.91,0,0,1,3,10.84A16.44,16.44,0,0,1,121,102.4a15.45,15.45,0,0,1-5.74,6,21,21,0,0,1-11.35,2.78v0H17.7c-.21,0-.43,0-.64,0a19,19,0,0,1-7.83-1.74,15.83,15.83,0,0,1-6.65-5.72A16.26,16.26,0,0,1,0,95.18a21.66,21.66,0,0,1,2.2-9.62c.1-.2.2-.4.31-.59Z"/><path class="cls-1" d="M9.09,88.78l43-74.38c5.22-8.94,13.49-9.2,18.81,0l42.32,73.49c4.12,6.79,2.41,15.9-9.31,15.72H17.7C9.78,103.79,5,97.44,9.09,88.78Z"/><path class="cls-2" d="M57.55,83.15a5.47,5.47,0,0,1,5.85-1.22,5.65,5.65,0,0,1,2,1.3A5.49,5.49,0,0,1,67,86.77a5.12,5.12,0,0,1-.08,1.4,5.22,5.22,0,0,1-.42,1.34,5.51,5.51,0,0,1-5.2,3.25,5.63,5.63,0,0,1-2.26-.53,5.51,5.51,0,0,1-2.81-2.92A6,6,0,0,1,55.9,88a5.28,5.28,0,0,1,0-1.31h0a6,6,0,0,1,.56-2,4.6,4.6,0,0,1,1.14-1.56Zm8.12-10.21c-.19,4.78-8.28,4.78-8.46,0-.82-8.19-2.92-27.63-2.85-35.32.07-2.37,2-3.78,4.55-4.31a11.65,11.65,0,0,1,2.48-.25,12.54,12.54,0,0,1,2.5.25c2.59.56,4.63,2,4.63,4.43V38l-2.84,35Z"/></svg>
|
After Width: | Height: | Size: 1.2 KiB |
|
@ -137,6 +137,7 @@ static void ReportRCError(int err, fmt::format_string<T...> fmt, T&&... args);
|
|||
static void ClearGameInfo();
|
||||
static void ClearGameHash();
|
||||
static std::string GetGameHash(CDImage* image);
|
||||
static bool TryLoggingInWithToken();
|
||||
static void SetHardcoreMode(bool enabled, bool force_display_message);
|
||||
static bool IsLoggedInOrLoggingIn();
|
||||
static bool CanEnableHardcoreMode();
|
||||
|
@ -583,24 +584,7 @@ bool Achievements::Initialize()
|
|||
if (System::IsValid())
|
||||
IdentifyGame(System::GetDiscPath(), nullptr);
|
||||
|
||||
std::string username = Host::GetBaseStringSettingValue("Cheevos", "Username");
|
||||
std::string api_token = Host::GetBaseStringSettingValue("Cheevos", "Token");
|
||||
if (!username.empty() && !api_token.empty())
|
||||
{
|
||||
INFO_LOG("Attempting login with user '{}'...", username);
|
||||
|
||||
// If we can't decrypt the token, it was an old config and we need to re-login.
|
||||
if (const TinyString decrypted_api_token = DecryptLoginToken(api_token, username); !decrypted_api_token.empty())
|
||||
{
|
||||
s_state.login_request = rc_client_begin_login_with_token(
|
||||
s_state.client, username.c_str(), decrypted_api_token.c_str(), ClientLoginWithTokenCallback, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
WARNING_LOG("Invalid encrypted login token, requesitng a new one.");
|
||||
Host::OnAchievementsLoginRequested(LoginRequestReason::TokenInvalid);
|
||||
}
|
||||
}
|
||||
TryLoggingInWithToken();
|
||||
|
||||
// Hardcore mode isn't enabled when achievements first starts, if a game is already running.
|
||||
if (System::IsValid() && IsLoggedInOrLoggingIn() && g_settings.achievements_hardcore_mode)
|
||||
|
@ -649,6 +633,36 @@ void Achievements::DestroyClient(rc_client_t** client, std::unique_ptr<HTTPDownl
|
|||
http->reset();
|
||||
}
|
||||
|
||||
bool Achievements::TryLoggingInWithToken()
|
||||
{
|
||||
std::string username = Host::GetBaseStringSettingValue("Cheevos", "Username");
|
||||
std::string api_token = Host::GetBaseStringSettingValue("Cheevos", "Token");
|
||||
if (username.empty() || api_token.empty())
|
||||
return false;
|
||||
|
||||
INFO_LOG("Attempting token login with user '{}'...", username);
|
||||
|
||||
// If we can't decrypt the token, it was an old config and we need to re-login.
|
||||
if (const TinyString decrypted_api_token = DecryptLoginToken(api_token, username); !decrypted_api_token.empty())
|
||||
{
|
||||
s_state.login_request = rc_client_begin_login_with_token(
|
||||
s_state.client, username.c_str(), decrypted_api_token.c_str(), ClientLoginWithTokenCallback, nullptr);
|
||||
if (!s_state.login_request)
|
||||
{
|
||||
WARNING_LOG("Creating login request failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
WARNING_LOG("Invalid encrypted login token, requesitng a new one.");
|
||||
Host::OnAchievementsLoginRequested(LoginRequestReason::TokenInvalid);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Achievements::UpdateSettings(const Settings& old_config)
|
||||
{
|
||||
if (IsUsingRAIntegration())
|
||||
|
@ -976,7 +990,7 @@ void Achievements::UpdateRichPresence(std::unique_lock<std::recursive_mutex>& lo
|
|||
lock.lock();
|
||||
}
|
||||
|
||||
void Achievements::GameChanged(const std::string& path, CDImage* image)
|
||||
void Achievements::GameChanged(const std::string& path, CDImage* image, bool booting)
|
||||
{
|
||||
std::unique_lock lock(s_state.mutex);
|
||||
|
||||
|
@ -984,6 +998,15 @@ void Achievements::GameChanged(const std::string& path, CDImage* image)
|
|||
return;
|
||||
|
||||
IdentifyGame(path, image);
|
||||
|
||||
// if we're not logged in, and there's no login request, retry logging in
|
||||
// this'll happen if we had no network connection on startup, but gained it before starting a game.
|
||||
// follow the same order as Initialize() - identify, then log in
|
||||
if (!IsLoggedInOrLoggingIn() && booting)
|
||||
{
|
||||
WARNING_LOG("Not logged in on game booting, trying again.");
|
||||
TryLoggingInWithToken();
|
||||
}
|
||||
}
|
||||
|
||||
void Achievements::IdentifyGame(const std::string& path, CDImage* image)
|
||||
|
@ -1985,12 +2008,32 @@ void Achievements::ClientLoginWithTokenCallback(int result, const char* error_me
|
|||
{
|
||||
s_state.login_request = nullptr;
|
||||
|
||||
if (result != RC_OK)
|
||||
if (result == RC_INVALID_CREDENTIALS || result == RC_EXPIRED_TOKEN)
|
||||
{
|
||||
ReportFmtError("Login failed: {}", error_message);
|
||||
ERROR_LOG("Login failed due to invalid token: {}: {}", rc_error_str(result), error_message);
|
||||
Host::OnAchievementsLoginRequested(LoginRequestReason::TokenInvalid);
|
||||
return;
|
||||
}
|
||||
else if (result != RC_OK)
|
||||
{
|
||||
ERROR_LOG("Login failed: {}: {}", rc_error_str(result), error_message);
|
||||
|
||||
// only display user error if they've started a game
|
||||
if (System::IsValid())
|
||||
{
|
||||
std::string message =
|
||||
fmt::format("Achievement unlocks will not be submitted for this session.\nError: {}", error_message);
|
||||
GPUThread::RunOnThread([message = std::move(message)]() mutable {
|
||||
if (!GPUThread::HasGPUBackend() || !FullscreenUI::Initialize())
|
||||
return;
|
||||
|
||||
ImGuiFullscreen::AddNotification("AchievementsLoginFailed", Host::OSD_ERROR_DURATION,
|
||||
"RetroAchievements Login Failed", std::move(message), "images/warning.svg");
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ShowLoginSuccess(client);
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ bool Login(const char* username, const char* password, Error* error);
|
|||
void Logout();
|
||||
|
||||
/// Called when the system changes game, or is booting.
|
||||
void GameChanged(const std::string& path, CDImage* image);
|
||||
void GameChanged(const std::string& path, CDImage* image, bool booting);
|
||||
|
||||
/// Re-enables hardcore mode if it is enabled in the settings.
|
||||
bool ResetHardcoreMode(bool is_booting);
|
||||
|
|
|
@ -2014,7 +2014,7 @@ void System::ClearRunningGame()
|
|||
|
||||
Host::OnGameChanged(s_state.running_game_path, s_state.running_game_serial, s_state.running_game_title);
|
||||
|
||||
Achievements::GameChanged(s_state.running_game_path, nullptr);
|
||||
Achievements::GameChanged(s_state.running_game_path, nullptr, false);
|
||||
|
||||
UpdateRichPresence(true);
|
||||
}
|
||||
|
@ -4175,7 +4175,7 @@ void System::UpdateRunningGame(const std::string& path, CDImage* image, bool boo
|
|||
if (booting)
|
||||
Achievements::ResetHardcoreMode(true);
|
||||
|
||||
Achievements::GameChanged(s_state.running_game_path, image);
|
||||
Achievements::GameChanged(s_state.running_game_path, image, booting);
|
||||
|
||||
// game layer reloads cheats, but only the active list, we need new files
|
||||
Cheats::ReloadCheats(true, false, false, true);
|
||||
|
|
|
@ -3219,7 +3219,8 @@ void ImGuiFullscreen::DrawNotifications(ImVec2& position, float spacing)
|
|||
const ImVec2 badge_max(badge_min.x + badge_size, badge_min.y + badge_size);
|
||||
if (!notif.badge_path.empty())
|
||||
{
|
||||
GPUTexture* tex = GetCachedTexture(notif.badge_path.c_str());
|
||||
GPUTexture* tex =
|
||||
GetCachedTexture(notif.badge_path.c_str(), static_cast<u32>(badge_size), static_cast<u32>(badge_size));
|
||||
if (tex)
|
||||
{
|
||||
dl->AddImage(tex, badge_min, badge_max, ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f),
|
||||
|
|
Loading…
Reference in New Issue