The import preparation task can actually be non-null when exiting even
if the player hasn't passed:
- fail beatmap
- click import button to import the failed replay
Closes https://github.com/ppy/osu/issues/25247.
The scenario involved here is as follows:
1. User completes beatmap by hitting all notes.
2. `checkScoreCompleted()` determines completion, and calls
`progressToResults(withDelay: true)`.
3. `progressToResults()` schedules `resultsDisplayDelegate`, which
includes a call to `prepareAndImportScoreAsync()`, a second in the
future.
4. User presses quick retry hotkey.
This calls `Player.Restart(quickRestart: true)`,
which invokes `Player.RestartRequested`,
which in turn calls `PlayerLoader.restartRequested(true)`,
which in turn causes `PlayerLoader` to make itself current,
which means that `Player.OnExiting()` will get called.
5. `Player.OnExiting()` sees that `prepareScoreForDisplayTask` is null
(because `prepareAndImportScoreAsync()` - which sets it -
is scheduled to happen in the future), and as such assumes that
the score did not complete. Thus, it marks the score as failed.
6. `Player.Restart()` after invoking `RestartRequested` calls
`PerformExit(false)`, which then will unconditionally call
`prepareAndImportScoreAsync()`. But the score has already been marked
as failed.
The flow above can be described as "convoluted", but I'm not sure I have
it in me right now to try and refactor it again. Therefore, to fix,
switch the `prepareScoreForDisplayTask` null check in
`Player.OnExiting()` to check `GameplayState.HasPassed` instead, as it
is not susceptible to the same out-of-order read issue.
Previously, for lazer scores, the ID returned from `osu-web` was
discarded and replaced with -1, due to the fact that the appropriate
structures for unification with stable, as well as unification across
solo and multiplayer, were not in place yet.
Now we're at the point where scores from all the aforementioned sources
receive a `solo_scores` DB row, and as such, we can start treating
`solo_scores`-scheme IDs as canonical "online IDs" for a score.
I've gone ahead and matched the osu!stable behaviour for this, as it
seems like it's what people are used to and they will settle for no
less.
Closes https://github.com/ppy/osu/issues/18089.
I also took the freedom to add type checking, as we can't limit the
usage of `Add()` since it's a Container. The exception thrown also
advises of using the suggested `AddTrigger()` instead.