1
0
mirror of https://github.com/ppy/osu.git synced 2026-06-03 13:44:34 +08:00

Fix play button starting wrong beatmap before selection loads (#36104)

* Fix play button starting wrong beatmap before selection loads

When clicking the osu! cookie (play button) before a newly selected beatmap finishes loading, the previous beatmap would be played instead of the currently selected one. 

This was caused by the cookie reading from the global beatmap state which is debounced by 150ms, while the Enter key correctly used the carousel's current selection.

The fix makes the cookie use the same beatmap source as Enter - the carousel's current selection - which is always up-to-date regardless of debounce timing.

Closes #36074

* Use ensureGlobalBeatmapValid() for logo and Enter key actions

* Add test for beatmap selection timing bug

Tests the fix for issue #36074 where clicking the play button immediately after selecting a different difficulty would start the wrong beatmap due to the 150ms selection debounce.
This commit is contained in:
Jul
2026-01-05 06:54:25 +01:00
committed by GitHub
Unverified
parent b6dc64668e
commit ff820f730e
2 changed files with 47 additions and 0 deletions
@@ -659,6 +659,51 @@ namespace osu.Game.Tests.Visual.SongSelectV2
AddAssert("options disabled", () => !this.ChildrenOfType<FooterButtonOptions>().Single().Enabled.Value);
}
/// <summary>
/// tests that clicking the osu! logo immediately after selecting a different difficulty
/// (before the selection debounce completes) starts the correct beatmap.
/// this tests the fix for https://github.com/ppy/osu/issues/36074
/// </summary>
[Test]
public void TestPlayCorrectBeatmapWhenSelectionNotFullyLoaded()
{
// import a beatmap set with multiple difficulties
ImportBeatmapForRuleset(0);
LoadSongSelect();
// wait for initial beatmap to be selected
AddUntilStep("wait for first beatmap selected", () => !Beatmap.IsDefault);
BeatmapInfo? firstBeatmap = null;
AddStep("store first difficulty", () => firstBeatmap = Beatmap.Value.BeatmapInfo);
// start loading the first difficulty
AddStep("click logo to start loading", () => this.ChildrenOfType<OsuLogo>().Single().TriggerClick());
AddUntilStep("wait for player loader", () => Stack.CurrentScreen is PlayerLoader);
// return to song select
AddStep("press escape to return", () => InputManager.Key(Key.Escape));
AddUntilStep("wait for return to song select", () => SongSelect.IsCurrentScreen());
// press down and schedule logo click to happen shortly after (but before 150ms debounce)
// this reproduces the race condition where Beatmap.Value hasn't updated yet
AddStep("select next difficulty and click logo immediately", () =>
{
InputManager.Key(Key.Down);
Schedule(() => this.ChildrenOfType<OsuLogo>().Single().TriggerClick());
});
AddUntilStep("wait for player loader", () => Stack.CurrentScreen is PlayerLoader);
// verify we're loading the second difficulty, not the first
// without the fix, this would fail because Beatmap.Value still has the old value
AddAssert("player is loading second difficulty", () =>
Beatmap.Value.BeatmapInfo.ID != firstBeatmap!.ID);
AddUntilStep("wait for return to song select", () => SongSelect.IsCurrentScreen());
}
#endregion
}
}
+2
View File
@@ -756,6 +756,7 @@ namespace osu.Game.Screens.SelectV2
logo.Action = () =>
{
ensureGlobalBeatmapValid();
SelectAndRun(Beatmap.Value.BeatmapInfo, OnStart);
return false;
};
@@ -999,6 +1000,7 @@ namespace osu.Game.Screens.SelectV2
// one of which is filtering out all visible beatmaps and attempting to start gameplay.
// in that case, users still expect a `Select` press to advance to gameplay anyway, using the ambient selected beatmap if there is one,
// which matches the behaviour resulting from clicking the osu! cookie in that scenario.
ensureGlobalBeatmapValid();
SelectAndRun(Beatmap.Value.BeatmapInfo, OnStart);
return true;