1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-27 15:53:19 +08:00

Add beatmap loading timeout

This commit is contained in:
smoogipoo 2020-03-13 13:52:40 +09:00
parent 8fb41e4c67
commit f7c036726a
2 changed files with 61 additions and 41 deletions

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Audio.Track; using osu.Framework.Audio.Track;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
@ -60,8 +61,9 @@ namespace osu.Game.Beatmaps
/// </summary> /// </summary>
/// <param name="ruleset">The <see cref="RulesetInfo"/> to create a playable <see cref="IBeatmap"/> for.</param> /// <param name="ruleset">The <see cref="RulesetInfo"/> to create a playable <see cref="IBeatmap"/> for.</param>
/// <param name="mods">The <see cref="Mod"/>s to apply to the <see cref="IBeatmap"/>.</param> /// <param name="mods">The <see cref="Mod"/>s to apply to the <see cref="IBeatmap"/>.</param>
/// <param name="timeout">The loading timeout.</param>
/// <returns>The converted <see cref="IBeatmap"/>.</returns> /// <returns>The converted <see cref="IBeatmap"/>.</returns>
/// <exception cref="BeatmapInvalidForRulesetException">If <see cref="Beatmap"/> could not be converted to <paramref name="ruleset"/>.</exception> /// <exception cref="BeatmapInvalidForRulesetException">If <see cref="Beatmap"/> could not be converted to <paramref name="ruleset"/>.</exception>
IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList<Mod> mods = null); IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList<Mod> mods = null, TimeSpan? timeout = null);
} }
} }

View File

@ -83,7 +83,9 @@ namespace osu.Game.Beatmaps
/// <returns>The applicable <see cref="IBeatmapConverter"/>.</returns> /// <returns>The applicable <see cref="IBeatmapConverter"/>.</returns>
protected virtual IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) => ruleset.CreateBeatmapConverter(beatmap); protected virtual IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) => ruleset.CreateBeatmapConverter(beatmap);
public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList<Mod> mods = null) public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList<Mod> mods = null, TimeSpan? timeout = null)
{
using (var cancellationSource = new CancellationTokenSource(timeout ?? TimeSpan.FromSeconds(10)))
{ {
mods ??= Array.Empty<Mod>(); mods ??= Array.Empty<Mod>();
@ -97,7 +99,10 @@ namespace osu.Game.Beatmaps
// Apply conversion mods // Apply conversion mods
foreach (var mod in mods.OfType<IApplicableToBeatmapConverter>()) foreach (var mod in mods.OfType<IApplicableToBeatmapConverter>())
{
cancellationSource.Token.ThrowIfCancellationRequested();
mod.ApplyToBeatmapConverter(converter); mod.ApplyToBeatmapConverter(converter);
}
// Convert // Convert
IBeatmap converted = converter.Convert(); IBeatmap converted = converter.Convert();
@ -109,8 +114,11 @@ namespace osu.Game.Beatmaps
converted.BeatmapInfo.BaseDifficulty = converted.BeatmapInfo.BaseDifficulty.Clone(); converted.BeatmapInfo.BaseDifficulty = converted.BeatmapInfo.BaseDifficulty.Clone();
foreach (var mod in mods.OfType<IApplicableToDifficulty>()) foreach (var mod in mods.OfType<IApplicableToDifficulty>())
{
cancellationSource.Token.ThrowIfCancellationRequested();
mod.ApplyToDifficulty(converted.BeatmapInfo.BaseDifficulty); mod.ApplyToDifficulty(converted.BeatmapInfo.BaseDifficulty);
} }
}
IBeatmapProcessor processor = rulesetInstance.CreateBeatmapProcessor(converted); IBeatmapProcessor processor = rulesetInstance.CreateBeatmapProcessor(converted);
@ -118,21 +126,31 @@ namespace osu.Game.Beatmaps
// Compute default values for hitobjects, including creating nested hitobjects in-case they're needed // Compute default values for hitobjects, including creating nested hitobjects in-case they're needed
foreach (var obj in converted.HitObjects) foreach (var obj in converted.HitObjects)
{
cancellationSource.Token.ThrowIfCancellationRequested();
obj.ApplyDefaults(converted.ControlPointInfo, converted.BeatmapInfo.BaseDifficulty); obj.ApplyDefaults(converted.ControlPointInfo, converted.BeatmapInfo.BaseDifficulty);
}
foreach (var mod in mods.OfType<IApplicableToHitObject>()) foreach (var mod in mods.OfType<IApplicableToHitObject>())
{ {
foreach (var obj in converted.HitObjects) foreach (var obj in converted.HitObjects)
{
cancellationSource.Token.ThrowIfCancellationRequested();
mod.ApplyToHitObject(obj); mod.ApplyToHitObject(obj);
} }
}
processor?.PostProcess(); processor?.PostProcess();
foreach (var mod in mods.OfType<IApplicableToBeatmap>()) foreach (var mod in mods.OfType<IApplicableToBeatmap>())
{
cancellationSource.Token.ThrowIfCancellationRequested();
mod.ApplyToBeatmap(converted); mod.ApplyToBeatmap(converted);
}
return converted; return converted;
} }
}
private CancellationTokenSource loadCancellation = new CancellationTokenSource(); private CancellationTokenSource loadCancellation = new CancellationTokenSource();