From 448574e7e67cba8ead7bf1c27e0b892d9fec3754 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Sat, 17 Apr 2021 17:33:53 +0200 Subject: [PATCH 01/29] Use `WorkingBeatmap` instead of `IBeatmap` This lets us access things like the background, track, etc. which are necessary for quality and filesize checks. Also improves the structure of the `CheckBackgroundTest` class in the process. --- .../Checks/CheckOffscreenObjectsTest.cs | 70 ++++++++----------- .../Edit/Checks/CheckOffscreenObjects.cs | 4 +- .../Edit/OsuBeatmapVerifier.cs | 2 +- .../Editing/Checks/CheckBackgroundTest.cs | 7 +- osu.Game/Rulesets/Edit/BeatmapVerifier.cs | 2 +- .../Rulesets/Edit/Checks/CheckBackground.cs | 10 +-- .../Rulesets/Edit/Checks/Components/ICheck.cs | 4 +- osu.Game/Rulesets/Edit/IBeatmapVerifier.cs | 2 +- osu.Game/Screens/Edit/Verify/VerifyScreen.cs | 3 +- 9 files changed, 46 insertions(+), 58 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs index f9445a9a96..db347960ef 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs @@ -10,6 +10,7 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Edit.Checks; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.UI; +using osu.Game.Tests.Beatmaps; using osuTK; namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks @@ -30,25 +31,23 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks [Test] public void TestCircleInCenter() { - var beatmap = new Beatmap + assertOk(new Beatmap { HitObjects = new List { new HitCircle { StartTime = 3000, - Position = playfield_centre // Playfield is 640 x 480. + Position = playfield_centre } } - }; - - Assert.That(check.Run(beatmap), Is.Empty); + }); } [Test] public void TestCircleNearEdge() { - var beatmap = new Beatmap + assertOk(new Beatmap { HitObjects = new List { @@ -58,15 +57,13 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks Position = new Vector2(5, 5) } } - }; - - Assert.That(check.Run(beatmap), Is.Empty); + }); } [Test] public void TestCircleNearEdgeStackedOffscreen() { - var beatmap = new Beatmap + assertOffscreenCircle(new Beatmap { HitObjects = new List { @@ -77,15 +74,13 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks StackHeight = 5 } } - }; - - assertOffscreenCircle(beatmap); + }); } [Test] public void TestCircleOffscreen() { - var beatmap = new Beatmap + assertOffscreenCircle(new Beatmap { HitObjects = new List { @@ -95,15 +90,13 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks Position = new Vector2(0, 0) } } - }; - - assertOffscreenCircle(beatmap); + }); } [Test] public void TestSliderInCenter() { - var beatmap = new Beatmap + assertOk(new Beatmap { HitObjects = new List { @@ -118,15 +111,13 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks }), } } - }; - - Assert.That(check.Run(beatmap), Is.Empty); + }); } [Test] public void TestSliderNearEdge() { - var beatmap = new Beatmap + assertOk(new Beatmap { HitObjects = new List { @@ -141,15 +132,13 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks }), } } - }; - - Assert.That(check.Run(beatmap), Is.Empty); + }); } [Test] public void TestSliderNearEdgeStackedOffscreen() { - var beatmap = new Beatmap + assertOk(new Beatmap { HitObjects = new List { @@ -165,15 +154,13 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks StackHeight = 5 } } - }; - - assertOffscreenSlider(beatmap); + }); } [Test] public void TestSliderOffscreenStart() { - var beatmap = new Beatmap + assertOffscreenSlider(new Beatmap { HitObjects = new List { @@ -188,15 +175,13 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks }), } } - }; - - assertOffscreenSlider(beatmap); + }); } [Test] public void TestSliderOffscreenEnd() { - var beatmap = new Beatmap + assertOffscreenSlider(new Beatmap { HitObjects = new List { @@ -211,15 +196,13 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks }), } } - }; - - assertOffscreenSlider(beatmap); + }); } [Test] public void TestSliderOffscreenPath() { - var beatmap = new Beatmap + assertOffscreenSlider(new Beatmap { HitObjects = new List { @@ -236,14 +219,17 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks }), } } - }; + }); + } - assertOffscreenSlider(beatmap); + private void assertOk(IBeatmap beatmap) + { + Assert.That(check.Run(new TestWorkingBeatmap(beatmap)), Is.Empty); } private void assertOffscreenCircle(IBeatmap beatmap) { - var issues = check.Run(beatmap).ToList(); + var issues = check.Run(new TestWorkingBeatmap(beatmap)).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckOffscreenObjects.IssueTemplateOffscreenCircle); @@ -251,7 +237,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks private void assertOffscreenSlider(IBeatmap beatmap) { - var issues = check.Run(beatmap).ToList(); + var issues = check.Run(new TestWorkingBeatmap(beatmap)).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckOffscreenObjects.IssueTemplateOffscreenSlider); diff --git a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs index 27cae2ecc1..54b167aaf3 100644 --- a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs +++ b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs @@ -31,9 +31,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Checks new IssueTemplateOffscreenSlider(this) }; - public IEnumerable Run(IBeatmap beatmap) + public IEnumerable Run(WorkingBeatmap workingBeatmap) { - foreach (var hitobject in beatmap.HitObjects) + foreach (var hitobject in workingBeatmap.Beatmap.HitObjects) { switch (hitobject) { diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs b/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs index 1c7ab00bbb..9b9383d547 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs @@ -17,6 +17,6 @@ namespace osu.Game.Rulesets.Osu.Edit new CheckOffscreenObjects() }; - public IEnumerable Run(IBeatmap beatmap) => checks.SelectMany(check => check.Run(beatmap)); + public IEnumerable Run(WorkingBeatmap workingBeatmap) => checks.SelectMany(check => check.Run(workingBeatmap)); } } diff --git a/osu.Game.Tests/Editing/Checks/CheckBackgroundTest.cs b/osu.Game.Tests/Editing/Checks/CheckBackgroundTest.cs index 635e3bb0f3..d61f0989a6 100644 --- a/osu.Game.Tests/Editing/Checks/CheckBackgroundTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckBackgroundTest.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit.Checks; using osu.Game.Rulesets.Objects; +using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Editing.Checks { @@ -14,13 +15,13 @@ namespace osu.Game.Tests.Editing.Checks public class CheckBackgroundTest { private CheckBackground check; - private IBeatmap beatmap; + private WorkingBeatmap beatmap; [SetUp] public void Setup() { check = new CheckBackground(); - beatmap = new Beatmap + beatmap = new TestWorkingBeatmap(new Beatmap { BeatmapInfo = new BeatmapInfo { @@ -33,7 +34,7 @@ namespace osu.Game.Tests.Editing.Checks }) } } - }; + }); } [Test] diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs index f9bced7beb..40714e8c7e 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs @@ -19,6 +19,6 @@ namespace osu.Game.Rulesets.Edit new CheckBackground(), }; - public IEnumerable Run(IBeatmap beatmap) => checks.SelectMany(check => check.Run(beatmap)); + public IEnumerable Run(WorkingBeatmap workingBeatmap) => checks.SelectMany(check => check.Run(workingBeatmap)); } } diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackground.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackground.cs index 93da42425c..d2fffeea4e 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackground.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackground.cs @@ -18,9 +18,9 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateDoesNotExist(this) }; - public IEnumerable Run(IBeatmap beatmap) + public IEnumerable Run(WorkingBeatmap workingBeatmap) { - if (beatmap.Metadata.BackgroundFile == null) + if (workingBeatmap.Metadata?.BackgroundFile == null) { yield return new IssueTemplateNoneSet(this).Create(); @@ -29,13 +29,13 @@ namespace osu.Game.Rulesets.Edit.Checks // If the background is set, also make sure it still exists. - var set = beatmap.BeatmapInfo.BeatmapSet; - var file = set.Files.FirstOrDefault(f => f.Filename == beatmap.Metadata.BackgroundFile); + var set = workingBeatmap.BeatmapInfo.BeatmapSet; + var file = set.Files.FirstOrDefault(f => f.Filename == workingBeatmap.Metadata.BackgroundFile); if (file != null) yield break; - yield return new IssueTemplateDoesNotExist(this).Create(beatmap.Metadata.BackgroundFile); + yield return new IssueTemplateDoesNotExist(this).Create(workingBeatmap.Metadata.BackgroundFile); } public class IssueTemplateNoneSet : IssueTemplate diff --git a/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs b/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs index f284240092..a2814ee603 100644 --- a/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs +++ b/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Edit.Checks.Components /// /// Runs this check and returns any issues detected for the provided beatmap. /// - /// The beatmap to run the check on. - public IEnumerable Run(IBeatmap beatmap); + /// The beatmap to run the check on. + public IEnumerable Run(WorkingBeatmap workingBeatmap); } } diff --git a/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs b/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs index 61d8119635..12be8815e1 100644 --- a/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs @@ -12,6 +12,6 @@ namespace osu.Game.Rulesets.Edit /// public interface IBeatmapVerifier { - public IEnumerable Run(IBeatmap beatmap); + public IEnumerable Run(WorkingBeatmap workingBeatmap); } } diff --git a/osu.Game/Screens/Edit/Verify/VerifyScreen.cs b/osu.Game/Screens/Edit/Verify/VerifyScreen.cs index 550fbe2950..160a14caac 100644 --- a/osu.Game/Screens/Edit/Verify/VerifyScreen.cs +++ b/osu.Game/Screens/Edit/Verify/VerifyScreen.cs @@ -7,6 +7,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; @@ -61,7 +62,7 @@ namespace osu.Game.Screens.Edit.Verify private EditorClock clock { get; set; } [Resolved] - protected EditorBeatmap Beatmap { get; private set; } + protected WorkingBeatmap Beatmap { get; private set; } [Resolved] private Bindable selectedIssue { get; set; } From 400f8b3938428d22ca25d5760214045f42b3328d Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Sat, 17 Apr 2021 17:47:13 +0200 Subject: [PATCH 02/29] Add `GetStream` to `IWorkingBeatmap` This is necessary to obtain the filesize of the audio and background files. --- osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs | 2 ++ osu.Game.Tests/WaveformTestBeatmap.cs | 2 ++ osu.Game/Beatmaps/BeatmapManager.cs | 1 + osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs | 3 +++ osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 3 +++ osu.Game/Beatmaps/WorkingBeatmap.cs | 3 +++ osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs | 2 ++ osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs | 2 ++ osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs | 3 +++ 9 files changed, 21 insertions(+) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs index 920cc36776..a18f82fe4a 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs @@ -168,6 +168,8 @@ namespace osu.Game.Tests.Beatmaps.Formats protected override Texture GetBackground() => throw new NotImplementedException(); protected override Track GetBeatmapTrack() => throw new NotImplementedException(); + + public override Stream GetStream(string storagePath) => throw new NotImplementedException(); } } } diff --git a/osu.Game.Tests/WaveformTestBeatmap.cs b/osu.Game.Tests/WaveformTestBeatmap.cs index 8c8c827404..cbed28641c 100644 --- a/osu.Game.Tests/WaveformTestBeatmap.cs +++ b/osu.Game.Tests/WaveformTestBeatmap.cs @@ -52,6 +52,8 @@ namespace osu.Game.Tests protected override Waveform GetWaveform() => new Waveform(trackStore.GetStream(firstAudioFile)); + public override Stream GetStream(string storagePath) => null; + protected override Track GetBeatmapTrack() => trackStore.Get(firstAudioFile); private string firstAudioFile diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index b4ea898b7d..5e975de77c 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -526,6 +526,7 @@ namespace osu.Game.Beatmaps protected override IBeatmap GetBeatmap() => beatmap; protected override Texture GetBackground() => null; protected override Track GetBeatmapTrack() => null; + public override Stream GetStream(string storagePath) => null; } } diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 62cf29dc03..c1fc7a72e2 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.IO; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; using osu.Framework.Logging; @@ -142,6 +143,8 @@ namespace osu.Game.Beatmaps return null; } } + + public override Stream GetStream(string storagePath) => resources.Files.GetStream(storagePath); } } } diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index c114358771..6922d1c286 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Threading; using JetBrains.Annotations; using osu.Framework.Audio; @@ -48,6 +49,8 @@ namespace osu.Game.Beatmaps protected override Track GetBeatmapTrack() => GetVirtualTrack(); + public override Stream GetStream(string storagePath) => null; + private class DummyRulesetInfo : RulesetInfo { public override Ruleset CreateInstance() => new DummyRuleset(); diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index f7f276230f..e0eeaf6db0 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -326,6 +327,8 @@ namespace osu.Game.Beatmaps protected virtual ISkin GetSkin() => new DefaultSkin(); private readonly RecyclableLazy skin; + public abstract Stream GetStream(string storagePath); + public class RecyclableLazy { private Lazy lazy; diff --git a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs index f2e0320ce3..66784fda54 100644 --- a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs +++ b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs @@ -116,6 +116,8 @@ namespace osu.Game.Screens.Edit protected override Texture GetBackground() => throw new NotImplementedException(); protected override Track GetBeatmapTrack() => throw new NotImplementedException(); + + public override Stream GetStream(string storagePath) => throw new NotImplementedException(); } } } diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index 5ef2458919..1c5e551042 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -215,6 +215,8 @@ namespace osu.Game.Tests.Beatmaps protected override Track GetBeatmapTrack() => throw new NotImplementedException(); + public override Stream GetStream(string storagePath) => throw new NotImplementedException(); + protected override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) { var converter = base.CreateBeatmapConverter(beatmap, ruleset); diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index bfcb2403c1..852006bc9b 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.IO; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; @@ -35,6 +36,8 @@ namespace osu.Game.Tests.Beatmaps protected override Storyboard GetStoryboard() => storyboard ?? base.GetStoryboard(); + public override Stream GetStream(string storagePath) => null; + protected override Texture GetBackground() => null; protected override Track GetBeatmapTrack() => null; From b36da2664c2be2e9be6a2c69383dc3b95d459080 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Sat, 17 Apr 2021 17:49:10 +0200 Subject: [PATCH 03/29] Add `GetPathForFile` to `BeatmapSetInfo` This is used in several places, and so should probably have a function rather than remaining as duplicated code. Also applies this together with the previous commit to `BeatmapManagerWorkingBeatmap`. --- .../Beatmaps/BeatmapManager_WorkingBeatmap.cs | 15 ++++++--------- osu.Game/Beatmaps/BeatmapSetInfo.cs | 2 ++ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index c1fc7a72e2..d78ffbbfb6 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -3,7 +3,6 @@ using System; using System.Diagnostics.CodeAnalysis; -using System.Linq; using System.IO; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; @@ -37,7 +36,7 @@ namespace osu.Game.Beatmaps try { - using (var stream = new LineBufferedReader(resources.Files.GetStream(getPathForFile(BeatmapInfo.Path)))) + using (var stream = new LineBufferedReader(GetStream(BeatmapSetInfo.GetPathForFile(BeatmapInfo.Path)))) return Decoder.GetDecoder(stream).Decode(stream); } catch (Exception e) @@ -47,8 +46,6 @@ namespace osu.Game.Beatmaps } } - private string getPathForFile(string filename) => BeatmapSetInfo.Files.SingleOrDefault(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath; - protected override bool BackgroundStillValid(Texture b) => false; // bypass lazy logic. we want to return a new background each time for refcounting purposes. protected override Texture GetBackground() @@ -58,7 +55,7 @@ namespace osu.Game.Beatmaps try { - return resources.LargeTextureStore.Get(getPathForFile(Metadata.BackgroundFile)); + return resources.LargeTextureStore.Get(BeatmapSetInfo.GetPathForFile(Metadata.BackgroundFile)); } catch (Exception e) { @@ -74,7 +71,7 @@ namespace osu.Game.Beatmaps try { - return resources.Tracks.Get(getPathForFile(Metadata.AudioFile)); + return resources.Tracks.Get(BeatmapSetInfo.GetPathForFile(Metadata.AudioFile)); } catch (Exception e) { @@ -90,7 +87,7 @@ namespace osu.Game.Beatmaps try { - var trackData = resources.Files.GetStream(getPathForFile(Metadata.AudioFile)); + var trackData = GetStream(BeatmapSetInfo.GetPathForFile(Metadata.AudioFile)); return trackData == null ? null : new Waveform(trackData); } catch (Exception e) @@ -106,7 +103,7 @@ namespace osu.Game.Beatmaps try { - using (var stream = new LineBufferedReader(resources.Files.GetStream(getPathForFile(BeatmapInfo.Path)))) + using (var stream = new LineBufferedReader(GetStream(BeatmapSetInfo.GetPathForFile(BeatmapInfo.Path)))) { var decoder = Decoder.GetDecoder(stream); @@ -115,7 +112,7 @@ namespace osu.Game.Beatmaps storyboard = decoder.Decode(stream); else { - using (var secondaryStream = new LineBufferedReader(resources.Files.GetStream(getPathForFile(BeatmapSetInfo.StoryboardFile)))) + using (var secondaryStream = new LineBufferedReader(GetStream(BeatmapSetInfo.GetPathForFile(BeatmapSetInfo.StoryboardFile)))) storyboard = decoder.Decode(stream, secondaryStream); } } diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 7bc1c8c7b9..774bd0bc62 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -59,6 +59,8 @@ namespace osu.Game.Beatmaps public string StoryboardFile => Files?.Find(f => f.Filename.EndsWith(".osb", StringComparison.OrdinalIgnoreCase))?.Filename; + public string GetPathForFile(string filename) => Files?.SingleOrDefault(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath; + public List Files { get; set; } public override string ToString() => Metadata?.ToString() ?? base.ToString(); From 62c54e00cb7eee3b424e965a09462431ab03cf9c Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Sat, 17 Apr 2021 18:01:04 +0200 Subject: [PATCH 04/29] Add check for background resolution and filesize --- osu.Game/Rulesets/Edit/BeatmapVerifier.cs | 1 + .../Edit/Checks/CheckBackgroundQuality.cs | 98 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs index 40714e8c7e..24a4f473de 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs @@ -17,6 +17,7 @@ namespace osu.Game.Rulesets.Edit private readonly List checks = new List { new CheckBackground(), + new CheckBackgroundQuality() }; public IEnumerable Run(WorkingBeatmap workingBeatmap) => checks.SelectMany(check => check.Run(workingBeatmap)); diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs new file mode 100644 index 0000000000..ed504f52ed --- /dev/null +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs @@ -0,0 +1,98 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit.Checks.Components; + +namespace osu.Game.Rulesets.Edit.Checks +{ + public class CheckBackgroundQuality : ICheck + { + // These are the requirements as stated in the Ranking Criteria. + // See https://osu.ppy.sh/wiki/en/Ranking_Criteria#rules.5 + private const int min_width = 160; + private const int max_width = 2560; + private const int min_height = 120; + private const int max_height = 1440; + private const double max_filesize_mb = 2.5d; + + // It's usually possible to find a higher resolution of the same image if lower than these. + private const int low_width = 960; + private const int low_height = 540; + + public CheckMetadata Metadata { get; } = new CheckMetadata(CheckCategory.Resources, "Too high or low background resolution"); + + public IEnumerable PossibleTemplates => new IssueTemplate[] + { + new IssueTemplateTooHighResolution(this), + new IssueTemplateTooLowResolution(this), + new IssueTemplateTooUncompressed(this) + }; + + public IEnumerable Run(WorkingBeatmap workingBeatmap) + { + if (workingBeatmap.Metadata?.BackgroundFile == null) + yield break; + + var texture = workingBeatmap.Background; + if (texture == null) + yield break; + + if (texture.Width > max_width || texture.Height > max_height) + yield return new IssueTemplateTooHighResolution(this).Create(texture.Width, texture.Height); + + if (texture.Width < min_width || texture.Height < min_height) + yield return new IssueTemplateTooLowResolution(this).Create(texture.Width, texture.Height); + + if (texture.Width < low_width || texture.Height < low_height) + yield return new IssueTemplateLowResolution(this).Create(texture.Width, texture.Height); + + string storagePath = workingBeatmap.BeatmapInfo.BeatmapSet.GetPathForFile(workingBeatmap.Metadata.BackgroundFile); + double filesizeMb = workingBeatmap.GetStream(storagePath).Length / (1024d * 1024d); + + if (filesizeMb > max_filesize_mb) + yield return new IssueTemplateTooUncompressed(this).Create(filesizeMb); + } + + public class IssueTemplateTooHighResolution : IssueTemplate + { + public IssueTemplateTooHighResolution(ICheck check) + : base(check, IssueType.Problem, "The background resolution ({0} x {1}) exceeds {2} x {3}.") + { + } + + public Issue Create(double width, double height) => new Issue(this, width, height, max_width, max_height); + } + + public class IssueTemplateTooLowResolution : IssueTemplate + { + public IssueTemplateTooLowResolution(ICheck check) + : base(check, IssueType.Problem, "The background resolution ({0} x {1}) is lower than {2} x {3}.") + { + } + + public Issue Create(double width, double height) => new Issue(this, width, height, min_width, min_height); + } + + public class IssueTemplateLowResolution : IssueTemplate + { + public IssueTemplateLowResolution(ICheck check) + : base(check, IssueType.Warning, "The background resolution ({0} x {1}) is lower than {2} x {3}.") + { + } + + public Issue Create(double width, double height) => new Issue(this, width, height, low_width, low_height); + } + + public class IssueTemplateTooUncompressed : IssueTemplate + { + public IssueTemplateTooUncompressed(ICheck check) + : base(check, IssueType.Problem, "The background filesize ({0:0.#} MB) exceeds {1} MB.") + { + } + + public Issue Create(double actualMb) => new Issue(this, actualMb, max_filesize_mb); + } + } +} From cb41c89935a4e7b0e76865efd6e8dd36ceb22124 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Sat, 17 Apr 2021 20:10:07 +0200 Subject: [PATCH 05/29] Don't return low res and too low res at the same time --- osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs index ed504f52ed..a3f363554e 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs @@ -44,8 +44,7 @@ namespace osu.Game.Rulesets.Edit.Checks if (texture.Width < min_width || texture.Height < min_height) yield return new IssueTemplateTooLowResolution(this).Create(texture.Width, texture.Height); - - if (texture.Width < low_width || texture.Height < low_height) + else if (texture.Width < low_width || texture.Height < low_height) yield return new IssueTemplateLowResolution(this).Create(texture.Width, texture.Height); string storagePath = workingBeatmap.BeatmapInfo.BeatmapSet.GetPathForFile(workingBeatmap.Metadata.BackgroundFile); From bf8789528ae81cd332416ab0ed11572c53693a4a Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Sun, 18 Apr 2021 01:13:57 +0200 Subject: [PATCH 06/29] Add `GetStream` to `IWorkingBeatmap` --- osu.Game/Beatmaps/IWorkingBeatmap.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index bcd94d76fd..f1bf6f48ef 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.IO; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; using osu.Game.Rulesets; @@ -67,5 +68,7 @@ namespace osu.Game.Beatmaps /// /// A fresh track instance, which will also be available via . Track LoadTrack(); + + Stream GetStream(string storagePath); } } From ef65c8910f0a6a9d76327810c70733630aed8c25 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Sun, 18 Apr 2021 01:15:13 +0200 Subject: [PATCH 07/29] Fix resolved fields --- osu.Game/Screens/Edit/Verify/VerifyScreen.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Verify/VerifyScreen.cs b/osu.Game/Screens/Edit/Verify/VerifyScreen.cs index 160a14caac..6aa479b38d 100644 --- a/osu.Game/Screens/Edit/Verify/VerifyScreen.cs +++ b/osu.Game/Screens/Edit/Verify/VerifyScreen.cs @@ -62,7 +62,10 @@ namespace osu.Game.Screens.Edit.Verify private EditorClock clock { get; set; } [Resolved] - protected WorkingBeatmap Beatmap { get; private set; } + private BeatmapManager beatmapManager { get; set; } + + [Resolved] + private EditorBeatmap beatmap { get; set; } [Resolved] private Bindable selectedIssue { get; set; } @@ -74,7 +77,7 @@ namespace osu.Game.Screens.Edit.Verify private void load(OsuColour colours) { generalVerifier = new BeatmapVerifier(); - rulesetVerifier = Beatmap.BeatmapInfo.Ruleset?.CreateInstance()?.CreateBeatmapVerifier(); + rulesetVerifier = beatmap.BeatmapInfo.Ruleset?.CreateInstance()?.CreateBeatmapVerifier(); RelativeSizeAxes = Axes.Both; @@ -120,10 +123,11 @@ namespace osu.Game.Screens.Edit.Verify private void refresh() { - var issues = generalVerifier.Run(Beatmap); + var workingBeatmap = beatmapManager.GetWorkingBeatmap(beatmap.BeatmapInfo); + var issues = generalVerifier.Run(workingBeatmap); if (rulesetVerifier != null) - issues = issues.Concat(rulesetVerifier.Run(Beatmap)); + issues = issues.Concat(rulesetVerifier.Run(workingBeatmap)); table.Issues = issues .OrderBy(issue => issue.Template.Type) From abf512532e2f8d7e79d8b8fafe419b651fb1f896 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Sun, 18 Apr 2021 01:19:25 +0200 Subject: [PATCH 08/29] Clean up check logic Makes use of the new `BeatmapSet.GetPathForFile` method and removes dependency on `WorkingBeatmap` specifically, allowing us to switch to `IWorkingBeatmap` later. --- osu.Game/Rulesets/Edit/Checks/CheckBackground.cs | 14 ++++++-------- .../Rulesets/Edit/Checks/CheckBackgroundQuality.cs | 5 +++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackground.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackground.cs index d2fffeea4e..637e603e17 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackground.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackground.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit.Checks.Components; @@ -20,7 +19,9 @@ namespace osu.Game.Rulesets.Edit.Checks public IEnumerable Run(WorkingBeatmap workingBeatmap) { - if (workingBeatmap.Metadata?.BackgroundFile == null) + string backgroundFile = workingBeatmap.Beatmap.Metadata?.BackgroundFile; + + if (backgroundFile == null) { yield return new IssueTemplateNoneSet(this).Create(); @@ -28,14 +29,11 @@ namespace osu.Game.Rulesets.Edit.Checks } // If the background is set, also make sure it still exists. - - var set = workingBeatmap.BeatmapInfo.BeatmapSet; - var file = set.Files.FirstOrDefault(f => f.Filename == workingBeatmap.Metadata.BackgroundFile); - - if (file != null) + var storagePath = workingBeatmap.Beatmap.BeatmapInfo.BeatmapSet.GetPathForFile(backgroundFile); + if (storagePath != null) yield break; - yield return new IssueTemplateDoesNotExist(this).Create(workingBeatmap.Metadata.BackgroundFile); + yield return new IssueTemplateDoesNotExist(this).Create(backgroundFile); } public class IssueTemplateNoneSet : IssueTemplate diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs index a3f363554e..48d536079a 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs @@ -32,7 +32,8 @@ namespace osu.Game.Rulesets.Edit.Checks public IEnumerable Run(WorkingBeatmap workingBeatmap) { - if (workingBeatmap.Metadata?.BackgroundFile == null) + var backgroundFile = workingBeatmap.Beatmap.Metadata?.BackgroundFile; + if (backgroundFile == null) yield break; var texture = workingBeatmap.Background; @@ -47,7 +48,7 @@ namespace osu.Game.Rulesets.Edit.Checks else if (texture.Width < low_width || texture.Height < low_height) yield return new IssueTemplateLowResolution(this).Create(texture.Width, texture.Height); - string storagePath = workingBeatmap.BeatmapInfo.BeatmapSet.GetPathForFile(workingBeatmap.Metadata.BackgroundFile); + string storagePath = workingBeatmap.Beatmap.BeatmapInfo.BeatmapSet.GetPathForFile(backgroundFile); double filesizeMb = workingBeatmap.GetStream(storagePath).Length / (1024d * 1024d); if (filesizeMb > max_filesize_mb) From 56bf49c85c525547c6ebe8bb1656b69e1cd2b0ec Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Sun, 18 Apr 2021 01:21:20 +0200 Subject: [PATCH 09/29] Take `IWorkingBeatmap` instead of `WorkingBeatmap` This makes testing much easier, and allows for checking of any class deriving from that interface, including `WorkingBeatmap`. --- osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs | 2 +- osu.Game/Rulesets/Edit/Checks/CheckBackground.cs | 2 +- osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs | 2 +- osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs index 54b167aaf3..c210f73b5f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs +++ b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Checks new IssueTemplateOffscreenSlider(this) }; - public IEnumerable Run(WorkingBeatmap workingBeatmap) + public IEnumerable Run(IWorkingBeatmap workingBeatmap) { foreach (var hitobject in workingBeatmap.Beatmap.HitObjects) { diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackground.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackground.cs index 637e603e17..71821b8073 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackground.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackground.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateDoesNotExist(this) }; - public IEnumerable Run(WorkingBeatmap workingBeatmap) + public IEnumerable Run(IWorkingBeatmap workingBeatmap) { string backgroundFile = workingBeatmap.Beatmap.Metadata?.BackgroundFile; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs index 48d536079a..1494ae5da4 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateTooUncompressed(this) }; - public IEnumerable Run(WorkingBeatmap workingBeatmap) + public IEnumerable Run(IWorkingBeatmap workingBeatmap) { var backgroundFile = workingBeatmap.Beatmap.Metadata?.BackgroundFile; if (backgroundFile == null) diff --git a/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs b/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs index a2814ee603..c3a64b58e9 100644 --- a/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs +++ b/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs @@ -25,6 +25,6 @@ namespace osu.Game.Rulesets.Edit.Checks.Components /// Runs this check and returns any issues detected for the provided beatmap. /// /// The beatmap to run the check on. - public IEnumerable Run(WorkingBeatmap workingBeatmap); + public IEnumerable Run(IWorkingBeatmap workingBeatmap); } } From 0502fbb4296e103d4841ce86becb57aef38e73a1 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Sun, 18 Apr 2021 01:21:51 +0200 Subject: [PATCH 10/29] Add background quality check tests --- .../Checks/CheckBackgroundQualityTest.cs | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs diff --git a/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs b/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs new file mode 100644 index 0000000000..8dad5bbf34 --- /dev/null +++ b/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs @@ -0,0 +1,130 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using JetBrains.Annotations; +using Moq; +using NUnit.Framework; +using osu.Framework.Graphics.Textures; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit.Checks; +using osu.Game.Rulesets.Objects; +using FileInfo = osu.Game.IO.FileInfo; + +namespace osu.Game.Tests.Editing.Checks +{ + [TestFixture] + public class CheckBackgroundQualityTest + { + private CheckBackgroundQuality check; + private IBeatmap beatmap; + + [SetUp] + public void Setup() + { + check = new CheckBackgroundQuality(); + beatmap = new Beatmap + { + BeatmapInfo = new BeatmapInfo + { + Metadata = new BeatmapMetadata { BackgroundFile = "abc123.jpg" }, + BeatmapSet = new BeatmapSetInfo + { + Files = new List(new[] + { + new BeatmapSetFileInfo + { + Filename = "abc123.jpg", + FileInfo = new FileInfo + { + Hash = "abcdef" + } + } + }) + } + } + }; + } + + [Test] + public void TestBackgroundMissing() + { + // While this is a problem, it is out of scope for this check and is caught by a different one. + beatmap.Metadata.BackgroundFile = null; + var mock = getMockWorkingBeatmap(null, System.Array.Empty()); + + Assert.That(check.Run(mock.Object), Is.Empty); + } + + [Test] + public void TestBackgroundAcceptable() + { + var mock = getMockWorkingBeatmap(new Texture(1920, 1080)); + + Assert.That(check.Run(mock.Object), Is.Empty); + } + + [Test] + public void TestBackgroundTooHighResolution() + { + var mock = getMockWorkingBeatmap(new Texture(3840, 2160)); + + var issues = check.Run(mock.Object).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateTooHighResolution); + } + + [Test] + public void TestBackgroundLowResolution() + { + var mock = getMockWorkingBeatmap(new Texture(640, 480)); + + var issues = check.Run(mock.Object).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateLowResolution); + } + + [Test] + public void TestBackgroundTooLowResolution() + { + var mock = getMockWorkingBeatmap(new Texture(100, 100)); + + var issues = check.Run(mock.Object).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateTooLowResolution); + } + + [Test] + public void TestBackgroundTooUncompressed() + { + var mock = getMockWorkingBeatmap(new Texture(1920, 1080), new byte[1024 * 1024 * 3]); + + var issues = check.Run(mock.Object).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateTooUncompressed); + } + + /// + /// Returns the mock of the working beatmap with the given background and filesize. + /// + /// The texture of the background. + /// The bytes that represent the background file. + private Mock getMockWorkingBeatmap(Texture background, [CanBeNull] byte[] fileBytes = null) + { + var stream = new MemoryStream(fileBytes ?? new byte[1024 * 1024]); + + var mock = new Mock(); + mock.SetupGet(_ => _.Beatmap).Returns(beatmap); + mock.SetupGet(_ => _.Background).Returns(background); + mock.Setup(_ => _.GetStream(It.IsAny())).Returns(stream); + + return mock; + } + } +} From 010720de74c67df74f140aa2263cb85c4054b563 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Sun, 18 Apr 2021 02:07:33 +0200 Subject: [PATCH 11/29] Factor out general file presence checking This allows us to use the same method of checking for other files that should exist, for example the audio file. By using the same method, they all share test cases too. --- ...groundTest.cs => CheckFilePresenceTest.cs} | 10 +++---- osu.Game/Rulesets/Edit/BeatmapVerifier.cs | 7 +++-- .../Edit/Checks/CheckBackgroundPresence.cs | 15 ++++++++++ ...heckBackground.cs => CheckFilePresence.cs} | 28 +++++++++++-------- 4 files changed, 41 insertions(+), 19 deletions(-) rename osu.Game.Tests/Editing/Checks/{CheckBackgroundTest.cs => CheckFilePresenceTest.cs} (84%) create mode 100644 osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs rename osu.Game/Rulesets/Edit/Checks/{CheckBackground.cs => CheckFilePresence.cs} (57%) diff --git a/osu.Game.Tests/Editing/Checks/CheckBackgroundTest.cs b/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs similarity index 84% rename from osu.Game.Tests/Editing/Checks/CheckBackgroundTest.cs rename to osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs index d61f0989a6..1149115b55 100644 --- a/osu.Game.Tests/Editing/Checks/CheckBackgroundTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs @@ -12,15 +12,15 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Editing.Checks { [TestFixture] - public class CheckBackgroundTest + public class CheckFilePresenceTest { - private CheckBackground check; + private CheckBackgroundPresence check; private WorkingBeatmap beatmap; [SetUp] public void Setup() { - check = new CheckBackground(); + check = new CheckBackgroundPresence(); beatmap = new TestWorkingBeatmap(new Beatmap { BeatmapInfo = new BeatmapInfo @@ -51,7 +51,7 @@ namespace osu.Game.Tests.Editing.Checks var issues = check.Run(beatmap).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); - Assert.That(issues.Single().Template is CheckBackground.IssueTemplateDoesNotExist); + Assert.That(issues.Single().Template is CheckFilePresence.IssueTemplateDoesNotExist); } [Test] @@ -62,7 +62,7 @@ namespace osu.Game.Tests.Editing.Checks var issues = check.Run(beatmap).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); - Assert.That(issues.Single().Template is CheckBackground.IssueTemplateNoneSet); + Assert.That(issues.Single().Template is CheckFilePresence.IssueTemplateNoneSet); } } } diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs index 24a4f473de..90447049f8 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs @@ -16,8 +16,11 @@ namespace osu.Game.Rulesets.Edit { private readonly List checks = new List { - new CheckBackground(), - new CheckBackgroundQuality() + // Resources + new CheckBackgroundPresence(), + new CheckBackgroundQuality(), + // Audio + new CheckAudioPresence(), }; public IEnumerable Run(WorkingBeatmap workingBeatmap) => checks.SelectMany(check => check.Run(workingBeatmap)); diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs new file mode 100644 index 0000000000..3a229b889b --- /dev/null +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit.Checks.Components; + +namespace osu.Game.Rulesets.Edit.Checks +{ + public class CheckBackgroundPresence : CheckFilePresence + { + protected override CheckCategory Category => CheckCategory.Resources; + protected override string TypeOfFile => "background"; + protected override string GetFilename(IWorkingBeatmap workingBeatmap) => workingBeatmap.Beatmap.Metadata?.BackgroundFile; + } +} diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackground.cs b/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs similarity index 57% rename from osu.Game/Rulesets/Edit/Checks/CheckBackground.cs rename to osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs index 71821b8073..37fa79568f 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackground.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs @@ -7,9 +7,13 @@ using osu.Game.Rulesets.Edit.Checks.Components; namespace osu.Game.Rulesets.Edit.Checks { - public class CheckBackground : ICheck + public abstract class CheckFilePresence : ICheck { - public CheckMetadata Metadata { get; } = new CheckMetadata(CheckCategory.Resources, "Missing background"); + protected abstract CheckCategory Category { get; } + protected abstract string TypeOfFile { get; } + protected abstract string GetFilename(IWorkingBeatmap workingBeatmap); + + public CheckMetadata Metadata => new CheckMetadata(Category, $"Missing {TypeOfFile}"); public IEnumerable PossibleTemplates => new IssueTemplate[] { @@ -19,41 +23,41 @@ namespace osu.Game.Rulesets.Edit.Checks public IEnumerable Run(IWorkingBeatmap workingBeatmap) { - string backgroundFile = workingBeatmap.Beatmap.Metadata?.BackgroundFile; + var filename = GetFilename(workingBeatmap); - if (backgroundFile == null) + if (filename == null) { - yield return new IssueTemplateNoneSet(this).Create(); + yield return new IssueTemplateNoneSet(this).Create(TypeOfFile); yield break; } - // If the background is set, also make sure it still exists. - var storagePath = workingBeatmap.Beatmap.BeatmapInfo.BeatmapSet.GetPathForFile(backgroundFile); + // If the file is set, also make sure it still exists. + var storagePath = workingBeatmap.Beatmap.BeatmapInfo.BeatmapSet.GetPathForFile(filename); if (storagePath != null) yield break; - yield return new IssueTemplateDoesNotExist(this).Create(backgroundFile); + yield return new IssueTemplateDoesNotExist(this).Create(TypeOfFile, filename); } public class IssueTemplateNoneSet : IssueTemplate { public IssueTemplateNoneSet(ICheck check) - : base(check, IssueType.Problem, "No background has been set.") + : base(check, IssueType.Problem, "No {0} has been set.") { } - public Issue Create() => new Issue(this); + public Issue Create(string typeOfFile) => new Issue(this, typeOfFile); } public class IssueTemplateDoesNotExist : IssueTemplate { public IssueTemplateDoesNotExist(ICheck check) - : base(check, IssueType.Problem, "The background file \"{0}\" does not exist.") + : base(check, IssueType.Problem, "The {0} file \"{1}\" does not exist.") { } - public Issue Create(string filename) => new Issue(this, filename); + public Issue Create(string typeOfFile, string filename) => new Issue(this, typeOfFile, filename); } } } From 9a69ca34a6ec004e6b336826f5623cbcd1c33a35 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Sun, 18 Apr 2021 02:07:57 +0200 Subject: [PATCH 12/29] Add audio presence check --- .../Rulesets/Edit/Checks/CheckAudioPresence.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs b/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs new file mode 100644 index 0000000000..55e53ef519 --- /dev/null +++ b/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit.Checks.Components; + +namespace osu.Game.Rulesets.Edit.Checks +{ + public class CheckAudioPresence : CheckFilePresence + { + protected override CheckCategory Category => CheckCategory.Audio; + protected override string TypeOfFile => "audio"; + protected override string GetFilename(IWorkingBeatmap workingBeatmap) => workingBeatmap.Beatmap.Metadata?.AudioFile; + } +} From 8656176ab8e09b14737212846fdeed787a3f7bc4 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Tue, 20 Apr 2021 01:31:51 +0200 Subject: [PATCH 13/29] Add the playable beatmap as check argument This is different from the working beatmap's `.Beatmap` property in that it is mutated by the ruleset/editor. So hit objects, for example, are actually of type `Slider` and such instead of the legacy `ConvertSlider`. This should be preferred over `workingBeatmap.Beatmap`. --- .../Editor/Checks/CheckOffscreenObjectsTest.cs | 6 +++--- .../Edit/Checks/CheckOffscreenObjects.cs | 4 ++-- osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs | 5 ++++- .../Editing/Checks/CheckBackgroundQualityTest.cs | 12 ++++++------ .../Editing/Checks/CheckFilePresenceTest.cs | 12 ++++++------ osu.Game/Rulesets/Edit/BeatmapVerifier.cs | 5 ++++- .../Rulesets/Edit/Checks/CheckBackgroundQuality.cs | 6 +++--- osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs | 4 ++-- osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs | 5 +++-- osu.Game/Rulesets/Edit/IBeatmapVerifier.cs | 2 +- osu.Game/Screens/Edit/Verify/VerifyScreen.cs | 4 ++-- 11 files changed, 36 insertions(+), 29 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs index db347960ef..3a4817398c 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs @@ -224,12 +224,12 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks private void assertOk(IBeatmap beatmap) { - Assert.That(check.Run(new TestWorkingBeatmap(beatmap)), Is.Empty); + Assert.That(check.Run(beatmap, new TestWorkingBeatmap(beatmap)), Is.Empty); } private void assertOffscreenCircle(IBeatmap beatmap) { - var issues = check.Run(new TestWorkingBeatmap(beatmap)).ToList(); + var issues = check.Run(beatmap, new TestWorkingBeatmap(beatmap)).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckOffscreenObjects.IssueTemplateOffscreenCircle); @@ -237,7 +237,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks private void assertOffscreenSlider(IBeatmap beatmap) { - var issues = check.Run(new TestWorkingBeatmap(beatmap)).ToList(); + var issues = check.Run(beatmap, new TestWorkingBeatmap(beatmap)).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckOffscreenObjects.IssueTemplateOffscreenSlider); diff --git a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs index c210f73b5f..4b0a7531a1 100644 --- a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs +++ b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs @@ -31,9 +31,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Checks new IssueTemplateOffscreenSlider(this) }; - public IEnumerable Run(IWorkingBeatmap workingBeatmap) + public IEnumerable Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap) { - foreach (var hitobject in workingBeatmap.Beatmap.HitObjects) + foreach (var hitobject in playableBeatmap.HitObjects) { switch (hitobject) { diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs b/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs index 9b9383d547..dab6483179 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs @@ -17,6 +17,9 @@ namespace osu.Game.Rulesets.Osu.Edit new CheckOffscreenObjects() }; - public IEnumerable Run(WorkingBeatmap workingBeatmap) => checks.SelectMany(check => check.Run(workingBeatmap)); + public IEnumerable Run(IBeatmap playableBeatmap, WorkingBeatmap workingBeatmap) + { + return checks.SelectMany(check => check.Run(playableBeatmap, workingBeatmap)); + } } } diff --git a/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs b/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs index 8dad5bbf34..42d143cc04 100644 --- a/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs @@ -55,7 +55,7 @@ namespace osu.Game.Tests.Editing.Checks beatmap.Metadata.BackgroundFile = null; var mock = getMockWorkingBeatmap(null, System.Array.Empty()); - Assert.That(check.Run(mock.Object), Is.Empty); + Assert.That(check.Run(beatmap, mock.Object), Is.Empty); } [Test] @@ -63,7 +63,7 @@ namespace osu.Game.Tests.Editing.Checks { var mock = getMockWorkingBeatmap(new Texture(1920, 1080)); - Assert.That(check.Run(mock.Object), Is.Empty); + Assert.That(check.Run(beatmap, mock.Object), Is.Empty); } [Test] @@ -71,7 +71,7 @@ namespace osu.Game.Tests.Editing.Checks { var mock = getMockWorkingBeatmap(new Texture(3840, 2160)); - var issues = check.Run(mock.Object).ToList(); + var issues = check.Run(beatmap, mock.Object).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateTooHighResolution); @@ -82,7 +82,7 @@ namespace osu.Game.Tests.Editing.Checks { var mock = getMockWorkingBeatmap(new Texture(640, 480)); - var issues = check.Run(mock.Object).ToList(); + var issues = check.Run(beatmap, mock.Object).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateLowResolution); @@ -93,7 +93,7 @@ namespace osu.Game.Tests.Editing.Checks { var mock = getMockWorkingBeatmap(new Texture(100, 100)); - var issues = check.Run(mock.Object).ToList(); + var issues = check.Run(beatmap, mock.Object).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateTooLowResolution); @@ -104,7 +104,7 @@ namespace osu.Game.Tests.Editing.Checks { var mock = getMockWorkingBeatmap(new Texture(1920, 1080), new byte[1024 * 1024 * 3]); - var issues = check.Run(mock.Object).ToList(); + var issues = check.Run(beatmap, mock.Object).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateTooUncompressed); diff --git a/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs b/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs index 1149115b55..fe2e16ffd8 100644 --- a/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs @@ -15,13 +15,13 @@ namespace osu.Game.Tests.Editing.Checks public class CheckFilePresenceTest { private CheckBackgroundPresence check; - private WorkingBeatmap beatmap; + private IBeatmap beatmap; [SetUp] public void Setup() { check = new CheckBackgroundPresence(); - beatmap = new TestWorkingBeatmap(new Beatmap + beatmap = new Beatmap { BeatmapInfo = new BeatmapInfo { @@ -34,13 +34,13 @@ namespace osu.Game.Tests.Editing.Checks }) } } - }); + }; } [Test] public void TestBackgroundSetAndInFiles() { - Assert.That(check.Run(beatmap), Is.Empty); + Assert.That(check.Run(beatmap, new TestWorkingBeatmap(beatmap)), Is.Empty); } [Test] @@ -48,7 +48,7 @@ namespace osu.Game.Tests.Editing.Checks { beatmap.BeatmapInfo.BeatmapSet.Files.Clear(); - var issues = check.Run(beatmap).ToList(); + var issues = check.Run(beatmap, new TestWorkingBeatmap(beatmap)).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckFilePresence.IssueTemplateDoesNotExist); @@ -59,7 +59,7 @@ namespace osu.Game.Tests.Editing.Checks { beatmap.Metadata.BackgroundFile = null; - var issues = check.Run(beatmap).ToList(); + var issues = check.Run(beatmap, new TestWorkingBeatmap(beatmap)).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckFilePresence.IssueTemplateNoneSet); diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs index 90447049f8..9efaa94b40 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs @@ -23,6 +23,9 @@ namespace osu.Game.Rulesets.Edit new CheckAudioPresence(), }; - public IEnumerable Run(WorkingBeatmap workingBeatmap) => checks.SelectMany(check => check.Run(workingBeatmap)); + public IEnumerable Run(IBeatmap playableBeatmap, WorkingBeatmap workingBeatmap) + { + return checks.SelectMany(check => check.Run(playableBeatmap, workingBeatmap)); + } } } diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs index 1494ae5da4..767c2b94b5 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs @@ -30,9 +30,9 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateTooUncompressed(this) }; - public IEnumerable Run(IWorkingBeatmap workingBeatmap) + public IEnumerable Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap) { - var backgroundFile = workingBeatmap.Beatmap.Metadata?.BackgroundFile; + var backgroundFile = playableBeatmap.Metadata?.BackgroundFile; if (backgroundFile == null) yield break; @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Edit.Checks else if (texture.Width < low_width || texture.Height < low_height) yield return new IssueTemplateLowResolution(this).Create(texture.Width, texture.Height); - string storagePath = workingBeatmap.Beatmap.BeatmapInfo.BeatmapSet.GetPathForFile(backgroundFile); + string storagePath = playableBeatmap.BeatmapInfo.BeatmapSet.GetPathForFile(backgroundFile); double filesizeMb = workingBeatmap.GetStream(storagePath).Length / (1024d * 1024d); if (filesizeMb > max_filesize_mb) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs b/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs index 37fa79568f..340b053fdb 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateDoesNotExist(this) }; - public IEnumerable Run(IWorkingBeatmap workingBeatmap) + public IEnumerable Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap) { var filename = GetFilename(workingBeatmap); @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Edit.Checks } // If the file is set, also make sure it still exists. - var storagePath = workingBeatmap.Beatmap.BeatmapInfo.BeatmapSet.GetPathForFile(filename); + var storagePath = playableBeatmap.BeatmapInfo.BeatmapSet.GetPathForFile(filename); if (storagePath != null) yield break; diff --git a/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs b/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs index c3a64b58e9..31a7583941 100644 --- a/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs +++ b/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs @@ -24,7 +24,8 @@ namespace osu.Game.Rulesets.Edit.Checks.Components /// /// Runs this check and returns any issues detected for the provided beatmap. /// - /// The beatmap to run the check on. - public IEnumerable Run(IWorkingBeatmap workingBeatmap); + /// The playable beatmap of the beatmap to run the check on. + /// The working beatmap of the beatmap to run the check on. + public IEnumerable Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap); } } diff --git a/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs b/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs index 12be8815e1..b598176a35 100644 --- a/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs @@ -12,6 +12,6 @@ namespace osu.Game.Rulesets.Edit /// public interface IBeatmapVerifier { - public IEnumerable Run(WorkingBeatmap workingBeatmap); + public IEnumerable Run(IBeatmap playableBeatmap, WorkingBeatmap workingBeatmap); } } diff --git a/osu.Game/Screens/Edit/Verify/VerifyScreen.cs b/osu.Game/Screens/Edit/Verify/VerifyScreen.cs index 6aa479b38d..393c89fe52 100644 --- a/osu.Game/Screens/Edit/Verify/VerifyScreen.cs +++ b/osu.Game/Screens/Edit/Verify/VerifyScreen.cs @@ -124,10 +124,10 @@ namespace osu.Game.Screens.Edit.Verify private void refresh() { var workingBeatmap = beatmapManager.GetWorkingBeatmap(beatmap.BeatmapInfo); - var issues = generalVerifier.Run(workingBeatmap); + var issues = generalVerifier.Run(beatmap.PlayableBeatmap, workingBeatmap); if (rulesetVerifier != null) - issues = issues.Concat(rulesetVerifier.Run(workingBeatmap)); + issues = issues.Concat(rulesetVerifier.Run(beatmap.PlayableBeatmap, workingBeatmap)); table.Issues = issues .OrderBy(issue => issue.Template.Type) From be6a02a17e3f5621d7f6942678d278748cd88cec Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Tue, 20 Apr 2021 01:32:22 +0200 Subject: [PATCH 14/29] Simplify background quality test names --- .../Editing/Checks/CheckBackgroundQualityTest.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs b/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs index 42d143cc04..b6970a99e4 100644 --- a/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs @@ -49,7 +49,7 @@ namespace osu.Game.Tests.Editing.Checks } [Test] - public void TestBackgroundMissing() + public void TestMissing() { // While this is a problem, it is out of scope for this check and is caught by a different one. beatmap.Metadata.BackgroundFile = null; @@ -59,7 +59,7 @@ namespace osu.Game.Tests.Editing.Checks } [Test] - public void TestBackgroundAcceptable() + public void TestAcceptable() { var mock = getMockWorkingBeatmap(new Texture(1920, 1080)); @@ -67,7 +67,7 @@ namespace osu.Game.Tests.Editing.Checks } [Test] - public void TestBackgroundTooHighResolution() + public void TestTooHighResolution() { var mock = getMockWorkingBeatmap(new Texture(3840, 2160)); @@ -78,7 +78,7 @@ namespace osu.Game.Tests.Editing.Checks } [Test] - public void TestBackgroundLowResolution() + public void TestLowResolution() { var mock = getMockWorkingBeatmap(new Texture(640, 480)); @@ -89,7 +89,7 @@ namespace osu.Game.Tests.Editing.Checks } [Test] - public void TestBackgroundTooLowResolution() + public void TestTooLowResolution() { var mock = getMockWorkingBeatmap(new Texture(100, 100)); @@ -100,7 +100,7 @@ namespace osu.Game.Tests.Editing.Checks } [Test] - public void TestBackgroundTooUncompressed() + public void TestTooUncompressed() { var mock = getMockWorkingBeatmap(new Texture(1920, 1080), new byte[1024 * 1024 * 3]); From 14c626ffcbff01f250a7008ebb8469181f5d6f95 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Tue, 20 Apr 2021 01:33:19 +0200 Subject: [PATCH 15/29] Use the playable beatmap for file presence checks --- osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs | 2 +- osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs | 2 +- osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs b/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs index 55e53ef519..2d572a521e 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs @@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Edit.Checks { protected override CheckCategory Category => CheckCategory.Audio; protected override string TypeOfFile => "audio"; - protected override string GetFilename(IWorkingBeatmap workingBeatmap) => workingBeatmap.Beatmap.Metadata?.AudioFile; + protected override string GetFilename(IBeatmap playableBeatmap) => playableBeatmap.Metadata?.AudioFile; } } diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs index 3a229b889b..233c708a25 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs @@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Edit.Checks { protected override CheckCategory Category => CheckCategory.Resources; protected override string TypeOfFile => "background"; - protected override string GetFilename(IWorkingBeatmap workingBeatmap) => workingBeatmap.Beatmap.Metadata?.BackgroundFile; + protected override string GetFilename(IBeatmap playableBeatmap) => playableBeatmap.Metadata?.BackgroundFile; } } diff --git a/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs b/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs index 340b053fdb..006fc57c04 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Edit.Checks { protected abstract CheckCategory Category { get; } protected abstract string TypeOfFile { get; } - protected abstract string GetFilename(IWorkingBeatmap workingBeatmap); + protected abstract string GetFilename(IBeatmap playableBeatmap); public CheckMetadata Metadata => new CheckMetadata(Category, $"Missing {TypeOfFile}"); @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Edit.Checks public IEnumerable Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap) { - var filename = GetFilename(workingBeatmap); + var filename = GetFilename(playableBeatmap); if (filename == null) { From 40ae856dfc4cb5006f43f10e3b1363e8434cb5ea Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Tue, 20 Apr 2021 01:34:05 +0200 Subject: [PATCH 16/29] Show 2 decimals for background filesize --- osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs index 767c2b94b5..59fee74023 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs @@ -88,7 +88,7 @@ namespace osu.Game.Rulesets.Edit.Checks public class IssueTemplateTooUncompressed : IssueTemplate { public IssueTemplateTooUncompressed(ICheck check) - : base(check, IssueType.Problem, "The background filesize ({0:0.#} MB) exceeds {1} MB.") + : base(check, IssueType.Problem, "The background filesize ({0:0.##} MB) exceeds {1} MB.") { } From f168247254424bda53e90680bfc45e83b69e7f22 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Tue, 20 Apr 2021 01:35:41 +0200 Subject: [PATCH 17/29] Add `Track` as a property to `IWorkingBeatmap` This is implemented by `WorkingBeatmap` already, and is much better to use than loading the track every time we need it. --- osu.Game/Beatmaps/IWorkingBeatmap.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index f1bf6f48ef..b1cf6db6fc 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -42,6 +42,11 @@ namespace osu.Game.Beatmaps /// ISkin Skin { get; } + /// + /// Get the loaded audio track instance. + /// + Track Track { get; } + /// /// Constructs a playable from using the applicable converters for a specific . /// From c633f155653ef109898471b489e2ef466f1a10fc Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Tue, 20 Apr 2021 01:36:03 +0200 Subject: [PATCH 18/29] Add audio quality check --- osu.Game/Rulesets/Edit/BeatmapVerifier.cs | 2 + .../Rulesets/Edit/Checks/CheckAudioQuality.cs | 75 +++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs index 9efaa94b40..f33feac971 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs @@ -19,8 +19,10 @@ namespace osu.Game.Rulesets.Edit // Resources new CheckBackgroundPresence(), new CheckBackgroundQuality(), + // Audio new CheckAudioPresence(), + new CheckAudioQuality() }; public IEnumerable Run(IBeatmap playableBeatmap, WorkingBeatmap workingBeatmap) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs new file mode 100644 index 0000000000..b67374c023 --- /dev/null +++ b/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs @@ -0,0 +1,75 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit.Checks.Components; + +namespace osu.Game.Rulesets.Edit.Checks +{ + public class CheckAudioQuality : ICheck + { + // This is a requirement as stated in the Ranking Criteria. + // See https://osu.ppy.sh/wiki/en/Ranking_Criteria#rules.4 + private const int max_bitrate = 192; + + // "A song's audio file /.../ must be of reasonable quality. Try to find the highest quality source file available" + // There not existing a version with a bitrate of 128 kbps or higher is extremely rare. + private const int min_bitrate = 128; + + public CheckMetadata Metadata { get; } = new CheckMetadata(CheckCategory.Resources, "Too high or low audio bitrate"); + + public IEnumerable PossibleTemplates => new IssueTemplate[] + { + new IssueTemplateTooHighBitrate(this), + new IssueTemplateTooLowBitrate(this), + new IssueTemplateNoBitrate(this) + }; + + public IEnumerable Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap) + { + var audioFile = playableBeatmap.Metadata?.AudioFile; + if (audioFile == null) + yield break; + + var track = workingBeatmap.Track; + + if (track?.Bitrate == null || track.Bitrate.Value == 0) + yield return new IssueTemplateNoBitrate(this).Create(); + else if (track.Bitrate.Value > max_bitrate) + yield return new IssueTemplateTooHighBitrate(this).Create(track.Bitrate.Value); + else if (track.Bitrate.Value < min_bitrate) + yield return new IssueTemplateTooLowBitrate(this).Create(track.Bitrate.Value); + } + + public class IssueTemplateTooHighBitrate : IssueTemplate + { + public IssueTemplateTooHighBitrate(ICheck check) + : base(check, IssueType.Problem, "The audio bitrate ({0} kbps) exceeds {1} kbps.") + { + } + + public Issue Create(int bitrate) => new Issue(this, bitrate, max_bitrate); + } + + public class IssueTemplateTooLowBitrate : IssueTemplate + { + public IssueTemplateTooLowBitrate(ICheck check) + : base(check, IssueType.Problem, "The audio bitrate ({0} kbps) is lower than {1} kbps.") + { + } + + public Issue Create(int bitrate) => new Issue(this, bitrate, min_bitrate); + } + + public class IssueTemplateNoBitrate : IssueTemplate + { + public IssueTemplateNoBitrate(ICheck check) + : base(check, IssueType.Error, "The audio bitrate could not be retrieved.") + { + } + + public Issue Create() => new Issue(this); + } + } +} From 2bb079ea1403479e1bf513eb63fdc3f1d98bceb3 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Tue, 20 Apr 2021 01:36:15 +0200 Subject: [PATCH 19/29] Add audio quality check tests --- .../Editing/Checks/CheckAudioQualityTest.cs | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs diff --git a/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs b/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs new file mode 100644 index 0000000000..e73d9adfb0 --- /dev/null +++ b/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs @@ -0,0 +1,114 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using Moq; +using NUnit.Framework; +using osu.Framework.Audio.Track; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit.Checks; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Tests.Editing.Checks +{ + [TestFixture] + public class CheckAudioQualityTest + { + private CheckAudioQuality check; + private IBeatmap beatmap; + + [SetUp] + public void Setup() + { + check = new CheckAudioQuality(); + beatmap = new Beatmap + { + BeatmapInfo = new BeatmapInfo + { + Metadata = new BeatmapMetadata { AudioFile = "abc123.jpg" } + } + }; + } + + [Test] + public void TestMissing() + { + // While this is a problem, it is out of scope for this check and is caught by a different one. + beatmap.Metadata.AudioFile = null; + + var mock = new Mock(); + mock.SetupGet(_ => _.Beatmap).Returns(beatmap); + mock.SetupGet(_ => _.Track).Returns((Track)null); + + Assert.That(check.Run(beatmap, mock.Object), Is.Empty); + } + + [Test] + public void TestAcceptable() + { + var mock = getMockWorkingBeatmap(192); + + Assert.That(check.Run(beatmap, mock.Object), Is.Empty); + } + + [Test] + public void TestNullBitrate() + { + var mock = getMockWorkingBeatmap(null); + + var issues = check.Run(beatmap, mock.Object).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAudioQuality.IssueTemplateNoBitrate); + } + + [Test] + public void TestZeroBitrate() + { + var mock = getMockWorkingBeatmap(0); + + var issues = check.Run(beatmap, mock.Object).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAudioQuality.IssueTemplateNoBitrate); + } + + [Test] + public void TestTooHighBitrate() + { + var mock = getMockWorkingBeatmap(320); + + var issues = check.Run(beatmap, mock.Object).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAudioQuality.IssueTemplateTooHighBitrate); + } + + [Test] + public void TestTooLowBitrate() + { + var mock = getMockWorkingBeatmap(64); + + var issues = check.Run(beatmap, mock.Object).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAudioQuality.IssueTemplateTooLowBitrate); + } + + /// + /// Returns the mock of the working beatmap with the given audio properties. + /// + /// The bitrate of the audio file the beatmap uses. + private Mock getMockWorkingBeatmap(int? audioBitrate) + { + var mockTrack = new Mock(); + mockTrack.SetupGet(_ => _.Bitrate).Returns(audioBitrate); + + var mockWorkingBeatmap = new Mock(); + mockWorkingBeatmap.SetupGet(_ => _.Beatmap).Returns(beatmap); + mockWorkingBeatmap.SetupGet(_ => _.Track).Returns(mockTrack.Object); + + return mockWorkingBeatmap; + } + } +} From 4510e795e1326257168b1174a551ecf281a45563 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Tue, 20 Apr 2021 02:13:26 +0200 Subject: [PATCH 20/29] Fix category of audio quality check --- osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs index b67374c023..c1074d7c74 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Edit.Checks // There not existing a version with a bitrate of 128 kbps or higher is extremely rare. private const int min_bitrate = 128; - public CheckMetadata Metadata { get; } = new CheckMetadata(CheckCategory.Resources, "Too high or low audio bitrate"); + public CheckMetadata Metadata { get; } = new CheckMetadata(CheckCategory.Audio, "Too high or low audio bitrate"); public IEnumerable PossibleTemplates => new IssueTemplate[] { From 67e4fe42847fab7f6cc47b422257971b13979e06 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Tue, 20 Apr 2021 02:28:38 +0200 Subject: [PATCH 21/29] Add xmldoc to `GetStream` --- osu.Game/Beatmaps/IWorkingBeatmap.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index b1cf6db6fc..053c6d373f 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -74,6 +74,10 @@ namespace osu.Game.Beatmaps /// A fresh track instance, which will also be available via . Track LoadTrack(); + /// + /// Returns the stream of the file from the given storage path. + /// + /// The storage path to the file. Stream GetStream(string storagePath); } } From 1478bcfa8e774dcbb3e1b785b94bae10c2d8acbd Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Tue, 20 Apr 2021 02:30:27 +0200 Subject: [PATCH 22/29] Improve xmldoc consistency --- osu.Game/Beatmaps/IWorkingBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index 053c6d373f..a916b37b85 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -43,7 +43,7 @@ namespace osu.Game.Beatmaps ISkin Skin { get; } /// - /// Get the loaded audio track instance. + /// Retrieves the which this has loaded. /// Track Track { get; } From 496df411a7e20485adf374233f5f4d93a292d6b7 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Tue, 20 Apr 2021 02:39:11 +0200 Subject: [PATCH 23/29] Remove now unused import --- osu.Game/Screens/Edit/Verify/VerifyScreen.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Verify/VerifyScreen.cs b/osu.Game/Screens/Edit/Verify/VerifyScreen.cs index 2ab529cb27..530f24300b 100644 --- a/osu.Game/Screens/Edit/Verify/VerifyScreen.cs +++ b/osu.Game/Screens/Edit/Verify/VerifyScreen.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; -using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; From 5262d94e21e630c794c8a6356d12f44f38ce33a0 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Tue, 20 Apr 2021 13:21:57 +0200 Subject: [PATCH 24/29] Fix wrong assert in offscreen test --- .../Editor/Checks/CheckOffscreenObjectsTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs index 3a4817398c..6139b0e676 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs @@ -138,7 +138,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks [Test] public void TestSliderNearEdgeStackedOffscreen() { - assertOk(new Beatmap + assertOffscreenSlider(new Beatmap { HitObjects = new List { From 6a1e4ff99f41091d04f82bb721525af410eb10b7 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Tue, 20 Apr 2021 13:28:32 +0200 Subject: [PATCH 25/29] Add file hash to file presence test Necessary because we now find the storage path of the file rather than just the file itself. --- osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs b/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs index fe2e16ffd8..f6e875a8fc 100644 --- a/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Game.Beatmaps; +using osu.Game.IO; using osu.Game.Rulesets.Edit.Checks; using osu.Game.Rulesets.Objects; using osu.Game.Tests.Beatmaps; @@ -30,7 +31,11 @@ namespace osu.Game.Tests.Editing.Checks { Files = new List(new[] { - new BeatmapSetFileInfo { Filename = "abc123.jpg" } + new BeatmapSetFileInfo + { + Filename = "abc123.jpg", + FileInfo = new FileInfo { Hash = "abcdef" } + } }) } } From c0318a4d3ef401f4b3288d14ac4188f995a5f0d1 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Tue, 20 Apr 2021 13:29:14 +0200 Subject: [PATCH 26/29] Fix usage of _ in Moq lambdas --- osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs | 10 +++++----- .../Editing/Checks/CheckBackgroundQualityTest.cs | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs b/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs index e73d9adfb0..7658ca728d 100644 --- a/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs @@ -37,8 +37,8 @@ namespace osu.Game.Tests.Editing.Checks beatmap.Metadata.AudioFile = null; var mock = new Mock(); - mock.SetupGet(_ => _.Beatmap).Returns(beatmap); - mock.SetupGet(_ => _.Track).Returns((Track)null); + mock.SetupGet(w => w.Beatmap).Returns(beatmap); + mock.SetupGet(w => w.Track).Returns((Track)null); Assert.That(check.Run(beatmap, mock.Object), Is.Empty); } @@ -102,11 +102,11 @@ namespace osu.Game.Tests.Editing.Checks private Mock getMockWorkingBeatmap(int? audioBitrate) { var mockTrack = new Mock(); - mockTrack.SetupGet(_ => _.Bitrate).Returns(audioBitrate); + mockTrack.SetupGet(t => t.Bitrate).Returns(audioBitrate); var mockWorkingBeatmap = new Mock(); - mockWorkingBeatmap.SetupGet(_ => _.Beatmap).Returns(beatmap); - mockWorkingBeatmap.SetupGet(_ => _.Track).Returns(mockTrack.Object); + mockWorkingBeatmap.SetupGet(w => w.Beatmap).Returns(beatmap); + mockWorkingBeatmap.SetupGet(w => w.Track).Returns(mockTrack.Object); return mockWorkingBeatmap; } diff --git a/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs b/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs index b6970a99e4..f0f972d2fa 100644 --- a/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs @@ -120,9 +120,9 @@ namespace osu.Game.Tests.Editing.Checks var stream = new MemoryStream(fileBytes ?? new byte[1024 * 1024]); var mock = new Mock(); - mock.SetupGet(_ => _.Beatmap).Returns(beatmap); - mock.SetupGet(_ => _.Background).Returns(background); - mock.Setup(_ => _.GetStream(It.IsAny())).Returns(stream); + mock.SetupGet(w => w.Beatmap).Returns(beatmap); + mock.SetupGet(w => w.Background).Returns(background); + mock.Setup(w => w.GetStream(It.IsAny())).Returns(stream); return mock; } From 3e1b6b3b346ea449a3504eb71961f7446bf84379 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Tue, 20 Apr 2021 13:34:12 +0200 Subject: [PATCH 27/29] Simplify verifier run call args Uses the resolved working beatmap instead of resolving it every time. Also uses the EditorBeatmap itself as playable beatmap, as it is of type `IBeatmap` already, and `.PlayableBeatmap` forwards everything anyway. --- osu.Game/Screens/Edit/Verify/VerifyScreen.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Verify/VerifyScreen.cs b/osu.Game/Screens/Edit/Verify/VerifyScreen.cs index 530f24300b..9de1f04271 100644 --- a/osu.Game/Screens/Edit/Verify/VerifyScreen.cs +++ b/osu.Game/Screens/Edit/Verify/VerifyScreen.cs @@ -61,7 +61,7 @@ namespace osu.Game.Screens.Edit.Verify private EditorClock clock { get; set; } [Resolved] - private BeatmapManager beatmapManager { get; set; } + private IBindable workingBeatmap { get; set; } [Resolved] private EditorBeatmap beatmap { get; set; } @@ -122,11 +122,10 @@ namespace osu.Game.Screens.Edit.Verify private void refresh() { - var workingBeatmap = beatmapManager.GetWorkingBeatmap(beatmap.BeatmapInfo); - var issues = generalVerifier.Run(beatmap.PlayableBeatmap, workingBeatmap); + var issues = generalVerifier.Run(beatmap, workingBeatmap.Value); if (rulesetVerifier != null) - issues = issues.Concat(rulesetVerifier.Run(beatmap.PlayableBeatmap, workingBeatmap)); + issues = issues.Concat(rulesetVerifier.Run(beatmap, workingBeatmap.Value)); table.Issues = issues .OrderBy(issue => issue.Template.Type) From d7a81471c85a4aff21279974092847c4331355aa Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Tue, 20 Apr 2021 13:40:38 +0200 Subject: [PATCH 28/29] Add xmldoc to `GetPathForFile` --- osu.Game/Beatmaps/BeatmapSetInfo.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 774bd0bc62..d90ede5d4b 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -59,6 +59,10 @@ namespace osu.Game.Beatmaps public string StoryboardFile => Files?.Find(f => f.Filename.EndsWith(".osb", StringComparison.OrdinalIgnoreCase))?.Filename; + /// + /// Returns the storage path for the file in this beatmapset with the given filename, if any exists, otherwise null. + /// + /// The name of the file to get the storage path of. public string GetPathForFile(string filename) => Files?.SingleOrDefault(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath; public List Files { get; set; } From e9dfa2860a4fd63f61f0ad2a26d9677d6b4498fb Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Tue, 20 Apr 2021 13:44:06 +0200 Subject: [PATCH 29/29] Add xmldoc note about path being relative --- osu.Game/Beatmaps/BeatmapSetInfo.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index d90ede5d4b..1ce42535a0 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -61,6 +61,7 @@ namespace osu.Game.Beatmaps /// /// Returns the storage path for the file in this beatmapset with the given filename, if any exists, otherwise null. + /// The path returned is relative to the user file storage. /// /// The name of the file to get the storage path of. public string GetPathForFile(string filename) => Files?.SingleOrDefault(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath;