I can't count the number of times where someone backed up just the file
store without the realm database and lost data. As such this moves the
"IMPORTANT READ ME" disclaimer a directory higher and attempts to
describe the "proper" backup procedure in detail.
People don't read, but maybe this will at least partially lower the
volume.
With `ReplayPlayer` now consuming the `LeaderboardManager`'s global
state, flows such as presenting a score need to set the global state up
correctly to avoid accidentally showing a leaderboard from a completely
different score.
This also incidentally closes https://github.com/ppy/osu/issues/27609.
RFC. Another attempt at this.
- Supersedes https://github.com/ppy/osu/pull/31881
- Supersedes / closes https://github.com/ppy/osu/pull/31355
- Closes https://github.com/ppy/osu/issues/29861
This is a weird diff because I am feeling rather boxed in by all the
constraints, namely that:
- Leaderboard state should be global state
- But the global state is essentially managed by song select and namely
`BeatmapLeaderboard` itself. That's because trying to e.g. not have
`BeatmapLeaderboard` pass the beatmap and the ruleset to the global
leaderboard manager is worse, as it essentially introduces two
parallel paths of execution that need to be somehow merged into one
(as in I'd have to somehow sync `LeaderboardManager` responding to
beatmap/ruleset changes with `BeatmapLeaderboard` which is inheritance
hell)
- Also local leaderboard fetching is data-push (as in the scores can
change under the leaderboard manager), and online leaderboard fetching
is data-pull (as in the scores do not change unless the leaderboard
manager does something). Also online leaderboard fetching can fail.
Which is why I need to still have the weird setup wherein there's a
`FetchWithCriteriaAsync()` (because I need to be able to respond to
online requests taking time, or failing), but also the
`BeatmapLeaderboard` only uses the public `Scores` bindable to
actually read the scores (because it needs to respond to new local
scores arriving).
- Another thing to think about here is what happens when a retrieval
fails because e.g. the user requested friend leaderboards without
having supporter. With how this diff is written, that special
condition is handled to `BeatmapLeaderboard`, and
`LeaderboardManager`'s state will remain as whatever it was before
that scope change was requested, which may be considered good or it
may not (I imagine it's better to show scores in gameplay than not in
this case, but maybe I'm wrong?)
Whomst've thought this was an ok thing to do? How did this pass review?
Let's leave these as rhetorical questions right now. Huge chances are
I'd implicate myself with at least one of them.
I'm not sure why this was "fine" for as long as it apparently was,
but what `MusicController` was doing was completely incorrect and
playing with fire (accessing raw managed realm objects), which went
wrong somewhere around - admittedly -
https://github.com/ppy/osu/pull/29917, likely because that one started
*storing* these raw managed realm objects to fields, and you know what
will happen to those after you do a migration and recycle realms.
To attempt to circumvent this, (ab)use `DetachedBeatmapStore` instead.
Which does necessitate moving it to `OsuGameBase`, but it's the simplest
way out I can see. I guess the alternative would be to faff around with
`Live<T>` but it's ugly and I'm attempting to fix this relatively quick
right now.
Noticed in passing.
```
Exit code is 134 (Unhandled exception. System.NullReferenceException:
Object reference not set to an instance of an object.
at osu.Game.OsuGameBase.onExceptionThrown(Exception ex) in
/Users/dean/Projects/osu/osu.Game/OsuGameBase.cs:line 695
at osu.Framework.Platform.GameHost.abortExecutionFromException(Object
sender, Exception exception, Boolean isTerminating)
at osu.Framework.Platform.GameHost.unobservedExceptionHandler(Object
sender, UnobservedTaskExceptionEventArgs args)
at System.Threading.Tasks.TaskExceptionHolder.Finalize())
```
People were deleting files they shouldn't, causing osu! to lose track of
where the real user files are.
For now let's just keep things simple and not let the users know that
some files got left behind. Usually the files which are left behind are
minimal and it should be fine to leave this up to the user.
Closes https://github.com/ppy/osu/issues/29505.
This class was only used in two places, both on the results screen, but
was holding references to `OsuPlayfield` game-wide (due to unrelated
issues, but still).
Because I can't really think of future use cases for this, and running
the calculation twice at results screen isn't a huge overhead, let's
just do that for now to keep things simple.
This avoids it ever mutating the underlying track (aka attempting to start
it). Resolves the one caveat mentioned in
aeef92fa710648d4a00edc523e13c17ac6104125.
The new implementation of `DecouplingClock` will not mutate the
underlying clock in any way (unless attempting to start it when
approaching from a negative time value).
This should be quite safe as a result.