1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-24 10:49:53 +08:00

Fix song select carousel sometimes teleporting on beatmap set deletion

Closes https://github.com/ppy/osu/issues/35010.

The issue here does not reproduce consistently, and is more or less
random in presentation. That said, using a large enough realm database
more or less ensures that the issue will present itself (in testing on a
large realm db, the failure rate is around ~50%).

This actually regressed in https://github.com/ppy/osu/pull/34842. The
core failure in this case is here:

	https://github.com/ppy/osu/blob/fd412618dba7399b1778b0902b73ffbae21a2399/osu.Game/Screens/SelectV2/BeatmapCarousel.cs#L161

The `CheckModelEquality()` call above is comparing two `BeatmapInfo`s,
but a84c364e44 changed the
`BeatmapInfo`-comparing path of `CheckModelEquality()` to use
`GroupedBeatmap` instead. Due to this, `CheckModelEquality()` falls back
to reference equality comparison for `BeatmapInfo`s. When that reference
comparison fails, the carousel stops detecting that the current
selection was deleted from under it correctly, and therefore the
proximity-based selection logic never runs.

Due to the human-obvious mechanism of failure and relatively easy
manual reproduction I've decided not to try and add tests for this,
as they are likely to take a long time to write due to the mechanism
of failure being incorrect use of reference equality specifically. That
said, I can try on request.
This commit is contained in:
Bartłomiej Dach
2025-09-30 11:32:15 +02:00
Unverified
parent 062174d874
commit a3e09a1c31
@@ -816,6 +816,11 @@ namespace osu.Game.Screens.SelectV2
if (x is GroupedBeatmap groupedBeatmapX && y is GroupedBeatmap groupedBeatmapY)
return groupedBeatmapX.Equals(groupedBeatmapY);
// `BeatmapInfo` is no longer used directly in carousel items, but in rare circumstances still is used for model equality comparisons
// (see `beatmapSetsChanged()` deletion handling logic, which aims to find a beatmap close to the just-deleted one, disregarding grouping concerns)
if (x is BeatmapInfo beatmapInfoX && y is BeatmapInfo beatmapInfoY)
return beatmapInfoX.Equals(beatmapInfoY);
if (x is GroupDefinition groupX && y is GroupDefinition groupY)
return groupX.Equals(groupY);