1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-28 08:02:55 +08:00

Forcibly change ruleset to correct one before entering gameplay from main menu

Closes #25663 (again).

As it turns out, in some scenarios it can be the case that the current
game-global `Beatmap` is not valid for the current game-global
`Ruleset`. The validity of one and the other in conjunction is only
really validated by the song select screen; elsewhere there is no
guarantee that the global beatmap is playable using the global ruleset.

However, this only comes up in very specific circumstances, namely one:
when trying to autoplay a catch beatmap with osu! ruleset globally
active via the skin editor flow.

`Player` is responsible for retrieving the beatmap to be played. It does
so by invoking the appropriate beatmap converter and asking it if the
beatmap can be converted:

	6d64538d7a/osu.Game/Beatmaps/WorkingBeatmap.cs (L262-L266)

If the code above throws, `Player` actually silently covers for this, by
trying the beatmap's default ruleset instead:

	6d64538d7a/osu.Game/Screens/Play/Player.cs (L529-L536)

However, for the pairing of osu! ruleset and catch beatmap, this fails,
as `OsuBeatmapConverter`'s condition necessary for permitting conversion
is that the objects have a defined position:

	6d64538d7a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs (L25)

which they will do, due to the fact that all catch beatmaps are really
just osu! beatmaps but with conversion steps applied, and thus `Player`
succeeds to load the catch beatmap in osu! ruleset.

In the skin editor scenario, this would lead to the secondary failure
of the skin editor trying to apply `CatchModAutoplay` on top of all
of that, which would fail at the hard-cast of the beatmap
to `CatchBeatmap`.
This commit is contained in:
Bartłomiej Dach 2023-12-06 10:12:25 +01:00
parent faf60cec91
commit f239d03d75
No known key found for this signature in database

View File

@ -17,6 +17,7 @@ using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Graphics.Containers;
using osu.Game.Input.Bindings;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Scoring;
using osu.Game.Screens;
@ -58,6 +59,9 @@ namespace osu.Game.Overlays.SkinEditor
[Resolved]
private Bindable<IReadOnlyList<Mod>> mods { get; set; } = null!;
[Resolved]
private Bindable<RulesetInfo> ruleset { get; set; } = null!;
[Resolved]
private IBindable<WorkingBeatmap> beatmap { get; set; } = null!;
@ -153,7 +157,11 @@ namespace osu.Game.Overlays.SkinEditor
if (screen is Player)
return;
var replayGeneratingMod = beatmap.Value.BeatmapInfo.Ruleset.CreateInstance().GetAutoplayMod();
// the validity of the current game-wide beatmap + ruleset combination is enforced by song select.
// if we're anywhere else, the state is unknown and may not make sense, so forcibly set something that does.
if (screen is not PlaySongSelect)
ruleset.Value = beatmap.Value.BeatmapInfo.Ruleset;
var replayGeneratingMod = ruleset.Value.CreateInstance().GetAutoplayMod();
IReadOnlyList<Mod> usableMods = mods.Value;