mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 05:32:54 +08:00
Merge pull request #24450 from cdwcgt/missing-beatmap
Fetch missing beatmap when importing replay
This commit is contained in:
commit
067c487b21
@ -0,0 +1,97 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Database;
|
||||||
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Online.API.Requests;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Tests.Resources;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Online
|
||||||
|
{
|
||||||
|
public partial class TestSceneReplayMissingBeatmap : OsuGameTestScene
|
||||||
|
{
|
||||||
|
private DummyAPIAccess dummyAPI => (DummyAPIAccess)API;
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSceneMissingBeatmapWithOnlineAvailable()
|
||||||
|
{
|
||||||
|
var beatmap = new APIBeatmap
|
||||||
|
{
|
||||||
|
OnlineBeatmapSetID = 173612,
|
||||||
|
BeatmapSet = new APIBeatmapSet
|
||||||
|
{
|
||||||
|
Title = "FREEDOM Dive",
|
||||||
|
Artist = "xi",
|
||||||
|
Covers = new BeatmapSetOnlineCovers
|
||||||
|
{
|
||||||
|
Card = "https://assets.ppy.sh/beatmaps/173612/covers/card@2x.jpg"
|
||||||
|
},
|
||||||
|
OnlineID = 173612
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
setupBeatmapResponse(beatmap);
|
||||||
|
|
||||||
|
AddStep("import score", () =>
|
||||||
|
{
|
||||||
|
using (var resourceStream = TestResources.OpenResource("Replays/mania-replay.osr"))
|
||||||
|
{
|
||||||
|
var importTask = new ImportTask(resourceStream, "replay.osr");
|
||||||
|
|
||||||
|
Game.ScoreManager.Import(new[] { importTask });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("Replay missing notification show", () => Game.Notifications.ChildrenOfType<MissingBeatmapNotification>().Any());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSceneMissingBeatmapWithOnlineUnavailable()
|
||||||
|
{
|
||||||
|
setupFailedResponse();
|
||||||
|
|
||||||
|
AddStep("import score", () =>
|
||||||
|
{
|
||||||
|
using (var resourceStream = TestResources.OpenResource("Replays/mania-replay.osr"))
|
||||||
|
{
|
||||||
|
var importTask = new ImportTask(resourceStream, "replay.osr");
|
||||||
|
|
||||||
|
Game.ScoreManager.Import(new[] { importTask });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("Replay missing notification not show", () => !Game.Notifications.ChildrenOfType<MissingBeatmapNotification>().Any());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupBeatmapResponse(APIBeatmap b)
|
||||||
|
=> AddStep("setup response", () =>
|
||||||
|
{
|
||||||
|
dummyAPI.HandleRequest = request =>
|
||||||
|
{
|
||||||
|
if (request is GetBeatmapRequest getBeatmapRequest)
|
||||||
|
{
|
||||||
|
getBeatmapRequest.TriggerSuccess(b);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
private void setupFailedResponse()
|
||||||
|
=> AddStep("setup failed response", () =>
|
||||||
|
{
|
||||||
|
dummyAPI.HandleRequest = request =>
|
||||||
|
{
|
||||||
|
request.TriggerFailure(new WebException());
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Database;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
using osu.Game.Tests.Scores.IO;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.UserInterface
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public partial class TestSceneMissingBeatmapNotification : OsuTestScene
|
||||||
|
{
|
||||||
|
[Cached]
|
||||||
|
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
Child = new Container
|
||||||
|
{
|
||||||
|
Width = 280,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Child = new MissingBeatmapNotification(CreateAPIBeatmapSet(Ruleset.Value).Beatmaps.First(), new ImportScoreTest.TestArchiveReader(), "deadbeef")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -26,6 +26,7 @@ using osu.Game.Overlays.Notifications;
|
|||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osu.Game.Utils;
|
using osu.Game.Utils;
|
||||||
|
using Realms;
|
||||||
|
|
||||||
namespace osu.Game.Beatmaps
|
namespace osu.Game.Beatmaps
|
||||||
{
|
{
|
||||||
@ -284,7 +285,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="query">The query.</param>
|
/// <param name="query">The query.</param>
|
||||||
/// <returns>The first result for the provided query, or null if no results were found.</returns>
|
/// <returns>The first result for the provided query, or null if no results were found.</returns>
|
||||||
public BeatmapInfo? QueryBeatmap(Expression<Func<BeatmapInfo, bool>> query) => Realm.Run(r => r.All<BeatmapInfo>().FirstOrDefault(query)?.Detach());
|
public BeatmapInfo? QueryBeatmap(Expression<Func<BeatmapInfo, bool>> query) => Realm.Run(r => r.All<BeatmapInfo>().Filter($"{nameof(BeatmapInfo.BeatmapSet)}.{nameof(BeatmapSetInfo.DeletePending)} == false").FirstOrDefault(query)?.Detach());
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A default representation of a WorkingBeatmap to use when no beatmap is available.
|
/// A default representation of a WorkingBeatmap to use when no beatmap is available.
|
||||||
|
@ -20,14 +20,24 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
protected override Drawable IdleContent => idleBottomContent;
|
protected override Drawable IdleContent => idleBottomContent;
|
||||||
protected override Drawable DownloadInProgressContent => downloadProgressBar;
|
protected override Drawable DownloadInProgressContent => downloadProgressBar;
|
||||||
|
|
||||||
|
public override float Width
|
||||||
|
{
|
||||||
|
get => base.Width;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
base.Width = value;
|
||||||
|
|
||||||
|
if (LoadState >= LoadState.Ready)
|
||||||
|
buttonContainer.Width = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private const float height = 60;
|
private const float height = 60;
|
||||||
private const float width = 300;
|
private const float width = 300;
|
||||||
private const float cover_width = 80;
|
|
||||||
|
|
||||||
[Cached]
|
[Cached]
|
||||||
private readonly BeatmapCardContent content;
|
private readonly BeatmapCardContent content;
|
||||||
|
|
||||||
private BeatmapCardThumbnail thumbnail = null!;
|
|
||||||
private CollapsibleButtonContainer buttonContainer = null!;
|
private CollapsibleButtonContainer buttonContainer = null!;
|
||||||
|
|
||||||
private FillFlowContainer idleBottomContent = null!;
|
private FillFlowContainer idleBottomContent = null!;
|
||||||
@ -52,21 +62,15 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
{
|
{
|
||||||
c.MainContent = new Container
|
c.MainContent = new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = height,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
thumbnail = new BeatmapCardThumbnail(BeatmapSet)
|
|
||||||
{
|
|
||||||
Name = @"Left (icon) area",
|
|
||||||
Size = new Vector2(cover_width, height),
|
|
||||||
Padding = new MarginPadding { Right = CORNER_RADIUS },
|
|
||||||
},
|
|
||||||
buttonContainer = new CollapsibleButtonContainer(BeatmapSet)
|
buttonContainer = new CollapsibleButtonContainer(BeatmapSet)
|
||||||
{
|
{
|
||||||
X = cover_width - CORNER_RADIUS,
|
Width = Width,
|
||||||
Width = width - cover_width + CORNER_RADIUS,
|
|
||||||
FavouriteState = { BindTarget = FavouriteState },
|
FavouriteState = { BindTarget = FavouriteState },
|
||||||
ButtonsCollapsedWidth = CORNER_RADIUS,
|
ButtonsCollapsedWidth = 5,
|
||||||
ButtonsExpandedWidth = 30,
|
ButtonsExpandedWidth = 30,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
@ -160,7 +164,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
bool showDetails = IsHovered;
|
bool showDetails = IsHovered;
|
||||||
|
|
||||||
buttonContainer.ShowDetails.Value = showDetails;
|
buttonContainer.ShowDetails.Value = showDetails;
|
||||||
thumbnail.Dimmed.Value = showDetails;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ namespace osu.Game.Configuration
|
|||||||
SetDefault(OsuSetting.Username, string.Empty);
|
SetDefault(OsuSetting.Username, string.Empty);
|
||||||
SetDefault(OsuSetting.Token, string.Empty);
|
SetDefault(OsuSetting.Token, string.Empty);
|
||||||
|
|
||||||
SetDefault(OsuSetting.AutomaticallyDownloadWhenSpectating, false);
|
SetDefault(OsuSetting.AutomaticallyDownloadMissingBeatmaps, false);
|
||||||
|
|
||||||
SetDefault(OsuSetting.SavePassword, false).ValueChanged += enabled =>
|
SetDefault(OsuSetting.SavePassword, false).ValueChanged += enabled =>
|
||||||
{
|
{
|
||||||
@ -215,6 +215,12 @@ namespace osu.Game.Configuration
|
|||||||
|
|
||||||
// migrations can be added here using a condition like:
|
// migrations can be added here using a condition like:
|
||||||
// if (combined < 20220103) { performMigration() }
|
// if (combined < 20220103) { performMigration() }
|
||||||
|
if (combined < 20230918)
|
||||||
|
{
|
||||||
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
|
SetValue(OsuSetting.AutomaticallyDownloadMissingBeatmaps, Get<OsuSetting>(OsuSetting.AutomaticallyDownloadWhenSpectating)); // can be removed 20240618
|
||||||
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override TrackedSettings CreateTrackedSettings()
|
public override TrackedSettings CreateTrackedSettings()
|
||||||
@ -383,13 +389,17 @@ namespace osu.Game.Configuration
|
|||||||
EditorShowHitMarkers,
|
EditorShowHitMarkers,
|
||||||
EditorAutoSeekOnPlacement,
|
EditorAutoSeekOnPlacement,
|
||||||
DiscordRichPresence,
|
DiscordRichPresence,
|
||||||
|
|
||||||
|
[Obsolete($"Use {nameof(AutomaticallyDownloadMissingBeatmaps)} instead.")] // can be removed 20240318
|
||||||
AutomaticallyDownloadWhenSpectating,
|
AutomaticallyDownloadWhenSpectating,
|
||||||
|
|
||||||
ShowOnlineExplicitContent,
|
ShowOnlineExplicitContent,
|
||||||
LastProcessedMetadataId,
|
LastProcessedMetadataId,
|
||||||
SafeAreaConsiderations,
|
SafeAreaConsiderations,
|
||||||
ComboColourNormalisationAmount,
|
ComboColourNormalisationAmount,
|
||||||
ProfileCoverExpanded,
|
ProfileCoverExpanded,
|
||||||
EditorLimitedDistanceSnap,
|
EditorLimitedDistanceSnap,
|
||||||
ReplaySettingsOverlay
|
ReplaySettingsOverlay,
|
||||||
|
AutomaticallyDownloadMissingBeatmaps,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
103
osu.Game/Database/MissingBeatmapNotification.cs
Normal file
103
osu.Game/Database/MissingBeatmapNotification.cs
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.Drawables.Cards;
|
||||||
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.IO.Archives;
|
||||||
|
using osu.Game.Localisation;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Overlays.Notifications;
|
||||||
|
using osu.Game.Scoring;
|
||||||
|
using Realms;
|
||||||
|
|
||||||
|
namespace osu.Game.Database
|
||||||
|
{
|
||||||
|
public partial class MissingBeatmapNotification : SimpleNotification
|
||||||
|
{
|
||||||
|
[Resolved]
|
||||||
|
private BeatmapModelDownloader beatmapDownloader { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private ScoreManager scoreManager { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private RealmAccess realm { get; set; } = null!;
|
||||||
|
|
||||||
|
private readonly ArchiveReader scoreArchive;
|
||||||
|
private readonly APIBeatmapSet beatmapSetInfo;
|
||||||
|
private readonly string beatmapHash;
|
||||||
|
|
||||||
|
private Bindable<bool> autoDownloadConfig = null!;
|
||||||
|
private Bindable<bool> noVideoSetting = null!;
|
||||||
|
private BeatmapCardNano card = null!;
|
||||||
|
|
||||||
|
private IDisposable? realmSubscription;
|
||||||
|
|
||||||
|
public MissingBeatmapNotification(APIBeatmap beatmap, ArchiveReader scoreArchive, string beatmapHash)
|
||||||
|
{
|
||||||
|
beatmapSetInfo = beatmap.BeatmapSet!;
|
||||||
|
|
||||||
|
this.beatmapHash = beatmapHash;
|
||||||
|
this.scoreArchive = scoreArchive;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuConfigManager config)
|
||||||
|
{
|
||||||
|
realmSubscription = realm.RegisterForNotifications(
|
||||||
|
realm => realm.All<BeatmapSetInfo>().Where(s => !s.DeletePending), beatmapsChanged);
|
||||||
|
|
||||||
|
autoDownloadConfig = config.GetBindable<bool>(OsuSetting.AutomaticallyDownloadMissingBeatmaps);
|
||||||
|
noVideoSetting = config.GetBindable<bool>(OsuSetting.PreferNoVideo);
|
||||||
|
|
||||||
|
Content.Add(card = new BeatmapCardNano(beatmapSetInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
if (autoDownloadConfig.Value)
|
||||||
|
{
|
||||||
|
Text = NotificationsStrings.DownloadingBeatmapForReplay;
|
||||||
|
beatmapDownloader.Download(beatmapSetInfo, noVideoSetting.Value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool missingSetMatchesExistingOnlineId = realm.Run(r => r.All<BeatmapSetInfo>().Any(s => !s.DeletePending && s.OnlineID == beatmapSetInfo.OnlineID));
|
||||||
|
Text = missingSetMatchesExistingOnlineId ? NotificationsStrings.MismatchingBeatmapForReplay : NotificationsStrings.MissingBeatmapForReplay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
card.Width = Content.DrawWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void beatmapsChanged(IRealmCollection<BeatmapSetInfo> sender, ChangeSet? changes)
|
||||||
|
{
|
||||||
|
if (changes?.InsertedIndices == null) return;
|
||||||
|
|
||||||
|
if (sender.Any(s => s.Beatmaps.Any(b => b.MD5Hash == beatmapHash)))
|
||||||
|
{
|
||||||
|
string name = scoreArchive.Filenames.First(f => f.EndsWith(".osr", StringComparison.OrdinalIgnoreCase));
|
||||||
|
var importTask = new ImportTask(scoreArchive.GetStream(name), name);
|
||||||
|
scoreManager.Import(new[] { importTask });
|
||||||
|
realmSubscription?.Dispose();
|
||||||
|
Close(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
realmSubscription?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -93,6 +93,21 @@ Please try changing your audio device to a working setting.");
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static LocalisableString YourNameWasMentioned(string username) => new TranslatableString(getKey(@"your_name_was_mentioned"), @"Your name was mentioned in chat by '{0}'. Click to find out why!", username);
|
public static LocalisableString YourNameWasMentioned(string username) => new TranslatableString(getKey(@"your_name_was_mentioned"), @"Your name was mentioned in chat by '{0}'. Click to find out why!", username);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "You do not have the beatmap for this replay."
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString MissingBeatmapForReplay => new TranslatableString(getKey(@"missing_beatmap_for_replay"), @"You do not have the beatmap for this replay.");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Downloading missing beatmap for this replay..."
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString DownloadingBeatmapForReplay => new TranslatableString(getKey(@"downloading_beatmap_for_replay"), @"Downloading missing beatmap for this replay...");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Your local copy of the beatmap for this replay appears to be different than expected. You may need to update or re-download it."
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString MismatchingBeatmapForReplay => new TranslatableString(getKey(@"mismatching_beatmap_for_replay"), @"Your local copy of the beatmap for this replay appears to be different than expected. You may need to update or re-download it.");
|
||||||
|
|
||||||
private static string getKey(string key) => $@"{prefix}:{key}";
|
private static string getKey(string key) => $@"{prefix}:{key}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,9 +55,9 @@ namespace osu.Game.Localisation
|
|||||||
public static LocalisableString PreferNoVideo => new TranslatableString(getKey(@"prefer_no_video"), @"Prefer downloads without video");
|
public static LocalisableString PreferNoVideo => new TranslatableString(getKey(@"prefer_no_video"), @"Prefer downloads without video");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// "Automatically download beatmaps when spectating"
|
/// "Automatically download missing beatmaps"
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static LocalisableString AutomaticallyDownloadWhenSpectating => new TranslatableString(getKey(@"automatically_download_when_spectating"), @"Automatically download beatmaps when spectating");
|
public static LocalisableString AutomaticallyDownloadMissingBeatmaps => new TranslatableString(getKey(@"automatically_download_missing_beatmaps"), @"Automatically download missing beatmaps");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// "Show explicit content in search results"
|
/// "Show explicit content in search results"
|
||||||
|
@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Notifications
|
|||||||
|
|
||||||
public bool WasClosed { get; private set; }
|
public bool WasClosed { get; private set; }
|
||||||
|
|
||||||
private readonly Container content;
|
private readonly FillFlowContainer content;
|
||||||
|
|
||||||
protected override Container<Drawable> Content => content;
|
protected override Container<Drawable> Content => content;
|
||||||
|
|
||||||
@ -166,11 +166,13 @@ namespace osu.Game.Overlays.Notifications
|
|||||||
Padding = new MarginPadding(10),
|
Padding = new MarginPadding(10),
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
content = new Container
|
content = new FillFlowContainer
|
||||||
{
|
{
|
||||||
Masking = true,
|
Masking = true,
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Spacing = new Vector2(15)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -31,9 +31,9 @@ namespace osu.Game.Overlays.Settings.Sections.Online
|
|||||||
},
|
},
|
||||||
new SettingsCheckbox
|
new SettingsCheckbox
|
||||||
{
|
{
|
||||||
LabelText = OnlineSettingsStrings.AutomaticallyDownloadWhenSpectating,
|
LabelText = OnlineSettingsStrings.AutomaticallyDownloadMissingBeatmaps,
|
||||||
Keywords = new[] { "spectator" },
|
Keywords = new[] { "spectator", "replay" },
|
||||||
Current = config.GetBindable<bool>(OsuSetting.AutomaticallyDownloadWhenSpectating),
|
Current = config.GetBindable<bool>(OsuSetting.AutomaticallyDownloadMissingBeatmaps),
|
||||||
},
|
},
|
||||||
new SettingsCheckbox
|
new SettingsCheckbox
|
||||||
{
|
{
|
||||||
|
@ -54,7 +54,12 @@ namespace osu.Game.Scoring
|
|||||||
}
|
}
|
||||||
catch (LegacyScoreDecoder.BeatmapNotFoundException e)
|
catch (LegacyScoreDecoder.BeatmapNotFoundException e)
|
||||||
{
|
{
|
||||||
Logger.Log($@"Score '{name}' failed to import: no corresponding beatmap with the hash '{e.Hash}' could be found.", LoggingTarget.Database);
|
Logger.Log($@"Score '{archive.Name}' failed to import: no corresponding beatmap with the hash '{e.Hash}' could be found.", LoggingTarget.Database);
|
||||||
|
|
||||||
|
// In the case of a missing beatmap, let's attempt to resolve it and show a prompt to the user to download the required beatmap.
|
||||||
|
var req = new GetBeatmapRequest(new BeatmapInfo { MD5Hash = e.Hash });
|
||||||
|
req.Success += res => PostNotification?.Invoke(new MissingBeatmapNotification(res, archive, e.Hash));
|
||||||
|
api.Queue(req);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,7 @@ namespace osu.Game.Screens.Play
|
|||||||
automaticDownload = new SettingsCheckbox
|
automaticDownload = new SettingsCheckbox
|
||||||
{
|
{
|
||||||
LabelText = "Automatically download beatmaps",
|
LabelText = "Automatically download beatmaps",
|
||||||
Current = config.GetBindable<bool>(OsuSetting.AutomaticallyDownloadWhenSpectating),
|
Current = config.GetBindable<bool>(OsuSetting.AutomaticallyDownloadMissingBeatmaps),
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
},
|
},
|
||||||
|
@ -265,7 +265,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
Debug.Assert(original.BeatmapSet != null);
|
Debug.Assert(original.BeatmapSet != null);
|
||||||
|
|
||||||
return new APIBeatmapSet
|
var result = new APIBeatmapSet
|
||||||
{
|
{
|
||||||
OnlineID = original.BeatmapSet.OnlineID,
|
OnlineID = original.BeatmapSet.OnlineID,
|
||||||
Status = BeatmapOnlineStatus.Ranked,
|
Status = BeatmapOnlineStatus.Ranked,
|
||||||
@ -301,6 +301,11 @@ namespace osu.Game.Tests.Visual
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
foreach (var beatmap in result.Beatmaps)
|
||||||
|
beatmap.BeatmapSet = result;
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected WorkingBeatmap CreateWorkingBeatmap(RulesetInfo ruleset) =>
|
protected WorkingBeatmap CreateWorkingBeatmap(RulesetInfo ruleset) =>
|
||||||
|
Loading…
Reference in New Issue
Block a user