From 952fd0d493eb3cd9994ea8ff4e27b44e82c1f287 Mon Sep 17 00:00:00 2001 From: Krzysztof Gutkowski Date: Fri, 16 Jan 2026 16:38:00 +0100 Subject: [PATCH] Ensure diffcalc runs after mods get replaced during a ruleset change (#36359) --- .../SelectV2/BeatmapTitleWedge.DifficultyDisplay.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/SelectV2/BeatmapTitleWedge.DifficultyDisplay.cs b/osu.Game/Screens/SelectV2/BeatmapTitleWedge.DifficultyDisplay.cs index 65e55ff277..fc6ce0ac20 100644 --- a/osu.Game/Screens/SelectV2/BeatmapTitleWedge.DifficultyDisplay.cs +++ b/osu.Game/Screens/SelectV2/BeatmapTitleWedge.DifficultyDisplay.cs @@ -206,8 +206,13 @@ namespace osu.Game.Screens.SelectV2 { base.LoadComplete(); - beatmap.BindValueChanged(_ => updateDisplay()); - ruleset.BindValueChanged(_ => updateDisplay()); + // it is not uncommon for the beatmap and the ruleset to change in conjunction during a single update frame. + // in that process, it is possible for the global bindable triad (beatmap / ruleset / mods) to briefly be partially invalid in combination (e.g. mods invalid for given ruleset). + // `updateDisplay()` will initiate a difficulty calculation, and if it is allowed to run in that invalid intermediate state, it will loudly fail. + // therefore, all changes that may initiate a difficulty calculation are debounced until the next frame to ensure the global bindable state is fully consistent - + // and it's what you'd want to do anyway for performance reasons. + beatmap.BindValueChanged(_ => Scheduler.AddOnce(updateDisplay)); + ruleset.BindValueChanged(_ => Scheduler.AddOnce(updateDisplay)); mods.BindValueChanged(m => {