mirror of
https://github.com/ppy/osu
synced 2025-03-02 01:21:19 +00:00
Merge pull request #22032 from frenzibyte/fix-potential-difficulty-failure-alt
Fix advanced statistics display potentially performing invalid difficulty calculation
This commit is contained in:
commit
e3932c077b
@ -160,9 +160,12 @@ namespace osu.Game
|
|||||||
|
|
||||||
protected Bindable<WorkingBeatmap> Beatmap { get; private set; } // cached via load() method
|
protected Bindable<WorkingBeatmap> Beatmap { get; private set; } // cached via load() method
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The current ruleset selection for the local user.
|
||||||
|
/// </summary>
|
||||||
[Cached]
|
[Cached]
|
||||||
[Cached(typeof(IBindable<RulesetInfo>))]
|
[Cached(typeof(IBindable<RulesetInfo>))]
|
||||||
protected readonly Bindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
|
protected internal readonly Bindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current mod selection for the local user.
|
/// The current mod selection for the local user.
|
||||||
|
@ -30,14 +30,16 @@ namespace osu.Game.Screens.Select.Details
|
|||||||
{
|
{
|
||||||
public partial class AdvancedStats : Container
|
public partial class AdvancedStats : Container
|
||||||
{
|
{
|
||||||
|
[Resolved]
|
||||||
|
private BeatmapDifficultyCache difficultyCache { get; set; }
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private IBindable<IReadOnlyList<Mod>> mods { get; set; }
|
private IBindable<IReadOnlyList<Mod>> mods { get; set; }
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private IBindable<RulesetInfo> ruleset { get; set; }
|
private OsuGameBase game { get; set; }
|
||||||
|
|
||||||
[Resolved]
|
private IBindable<RulesetInfo> gameRuleset;
|
||||||
private BeatmapDifficultyCache difficultyCache { get; set; }
|
|
||||||
|
|
||||||
protected readonly StatisticRow FirstValue, HpDrain, Accuracy, ApproachRate;
|
protected readonly StatisticRow FirstValue, HpDrain, Accuracy, ApproachRate;
|
||||||
private readonly StatisticRow starDifficulty;
|
private readonly StatisticRow starDifficulty;
|
||||||
@ -84,7 +86,13 @@ namespace osu.Game.Screens.Select.Details
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
ruleset.BindValueChanged(_ => updateStatistics());
|
// the cached ruleset bindable might be a decoupled bindable provided by SongSelect,
|
||||||
|
// which we can't rely on in combination with the game-wide selected mods list,
|
||||||
|
// since mods could be updated to the new ruleset instances while the decoupled bindable is held behind,
|
||||||
|
// therefore resulting in performing difficulty calculation with invalid states.
|
||||||
|
gameRuleset = game.Ruleset.GetBoundCopy();
|
||||||
|
gameRuleset.BindValueChanged(_ => updateStatistics());
|
||||||
|
|
||||||
mods.BindValueChanged(modsChanged, true);
|
mods.BindValueChanged(modsChanged, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +150,14 @@ namespace osu.Game.Screens.Select.Details
|
|||||||
|
|
||||||
private CancellationTokenSource starDifficultyCancellationSource;
|
private CancellationTokenSource starDifficultyCancellationSource;
|
||||||
|
|
||||||
private void updateStarDifficulty()
|
/// <summary>
|
||||||
|
/// Updates the displayed star difficulty statistics with the values provided by the currently-selected beatmap, ruleset, and selected mods.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is scheduled to avoid scenarios wherein a ruleset changes first before selected mods do,
|
||||||
|
/// potentially resulting in failure during difficulty calculation due to incomplete bindable state updates.
|
||||||
|
/// </remarks>
|
||||||
|
private void updateStarDifficulty() => Scheduler.AddOnce(() =>
|
||||||
{
|
{
|
||||||
starDifficultyCancellationSource?.Cancel();
|
starDifficultyCancellationSource?.Cancel();
|
||||||
|
|
||||||
@ -151,8 +166,8 @@ namespace osu.Game.Screens.Select.Details
|
|||||||
|
|
||||||
starDifficultyCancellationSource = new CancellationTokenSource();
|
starDifficultyCancellationSource = new CancellationTokenSource();
|
||||||
|
|
||||||
var normalStarDifficultyTask = difficultyCache.GetDifficultyAsync(BeatmapInfo, ruleset.Value, null, starDifficultyCancellationSource.Token);
|
var normalStarDifficultyTask = difficultyCache.GetDifficultyAsync(BeatmapInfo, gameRuleset.Value, null, starDifficultyCancellationSource.Token);
|
||||||
var moddedStarDifficultyTask = difficultyCache.GetDifficultyAsync(BeatmapInfo, ruleset.Value, mods.Value, starDifficultyCancellationSource.Token);
|
var moddedStarDifficultyTask = difficultyCache.GetDifficultyAsync(BeatmapInfo, gameRuleset.Value, mods.Value, starDifficultyCancellationSource.Token);
|
||||||
|
|
||||||
Task.WhenAll(normalStarDifficultyTask, moddedStarDifficultyTask).ContinueWith(_ => Schedule(() =>
|
Task.WhenAll(normalStarDifficultyTask, moddedStarDifficultyTask).ContinueWith(_ => Schedule(() =>
|
||||||
{
|
{
|
||||||
@ -164,7 +179,7 @@ namespace osu.Game.Screens.Select.Details
|
|||||||
|
|
||||||
starDifficulty.Value = ((float)normalDifficulty.Value.Stars, (float)moddedDifficulty.Value.Stars);
|
starDifficulty.Value = ((float)normalDifficulty.Value.Stars, (float)moddedDifficulty.Value.Stars);
|
||||||
}), starDifficultyCancellationSource.Token, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Current);
|
}), starDifficultyCancellationSource.Token, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Current);
|
||||||
}
|
});
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user