Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add better submission failure messaging #27180

Merged
merged 3 commits into from
Feb 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion osu.Game/Screens/Play/SoloPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ protected override GameplayLeaderboard CreateGameplayLeaderboard() =>
Scores = { BindTarget = LeaderboardScores }
};

protected override bool HandleTokenRetrievalFailure(Exception exception) => false;
protected override bool ShouldExitOnTokenRetrievalFailure(Exception exception) => false;

protected override Task ImportScore(Score score)
{
Expand Down
39 changes: 24 additions & 15 deletions osu.Game/Screens/Play/SubmittingPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ private bool handleTokenRetrieval()
token = r.ID;
tcs.SetResult(true);
};
req.Failure += handleTokenFailure;
req.Failure += ex => handleTokenFailure(ex, displayNotification: true);

api.Queue(req);

Expand All @@ -128,40 +128,49 @@ private bool handleTokenRetrieval()

return true;

void handleTokenFailure(Exception exception)
void handleTokenFailure(Exception exception, bool displayNotification = false)
{
tcs.SetResult(false);

if (HandleTokenRetrievalFailure(exception))
bool shouldExit = ShouldExitOnTokenRetrievalFailure(exception);

if (displayNotification || shouldExit)
{
string whatWillHappen = shouldExit
? "Play in this state is not permitted."
: "Your score will not be submitted.";

if (string.IsNullOrEmpty(exception.Message))
Logger.Error(exception, "Failed to retrieve a score submission token.");
Logger.Error(exception, $"Failed to retrieve a score submission token.\n\n{whatWillHappen}");
else
{
switch (exception.Message)
{
case "expired token":
Logger.Log("Score submission failed because your system clock is set incorrectly. Please check your system time, date and timezone.", level: LogLevel.Important);
case @"missing token header":
case @"invalid client hash":
case @"invalid verification hash":
Logger.Log($"Please ensure that you are using the latest version of the official game releases.\n\n{whatWillHappen}", level: LogLevel.Important);
break;

case @"expired token":
Logger.Log($"Your system clock is set incorrectly. Please check your system time, date and timezone.\n\n{whatWillHappen}", level: LogLevel.Important);
break;

default:
Logger.Log($"You are not able to submit a score: {exception.Message}", level: LogLevel.Important);
Logger.Log($"{whatWillHappen} {exception.Message}", level: LogLevel.Important);
break;
}
}
}

if (shouldExit)
{
Schedule(() =>
{
ValidForResume = false;
this.Exit();
});
}
else
{
// Gameplay is allowed to continue, but we still should keep track of the error.
// In the future, this should be visible to the user in some way.
Logger.Log($"Score submission token retrieval failed ({exception.Message})");
}
}
}

Expand All @@ -170,7 +179,7 @@ void handleTokenFailure(Exception exception)
/// </summary>
/// <param name="exception">The error causing the failure.</param>
/// <returns>Whether gameplay should be immediately exited as a result. Returning false allows the gameplay session to continue. Defaults to true.</returns>
protected virtual bool HandleTokenRetrievalFailure(Exception exception) => true;
protected virtual bool ShouldExitOnTokenRetrievalFailure(Exception exception) => true;

protected override async Task PrepareScoreForResultsAsync(Score score)
{
Expand Down Expand Up @@ -231,7 +240,7 @@ private void submitFromFailOrQuit()

/// <summary>
/// Construct a request to be used for retrieval of the score token.
/// Can return null, at which point <see cref="HandleTokenRetrievalFailure"/> will be fired.
/// Can return null, at which point <see cref="ShouldExitOnTokenRetrievalFailure"/> will be fired.
/// </summary>
[CanBeNull]
protected abstract APIRequest<APIScoreToken> CreateTokenRequest();
Expand Down
2 changes: 1 addition & 1 deletion osu.Game/Tests/Visual/TestPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public TestPlayer(bool allowPause = true, bool showResults = true, bool pauseOnF
PauseOnFocusLost = pauseOnFocusLost;
}

protected override bool HandleTokenRetrievalFailure(Exception exception) => false;
protected override bool ShouldExitOnTokenRetrievalFailure(Exception exception) => false;

protected override APIRequest<APIScoreToken> CreateTokenRequest()
{
Expand Down
Loading