From d176ce791678c808782c6961dd6b322d254798c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 31 Jul 2025 10:09:05 +0200 Subject: [PATCH 1/2] Ensure scores are re-fetched with correct criteria on re-entering song select Closes https://github.com/ppy/osu/issues/34445. The primary issue is that song select is the only one that supports non-score sort mode, and therefore if any other component changes the sort mode in a way opaque to song select to score, then song select will lose the sort mode because it's using the global leaderboard manager's state which will contain scores sorted by total. Notably, the bug this is fixing requires specific circumstances. For instance, it is not enough to just *start gameplay* for the bug to manifest, because starting gameplay causes a working beatmap refetch: https://github.com/ppy/osu/blob/4b73afd1957a9161e2956fc4191c8114d9958372/osu.Game/Screens/SelectV2/SongSelect.cs#L456-L457 which will trigger a *delayed schedule refetch* of the scores: https://github.com/ppy/osu/blob/d2d3d14f1572ff8fc68fd01ea43c2ef68b5882fa/osu.Game/Screens/SelectV2/BeatmapLeaderboardWedge.cs#L235-L253 and because the refetch is thusly delayed, there's a very high chance it *will not run before the screen is resumed* because the wedge will not have its scheduler run until that point in time. This conundrum is also because there is no test coverage for this, because the above makes test coverage setup rather annoying. --- .../Screens/SelectV2/BeatmapDetailsArea.cs | 6 ++++++ .../SelectV2/BeatmapLeaderboardWedge.cs | 18 +++++++++--------- osu.Game/Screens/SelectV2/SongSelect.cs | 2 ++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/SelectV2/BeatmapDetailsArea.cs b/osu.Game/Screens/SelectV2/BeatmapDetailsArea.cs index 85bbf34837..7a2068b0cf 100644 --- a/osu.Game/Screens/SelectV2/BeatmapDetailsArea.cs +++ b/osu.Game/Screens/SelectV2/BeatmapDetailsArea.cs @@ -97,5 +97,11 @@ namespace osu.Game.Screens.SelectV2 contentContainer.Add(currentContent); currentContent.Show(); } + + public void Refresh() + { + if (currentContent is BeatmapLeaderboardWedge leaderboardWedge) + leaderboardWedge.RefetchScores(); + } } } diff --git a/osu.Game/Screens/SelectV2/BeatmapLeaderboardWedge.cs b/osu.Game/Screens/SelectV2/BeatmapLeaderboardWedge.cs index 259ce8565b..0b845474dd 100644 --- a/osu.Game/Screens/SelectV2/BeatmapLeaderboardWedge.cs +++ b/osu.Game/Screens/SelectV2/BeatmapLeaderboardWedge.cs @@ -189,14 +189,14 @@ namespace osu.Game.Screens.SelectV2 { base.LoadComplete(); - Scope.BindValueChanged(_ => refetchScores()); - Sorting.BindValueChanged(_ => refetchScores()); - FilterBySelectedMods.BindValueChanged(_ => refetchScores()); - beatmap.BindValueChanged(_ => refetchScores()); - ruleset.BindValueChanged(_ => refetchScores()); + Scope.BindValueChanged(_ => RefetchScores()); + Sorting.BindValueChanged(_ => RefetchScores()); + FilterBySelectedMods.BindValueChanged(_ => RefetchScores()); + beatmap.BindValueChanged(_ => RefetchScores()); + ruleset.BindValueChanged(_ => RefetchScores()); mods.BindValueChanged(_ => refetchScoresFromMods()); - refetchScores(); + RefetchScores(); } protected override void PopIn() @@ -212,14 +212,14 @@ namespace osu.Game.Screens.SelectV2 private void refetchScoresFromMods() { if (FilterBySelectedMods.Value) - refetchScores(); + RefetchScores(); } private bool initialFetchComplete; private ScheduledDelegate? refetchOperation; - private void refetchScores() + public void RefetchScores() { SetScores(Array.Empty()); @@ -477,7 +477,7 @@ namespace osu.Game.Screens.SelectV2 case LeaderboardState.NetworkFailure: return new ClickablePlaceholder(LeaderboardStrings.CouldntFetchScores, FontAwesome.Solid.Sync) { - Action = refetchScores + Action = RefetchScores }; case LeaderboardState.NoneSelected: diff --git a/osu.Game/Screens/SelectV2/SongSelect.cs b/osu.Game/Screens/SelectV2/SongSelect.cs index edc94953da..51150df384 100644 --- a/osu.Game/Screens/SelectV2/SongSelect.cs +++ b/osu.Game/Screens/SelectV2/SongSelect.cs @@ -595,6 +595,8 @@ namespace osu.Game.Screens.SelectV2 ensureGlobalBeatmapValid(); + detailsArea.Refresh(); + if (ControlGlobalMusic) { // restart playback on returning to song select, regardless. From 7a263efaa2a689e2e539ce5df1527e217cdf82cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 31 Jul 2025 10:10:14 +0200 Subject: [PATCH 2/2] Always fetch leaderboard with score sort mode in solo results This is borderline pedantic and mostly irrelevant but I think it makes some sense for a bit of extra safety. It definitely does not fix any bugs (that I'm aware of). --- osu.Game/Screens/Ranking/SoloResultsScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Ranking/SoloResultsScreen.cs b/osu.Game/Screens/Ranking/SoloResultsScreen.cs index 2d772e5f09..aeb21b09cb 100644 --- a/osu.Game/Screens/Ranking/SoloResultsScreen.cs +++ b/osu.Game/Screens/Ranking/SoloResultsScreen.cs @@ -41,12 +41,12 @@ namespace osu.Game.Screens.Ranking { Debug.Assert(Score != null); + // sort mode intentionally omitted to default to score - results screen only supports sorting by score, so don't pass any other to avoid confusion var criteria = new LeaderboardCriteria( Score.BeatmapInfo!, Score.Ruleset, leaderboardManager.CurrentCriteria?.Scope ?? BeatmapLeaderboardScope.Global, - leaderboardManager.CurrentCriteria?.ExactMods, - leaderboardManager.CurrentCriteria?.Sorting ?? LeaderboardSortMode.Score + leaderboardManager.CurrentCriteria?.ExactMods ); var requestTaskSource = new TaskCompletionSource(); globalScores.BindValueChanged(_ =>