-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Fix score no longer being saved when quick-restarting after pass #30937
Fix score no longer being saved when quick-restarting after pass #30937
Conversation
Tests failing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic seems sound, but tests need addressing.
Thanks to tests for pointing that out :blobsweat:
osu.Game/Screens/Play/Player.cs
Outdated
// if we're called externally (i.e. from results screen), | ||
// use MakeCurrent to exit results screen as well as this player screen | ||
// since ValidForResume = false in here | ||
Debug.Assert(!ValidForResume); | ||
this.MakeCurrent(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This hurts my head. I guess at least there's an inline comment next to it but it's still a solution I'd classify as convoluted at best.
Can this not be done any simpler? I'd much rather have a duplicated PerformExit()
call in the original code in the RestartRequested
block or something than this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bdach does this read any better to you?
diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs
index 3a0a0613f3..1866ed26ce 100644
--- a/osu.Game/Screens/Play/Player.cs
+++ b/osu.Game/Screens/Play/Player.cs
@@ -646,7 +646,6 @@ protected bool PerformExit(bool skipTransition = false)
// import current score if possible.
prepareAndImportScoreAsync();
- // Screen may not be current if a restart has been performed.
if (this.IsCurrentScreen())
{
skipExitTransition = skipTransition;
@@ -657,6 +656,12 @@ protected bool PerformExit(bool skipTransition = false)
// - the pause / fail dialog was requested but couldn't be displayed due to the type or state of this Player instance.
this.Exit();
}
+ else
+ {
+ // May be restarting from results screen.
+ if (this.GetChildScreen() != null)
+ this.MakeCurrent();
+ }
return true;
}
@@ -722,16 +727,6 @@ public bool Restart(bool quickRestart = false)
skipExitTransition = quickRestart;
PrepareLoaderForRestart?.Invoke(quickRestart);
- if (!this.IsCurrentScreen())
- {
- // if we're called externally (i.e. from results screen),
- // use MakeCurrent to exit results screen as well as this player screen
- // since ValidForResume = false in here
- Debug.Assert(!ValidForResume);
- this.MakeCurrent();
- return true;
- }
-
return PerformExit(quickRestart);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem I have is the whole "making a non-valid-for-resume screen current in order to implicitly exit it" shebang. Not the positioning of it in code. So I guess that's a no.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An alternative option I can imagine would be to move the Restart
method to PlayerLoader
instead and choose between calling Player.PerformExit()
and PlayerLoader.MakeCurrent()
based on whether player is current screen. That will solve the hack of making a non-valid-for-resume screen current.
It also generally makes sense for PlayerLoader
to expose restarting as that's what's really doing the "restarting" process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An alternative option I can imagine would be to move the
Restart
method toPlayerLoader
instead and choose between callingPlayer.PerformExit()
andPlayerLoader.MakeCurrent()
based on whether player is current screen.
Yeah I don't know if I'd consider this better.
Maybe this is fine if there really is no saner alternative, I dunno.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I say we just choose one and go with it. Can reassess next time the code is touched.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will say that I have attempted my proposal above just to see where it goes and how bad/good would it be, but upon stumbling across some existing test code that relies on the current structure I halted down immediately as totally not worth the effort.
I like peppy's diff as it makes the logic look more appropriate than it is currently, pushed in fa87df6.
@@ -83,7 +83,7 @@ public abstract partial class Player : ScreenWithBeatmapBackground, ISamplePlayb | |||
/// </summary> | |||
protected virtual bool PauseOnFocusLost => true; | |||
|
|||
public Action<bool> RestartRequested; | |||
public Action<bool> PrepareLoaderForRestart; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's with the rename? I preferred the old name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd say it's because the PlayerLoader
is no longer responsible for performing the restart, ie. calling this.MakeCurrent()
. the Requested
terminology implies that another component is going to make the decision of whether a restart should actually occur.
Co-authored-by: Dean Herbert <[email protected]>
// May be restarting from results screen. | ||
if (this.GetChildScreen() != null) | ||
this.MakeCurrent(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have ignored adding back the !ValidForResume
assertion as I think it's a given since the screen is not current and the current screen is presumed to be the results screen.
The
PerformExit
path ensures the score is imported even if the user restarts after passing the beatmap during the one second completion delayRESULTS_DISPLAY_DELAY
.In #30623,
Restart
no longer callsPerformExit
, therefore discarding the score for the scenario in question.I've resolved the issue by still calling
PerformExit
rather than letting thePlayerLoader
do the exiting process.I wanted to write a test case for this but timing is critical, I'll have to change the constant to be overridable and make my test case set the delay to infinity, but it feels weird to break parts of the component itself in order to test it. I can still write a test case if wanted.