From 4c372539a15fc1be0ff437dc3a007c9019282244 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Jun 2022 17:57:04 +0900 Subject: [PATCH 1/8] Consolidate remaining methods in `BeatmapModelManager` --- osu.Game/Beatmaps/BeatmapModelManager.cs | 30 +++++++----------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapModelManager.cs b/osu.Game/Beatmaps/BeatmapModelManager.cs index 055eb36850..11230caa7d 100644 --- a/osu.Game/Beatmaps/BeatmapModelManager.cs +++ b/osu.Game/Beatmaps/BeatmapModelManager.cs @@ -29,10 +29,6 @@ namespace osu.Game.Beatmaps /// public IWorkingBeatmapCache? WorkingBeatmapCache { private get; set; } - public override IEnumerable HandledExtensions => new[] { ".osz" }; - - protected override string[] HashableFileTypes => new[] { ".osu" }; - public static readonly string[] VIDEO_EXTENSIONS = { ".mp4", ".mov", ".avi", ".flv" }; public BeatmapModelManager(RealmAccess realm, Storage storage, BeatmapOnlineLookupQueue? onlineLookupQueue = null) @@ -71,7 +67,7 @@ namespace osu.Game.Beatmaps // AddFile generally handles updating/replacing files, but this is a case where the filename may have also changed so let's delete for simplicity. var existingFileInfo = setInfo.Files.SingleOrDefault(f => string.Equals(f.Filename, beatmapInfo.Path, StringComparison.OrdinalIgnoreCase)); - string targetFilename = getFilename(beatmapInfo); + string targetFilename = createBeatmapFilenameFromMetadata(beatmapInfo); // ensure that two difficulties from the set don't point at the same beatmap file. if (setInfo.Beatmaps.Any(b => b.ID != beatmapInfo.ID && string.Equals(b.Path, targetFilename, StringComparison.OrdinalIgnoreCase))) @@ -83,17 +79,18 @@ namespace osu.Game.Beatmaps beatmapInfo.MD5Hash = stream.ComputeMD5Hash(); beatmapInfo.Hash = stream.ComputeSHA2Hash(); - AddFile(setInfo, stream, getFilename(beatmapInfo)); - Update(setInfo); + AddFile(setInfo, stream, createBeatmapFilenameFromMetadata(beatmapInfo)); + + Realm.Write(r => setInfo.CopyChangesToRealm(r.Find(setInfo.ID))); } WorkingBeatmapCache?.Invalidate(beatmapInfo); - } - private static string getFilename(BeatmapInfo beatmapInfo) - { - var metadata = beatmapInfo.Metadata; - return $"{metadata.Artist} - {metadata.Title} ({metadata.Author.Username}) [{beatmapInfo.DifficultyName}].osu".GetValidArchiveContentFilename(); + static string createBeatmapFilenameFromMetadata(BeatmapInfo beatmapInfo) + { + var metadata = beatmapInfo.Metadata; + return $"{metadata.Artist} - {metadata.Title} ({metadata.Author.Username}) [{beatmapInfo.DifficultyName}].osu".GetValidArchiveContentFilename(); + } } /// @@ -106,15 +103,6 @@ namespace osu.Game.Beatmaps return Realm.Run(realm => realm.All().FirstOrDefault(query)?.Detach()); } - public void Update(BeatmapSetInfo item) - { - Realm.Write(r => - { - var existing = r.Find(item.ID); - item.CopyChangesToRealm(existing); - }); - } - /// /// Delete videos from a list of beatmaps. /// This will post notifications tracking progress. From 84dba36cf564e49cdf526588d111c2ed28975587 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Jun 2022 17:59:07 +0900 Subject: [PATCH 2/8] Update usages of `BeatmapModelManager` which only require importing to use `BeatmapImporter` --- .../Database/BeatmapImporterTests.cs | 52 +++++++++---------- osu.Game/Beatmaps/BeatmapImporter.cs | 4 +- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/osu.Game.Tests/Database/BeatmapImporterTests.cs b/osu.Game.Tests/Database/BeatmapImporterTests.cs index a057f893f4..03e388c821 100644 --- a/osu.Game.Tests/Database/BeatmapImporterTests.cs +++ b/osu.Game.Tests/Database/BeatmapImporterTests.cs @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using (var importer = new BeatmapModelManager(realm, storage)) + using (var importer = new BeatmapImporter(realm, storage)) using (new RealmRulesetStore(realm, storage)) { Live? beatmapSet; @@ -82,7 +82,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using (var importer = new BeatmapModelManager(realm, storage)) + using (var importer = new BeatmapImporter(realm, storage)) using (new RealmRulesetStore(realm, storage)) { Live? beatmapSet; @@ -141,7 +141,7 @@ namespace osu.Game.Tests.Database { BeatmapSetInfo? detachedSet = null; - using (var importer = new BeatmapModelManager(realm, storage)) + using (var importer = new BeatmapImporter(realm, storage)) using (new RealmRulesetStore(realm, storage)) { Task.Run(async () => @@ -170,7 +170,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using (var importer = new BeatmapModelManager(realm, storage)) + using (var importer = new BeatmapImporter(realm, storage)) using (new RealmRulesetStore(realm, storage)) { Live? imported; @@ -202,7 +202,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); await LoadOszIntoStore(importer, realm.Realm); @@ -214,7 +214,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); var imported = await LoadOszIntoStore(importer, realm.Realm); @@ -232,7 +232,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); var imported = await LoadOszIntoStore(importer, realm.Realm); @@ -246,7 +246,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); string? tempPath = TestResources.GetTestBeatmapForImport(); @@ -276,7 +276,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); var imported = await LoadOszIntoStore(importer, realm.Realm); @@ -296,7 +296,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); string? temp = TestResources.GetTestBeatmapForImport(); @@ -345,7 +345,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); string? temp = TestResources.GetTestBeatmapForImport(); @@ -396,7 +396,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); string? temp = TestResources.GetTestBeatmapForImport(); @@ -444,7 +444,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); string? temp = TestResources.GetTestBeatmapForImport(); @@ -492,7 +492,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); var imported = await LoadOszIntoStore(importer, realm.Realm); @@ -527,7 +527,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); var progressNotification = new ImportProgressNotification(); @@ -565,7 +565,7 @@ namespace osu.Game.Tests.Database Interlocked.Increment(ref loggedExceptionCount); }; - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); var imported = await LoadOszIntoStore(importer, realm.Realm); @@ -617,7 +617,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); var imported = await LoadOszIntoStore(importer, realm.Realm, batchImport: true); @@ -644,7 +644,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realmFactory, storage) => { - using var importer = new BeatmapModelManager(realmFactory, storage); + using var importer = new BeatmapImporter(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage); var imported = await LoadOszIntoStore(importer, realmFactory.Realm); @@ -676,7 +676,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); var imported = await LoadOszIntoStore(importer, realm.Realm); @@ -703,7 +703,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); var imported = await LoadOszIntoStore(importer, realm.Realm); @@ -729,7 +729,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealm((realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); var metadata = new BeatmapMetadata @@ -777,7 +777,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); string? temp = TestResources.GetTestBeatmapForImport(); @@ -794,7 +794,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); string? temp = TestResources.GetTestBeatmapForImport(); @@ -830,7 +830,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); string? temp = TestResources.GetTestBeatmapForImport(); @@ -872,7 +872,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); string? temp = TestResources.GetTestBeatmapForImport(); @@ -923,7 +923,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + using var importer = new BeatmapImporter(realm, storage); using var store = new RealmRulesetStore(realm, storage); string? temp = TestResources.GetTestBeatmapForImport(); diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs index a2ab70fed8..eded4cf9d1 100644 --- a/osu.Game/Beatmaps/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -32,7 +32,7 @@ namespace osu.Game.Beatmaps /// Handles the storage and retrieval of Beatmaps/WorkingBeatmaps. /// [ExcludeFromDynamicCompile] - public abstract class BeatmapImporter : RealmArchiveModelManager, IDisposable + public class BeatmapImporter : RealmArchiveModelManager, IDisposable { public override IEnumerable HandledExtensions => new[] { ".osz" }; @@ -40,7 +40,7 @@ namespace osu.Game.Beatmaps private readonly BeatmapOnlineLookupQueue? onlineLookupQueue; - protected BeatmapImporter(RealmAccess realm, Storage storage, BeatmapOnlineLookupQueue? onlineLookupQueue = null) + public BeatmapImporter(RealmAccess realm, Storage storage, BeatmapOnlineLookupQueue? onlineLookupQueue = null) : base(storage, realm) { this.onlineLookupQueue = onlineLookupQueue; From 8ea3042435ed60906f01037c1cc36bb312cd5f73 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Jun 2022 18:00:27 +0900 Subject: [PATCH 3/8] Move file extensions specification to common class --- osu.Game/Beatmaps/BeatmapModelManager.cs | 4 +--- osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs | 3 +-- osu.Game/OsuGameBase.cs | 2 ++ 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapModelManager.cs b/osu.Game/Beatmaps/BeatmapModelManager.cs index 11230caa7d..768bed6d67 100644 --- a/osu.Game/Beatmaps/BeatmapModelManager.cs +++ b/osu.Game/Beatmaps/BeatmapModelManager.cs @@ -29,8 +29,6 @@ namespace osu.Game.Beatmaps /// public IWorkingBeatmapCache? WorkingBeatmapCache { private get; set; } - public static readonly string[] VIDEO_EXTENSIONS = { ".mp4", ".mov", ".avi", ".flv" }; - public BeatmapModelManager(RealmAccess realm, Storage storage, BeatmapOnlineLookupQueue? onlineLookupQueue = null) : base(realm, storage, onlineLookupQueue) { @@ -131,7 +129,7 @@ namespace osu.Game.Beatmaps // user requested abort return; - var video = b.Files.FirstOrDefault(f => VIDEO_EXTENSIONS.Any(ex => f.Filename.EndsWith(ex, StringComparison.Ordinal))); + var video = b.Files.FirstOrDefault(f => OsuGameBase.VIDEO_EXTENSIONS.Any(ex => f.Filename.EndsWith(ex, StringComparison.Ordinal))); if (video != null) { diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs b/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs index d9dbf4974b..7c88e12dd3 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; -using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -67,7 +66,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { get { - if (BeatmapModelManager.VIDEO_EXTENSIONS.Contains(File.Extension)) + if (OsuGameBase.VIDEO_EXTENSIONS.Contains(File.Extension)) return FontAwesome.Regular.FileVideo; switch (File.Extension) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 993ca5b5e8..5c8620fba4 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -57,6 +57,8 @@ namespace osu.Game /// public partial class OsuGameBase : Framework.Game, ICanAcceptFiles, IBeatSyncProvider { + public static readonly string[] VIDEO_EXTENSIONS = { ".mp4", ".mov", ".avi", ".flv" }; + public const string OSU_PROTOCOL = "osu://"; public const string CLIENT_STREAM_NAME = @"lazer"; From 1f3e1b2d974f5e4c2fd1383963b744408f99ed9c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Jun 2022 18:07:04 +0900 Subject: [PATCH 4/8] Combine `BeatmapManager` and `BeatmapModelManager` into one class --- ...eneOnlinePlayBeatmapAvailabilityTracker.cs | 8 +- osu.Game/Beatmaps/BeatmapManager.cs | 192 ++++++++++++++---- osu.Game/Beatmaps/BeatmapModelManager.cs | 149 -------------- .../Database/RealmArchiveModelImporter.cs | 2 +- osu.Game/Tests/Visual/EditorTestScene.cs | 4 +- 5 files changed, 154 insertions(+), 201 deletions(-) delete mode 100644 osu.Game/Beatmaps/BeatmapModelManager.cs diff --git a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs index 4f255ddd00..915ad50d2b 100644 --- a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs +++ b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs @@ -210,16 +210,16 @@ namespace osu.Game.Tests.Online { } - protected override BeatmapModelManager CreateBeatmapModelManager(Storage storage, RealmAccess realm, RulesetStore rulesets, BeatmapOnlineLookupQueue onlineLookupQueue) + protected override BeatmapImporter CreateBeatmapImporter(Storage storage, RealmAccess realm, RulesetStore rulesets, BeatmapOnlineLookupQueue onlineLookupQueue) { - return new TestBeatmapModelManager(this, storage, realm, onlineLookupQueue); + return new TestBeatmapImporter(this, storage, realm, onlineLookupQueue); } - internal class TestBeatmapModelManager : BeatmapModelManager + internal class TestBeatmapImporter : BeatmapImporter { private readonly TestBeatmapManager testBeatmapManager; - public TestBeatmapModelManager(TestBeatmapManager testBeatmapManager, Storage storage, RealmAccess databaseAccess, BeatmapOnlineLookupQueue beatmapOnlineLookupQueue) + public TestBeatmapImporter(TestBeatmapManager testBeatmapManager, Storage storage, RealmAccess databaseAccess, BeatmapOnlineLookupQueue beatmapOnlineLookupQueue) : base(databaseAccess, storage, beatmapOnlineLookupQueue) { this.testBeatmapManager = testBeatmapManager; diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 9397c2f3b2..63bd7dc710 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -1,19 +1,26 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable enable + using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Linq.Expressions; +using System.Text; using System.Threading; using System.Threading.Tasks; using osu.Framework.Audio; using osu.Framework.Audio.Track; +using osu.Framework.Extensions; using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Framework.Testing; +using osu.Game.Beatmaps.Formats; using osu.Game.Database; +using osu.Game.Extensions; using osu.Game.IO.Archives; using osu.Game.Models; using osu.Game.Online.API; @@ -23,8 +30,6 @@ using osu.Game.Rulesets; using osu.Game.Skinning; using osu.Game.Utils; -#nullable enable - namespace osu.Game.Beatmaps { /// @@ -35,14 +40,15 @@ namespace osu.Game.Beatmaps { public ITrackStore BeatmapTrackStore { get; } - private readonly BeatmapModelManager beatmapModelManager; + private readonly BeatmapImporter beatmapImporter; private readonly WorkingBeatmapCache workingBeatmapCache; private readonly BeatmapOnlineLookupQueue? onlineBeatmapLookupQueue; private readonly RealmAccess realm; - public BeatmapManager(Storage storage, RealmAccess realm, RulesetStore rulesets, IAPIProvider? api, AudioManager audioManager, IResourceStore gameResources, GameHost? host = null, WorkingBeatmap? defaultBeatmap = null, bool performOnlineLookups = false) + public BeatmapManager(Storage storage, RealmAccess realm, RulesetStore rulesets, IAPIProvider? api, AudioManager audioManager, IResourceStore gameResources, GameHost? host = null, + WorkingBeatmap? defaultBeatmap = null, bool performOnlineLookups = false) { this.realm = realm; @@ -58,19 +64,18 @@ namespace osu.Game.Beatmaps BeatmapTrackStore = audioManager.GetTrackStore(userResources); - beatmapModelManager = CreateBeatmapModelManager(storage, realm, rulesets, onlineBeatmapLookupQueue); + beatmapImporter = CreateBeatmapImporter(storage, realm, rulesets, onlineBeatmapLookupQueue); workingBeatmapCache = CreateWorkingBeatmapCache(audioManager, gameResources, userResources, defaultBeatmap, host); - - beatmapModelManager.WorkingBeatmapCache = workingBeatmapCache; } - protected virtual WorkingBeatmapCache CreateWorkingBeatmapCache(AudioManager audioManager, IResourceStore resources, IResourceStore storage, WorkingBeatmap? defaultBeatmap, GameHost? host) + protected virtual WorkingBeatmapCache CreateWorkingBeatmapCache(AudioManager audioManager, IResourceStore resources, IResourceStore storage, WorkingBeatmap? defaultBeatmap, + GameHost? host) { return new WorkingBeatmapCache(BeatmapTrackStore, audioManager, resources, storage, defaultBeatmap, host); } - protected virtual BeatmapModelManager CreateBeatmapModelManager(Storage storage, RealmAccess realm, RulesetStore rulesets, BeatmapOnlineLookupQueue? onlineLookupQueue) => - new BeatmapModelManager(realm, storage, onlineLookupQueue); + protected virtual BeatmapImporter CreateBeatmapImporter(Storage storage, RealmAccess realm, RulesetStore rulesets, BeatmapOnlineLookupQueue? onlineLookupQueue) => + new BeatmapImporter(realm, storage, onlineLookupQueue); /// /// Create a new beatmap set, backed by a model, @@ -99,7 +104,7 @@ namespace osu.Game.Beatmaps foreach (BeatmapInfo b in beatmapSet.Beatmaps) b.BeatmapSet = beatmapSet; - var imported = beatmapModelManager.Import(beatmapSet); + var imported = beatmapImporter.Import(beatmapSet); if (imported == null) throw new InvalidOperationException("Failed to import new beatmap"); @@ -169,12 +174,12 @@ namespace osu.Game.Beatmaps private WorkingBeatmap addDifficultyToSet(BeatmapSetInfo targetBeatmapSet, IBeatmap newBeatmap, ISkin beatmapSkin) { // populate circular beatmap set info <-> beatmap info references manually. - // several places like `BeatmapModelManager.Save()` or `GetWorkingBeatmap()` + // several places like `BeatmapImporter.Save()` or `GetWorkingBeatmap()` // rely on them being freely traversable in both directions for correct operation. targetBeatmapSet.Beatmaps.Add(newBeatmap.BeatmapInfo); newBeatmap.BeatmapInfo.BeatmapSet = targetBeatmapSet; - beatmapModelManager.Save(newBeatmap.BeatmapInfo, newBeatmap, beatmapSkin); + Save(newBeatmap.BeatmapInfo, newBeatmap, beatmapSkin); workingBeatmapCache.Invalidate(targetBeatmapSet); return GetWorkingBeatmap(newBeatmap.BeatmapInfo); @@ -255,23 +260,14 @@ namespace osu.Game.Beatmaps return realm.Run(r => r.All().FirstOrDefault(query)?.ToLive(realm)); } - #region Delegation to BeatmapModelManager (methods which previously existed locally). + #region Delegation to BeatmapImporter (methods which previously existed locally). /// /// Perform a lookup query on available s. /// /// The query. /// The first result for the provided query, or null if no results were found. - public BeatmapInfo? QueryBeatmap(Expression> query) => beatmapModelManager.QueryBeatmap(query)?.Detach(); - - /// - /// Saves an file against a given . - /// - /// The to save the content against. The file referenced by will be replaced. - /// The content to write. - /// The beatmap content to write, null if to be omitted. - public virtual void Save(BeatmapInfo info, IBeatmap beatmapContent, ISkin? beatmapSkin = null) => - beatmapModelManager.Save(info, beatmapContent, beatmapSkin); + public BeatmapInfo? QueryBeatmap(Expression> query) => realm.Run(r => r.All().FirstOrDefault(query)?.Detach()); /// /// A default representation of a WorkingBeatmap to use when no beatmap is available. @@ -281,9 +277,10 @@ namespace osu.Game.Beatmaps /// /// Fired when a notification should be presented to the user. /// - public Action PostNotification + public Action? PostNotification { - set => beatmapModelManager.PostNotification = value; + get => beatmapImporter.PostNotification; + set => beatmapImporter.PostNotification = value; } #endregion @@ -292,17 +289,17 @@ namespace osu.Game.Beatmaps public bool IsAvailableLocally(BeatmapSetInfo model) { - return beatmapModelManager.IsAvailableLocally(model); + return beatmapImporter.IsAvailableLocally(model); } public bool Delete(BeatmapSetInfo item) { - return beatmapModelManager.Delete(item); + return beatmapImporter.Delete(item); } public void Delete(List items, bool silent = false) { - beatmapModelManager.Delete(items, silent); + beatmapImporter.Delete(items, silent); } public void Delete(Expression>? filter = null, bool silent = false) @@ -314,51 +311,156 @@ namespace osu.Game.Beatmaps if (filter != null) items = items.Where(filter); - beatmapModelManager.Delete(items.ToList(), silent); + beatmapImporter.Delete(items.ToList(), silent); }); } + /// + /// Saves an file against a given . + /// + /// The to save the content against. The file referenced by will be replaced. + /// The content to write. + /// The beatmap content to write, null if to be omitted. + public virtual void Save(BeatmapInfo beatmapInfo, IBeatmap beatmapContent, ISkin? beatmapSkin = null) + { + var setInfo = beatmapInfo.BeatmapSet; + Debug.Assert(setInfo != null); + + // Difficulty settings must be copied first due to the clone in `Beatmap<>.BeatmapInfo_Set`. + // This should hopefully be temporary, assuming said clone is eventually removed. + + // Warning: The directionality here is important. Changes have to be copied *from* beatmapContent (which comes from editor and is being saved) + // *to* the beatmapInfo (which is a database model and needs to receive values without the taiko slider velocity multiplier for correct operation). + // CopyTo() will undo such adjustments, while CopyFrom() will not. + beatmapContent.Difficulty.CopyTo(beatmapInfo.Difficulty); + + // All changes to metadata are made in the provided beatmapInfo, so this should be copied to the `IBeatmap` before encoding. + beatmapContent.BeatmapInfo = beatmapInfo; + + using (var stream = new MemoryStream()) + { + using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) + new LegacyBeatmapEncoder(beatmapContent, beatmapSkin).Encode(sw); + + stream.Seek(0, SeekOrigin.Begin); + + // AddFile generally handles updating/replacing files, but this is a case where the filename may have also changed so let's delete for simplicity. + var existingFileInfo = setInfo.Files.SingleOrDefault(f => string.Equals(f.Filename, beatmapInfo.Path, StringComparison.OrdinalIgnoreCase)); + string targetFilename = createBeatmapFilenameFromMetadata(beatmapInfo); + + // ensure that two difficulties from the set don't point at the same beatmap file. + if (setInfo.Beatmaps.Any(b => b.ID != beatmapInfo.ID && string.Equals(b.Path, targetFilename, StringComparison.OrdinalIgnoreCase))) + throw new InvalidOperationException($"{setInfo.GetDisplayString()} already has a difficulty with the name of '{beatmapInfo.DifficultyName}'."); + + if (existingFileInfo != null) + DeleteFile(setInfo, existingFileInfo); + + beatmapInfo.MD5Hash = stream.ComputeMD5Hash(); + beatmapInfo.Hash = stream.ComputeSHA2Hash(); + + AddFile(setInfo, stream, createBeatmapFilenameFromMetadata(beatmapInfo)); + + realm.Write(r => setInfo.CopyChangesToRealm(r.Find(setInfo.ID))); + } + + workingBeatmapCache.Invalidate(beatmapInfo); + + static string createBeatmapFilenameFromMetadata(BeatmapInfo beatmapInfo) + { + var metadata = beatmapInfo.Metadata; + return $"{metadata.Artist} - {metadata.Title} ({metadata.Author.Username}) [{beatmapInfo.DifficultyName}].osu".GetValidArchiveContentFilename(); + } + } + public void DeleteAllVideos() { realm.Write(r => { var items = r.All().Where(s => !s.DeletePending && !s.Protected); - beatmapModelManager.DeleteVideos(items.ToList()); + DeleteVideos(items.ToList()); }); } + /// + /// Delete videos from a list of beatmaps. + /// This will post notifications tracking progress. + /// + public void DeleteVideos(List items, bool silent = false) + { + if (items.Count == 0) return; + + var notification = new ProgressNotification + { + Progress = 0, + Text = $"Preparing to delete all {beatmapImporter.HumanisedModelName} videos...", + CompletionText = "No videos found to delete!", + State = ProgressNotificationState.Active, + }; + + if (!silent) + PostNotification?.Invoke(notification); + + int i = 0; + int deleted = 0; + + foreach (var b in items) + { + if (notification.State == ProgressNotificationState.Cancelled) + // user requested abort + return; + + var video = b.Files.FirstOrDefault(f => OsuGameBase.VIDEO_EXTENSIONS.Any(ex => f.Filename.EndsWith(ex, StringComparison.Ordinal))); + + if (video != null) + { + DeleteFile(b, video); + deleted++; + notification.CompletionText = $"Deleted {deleted} {beatmapImporter.HumanisedModelName} video(s)!"; + } + + notification.Text = $"Deleting videos from {beatmapImporter.HumanisedModelName}s ({deleted} deleted)"; + + notification.Progress = (float)++i / items.Count; + } + + notification.State = ProgressNotificationState.Completed; + } + public void UndeleteAll() { - realm.Run(r => beatmapModelManager.Undelete(r.All().Where(s => s.DeletePending).ToList())); + realm.Run(r => beatmapImporter.Undelete(r.All().Where(s => s.DeletePending).ToList())); } public void Undelete(List items, bool silent = false) { - beatmapModelManager.Undelete(items, silent); + beatmapImporter.Undelete(items, silent); } public void Undelete(BeatmapSetInfo item) { - beatmapModelManager.Undelete(item); + beatmapImporter.Undelete(item); } #endregion #region Implementation of ICanAcceptFiles - public Task Import(params string[] paths) => beatmapModelManager.Import(paths); + public Task Import(params string[] paths) => beatmapImporter.Import(paths); - public Task Import(params ImportTask[] tasks) => beatmapModelManager.Import(tasks); + public Task Import(params ImportTask[] tasks) => beatmapImporter.Import(tasks); - public Task>> Import(ProgressNotification notification, params ImportTask[] tasks) => beatmapModelManager.Import(notification, tasks); + public Task>> Import(ProgressNotification notification, params ImportTask[] tasks) => beatmapImporter.Import(notification, tasks); - public Task?> Import(ImportTask task, bool batchImport = false, CancellationToken cancellationToken = default) => beatmapModelManager.Import(task, batchImport, cancellationToken); + public Task?> Import(ImportTask task, bool batchImport = false, CancellationToken cancellationToken = default) => + beatmapImporter.Import(task, batchImport, cancellationToken); - public Task?> Import(ArchiveReader archive, bool batchImport = false, CancellationToken cancellationToken = default) => beatmapModelManager.Import(archive, batchImport, cancellationToken); + public Task?> Import(ArchiveReader archive, bool batchImport = false, CancellationToken cancellationToken = default) => + beatmapImporter.Import(archive, batchImport, cancellationToken); - public Live? Import(BeatmapSetInfo item, ArchiveReader? archive = null, CancellationToken cancellationToken = default) => beatmapModelManager.Import(item, archive, false, cancellationToken); + public Live? Import(BeatmapSetInfo item, ArchiveReader? archive = null, CancellationToken cancellationToken = default) => + beatmapImporter.Import(item, archive, false, cancellationToken); - public IEnumerable HandledExtensions => beatmapModelManager.HandledExtensions; + public IEnumerable HandledExtensions => beatmapImporter.HandledExtensions; #endregion @@ -400,17 +502,17 @@ namespace osu.Game.Beatmaps public void ReplaceFile(BeatmapSetInfo model, RealmNamedFileUsage file, Stream contents) { - beatmapModelManager.ReplaceFile(model, file, contents); + beatmapImporter.ReplaceFile(model, file, contents); } public void DeleteFile(BeatmapSetInfo model, RealmNamedFileUsage file) { - beatmapModelManager.DeleteFile(model, file); + beatmapImporter.DeleteFile(model, file); } public void AddFile(BeatmapSetInfo model, Stream contents, string filename) { - beatmapModelManager.AddFile(model, contents, filename); + beatmapImporter.AddFile(model, contents, filename); } #endregion @@ -428,7 +530,7 @@ namespace osu.Game.Beatmaps public Action>>? PostImport { - set => beatmapModelManager.PostImport = value; + set => beatmapImporter.PostImport = value; } #endregion diff --git a/osu.Game/Beatmaps/BeatmapModelManager.cs b/osu.Game/Beatmaps/BeatmapModelManager.cs deleted file mode 100644 index 768bed6d67..0000000000 --- a/osu.Game/Beatmaps/BeatmapModelManager.cs +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Linq.Expressions; -using System.Text; -using osu.Framework.Extensions; -using osu.Framework.Platform; -using osu.Framework.Testing; -using osu.Game.Beatmaps.Formats; -using osu.Game.Database; -using osu.Game.Extensions; -using osu.Game.Skinning; -using osu.Game.Overlays.Notifications; - -#nullable enable - -namespace osu.Game.Beatmaps -{ - [ExcludeFromDynamicCompile] - public class BeatmapModelManager : BeatmapImporter - { - /// - /// The game working beatmap cache, used to invalidate entries on changes. - /// - public IWorkingBeatmapCache? WorkingBeatmapCache { private get; set; } - - public BeatmapModelManager(RealmAccess realm, Storage storage, BeatmapOnlineLookupQueue? onlineLookupQueue = null) - : base(realm, storage, onlineLookupQueue) - { - } - - /// - /// Saves an file against a given . - /// - /// The to save the content against. The file referenced by will be replaced. - /// The content to write. - /// The beatmap content to write, null if to be omitted. - public void Save(BeatmapInfo beatmapInfo, IBeatmap beatmapContent, ISkin? beatmapSkin = null) - { - var setInfo = beatmapInfo.BeatmapSet; - Debug.Assert(setInfo != null); - - // Difficulty settings must be copied first due to the clone in `Beatmap<>.BeatmapInfo_Set`. - // This should hopefully be temporary, assuming said clone is eventually removed. - - // Warning: The directionality here is important. Changes have to be copied *from* beatmapContent (which comes from editor and is being saved) - // *to* the beatmapInfo (which is a database model and needs to receive values without the taiko slider velocity multiplier for correct operation). - // CopyTo() will undo such adjustments, while CopyFrom() will not. - beatmapContent.Difficulty.CopyTo(beatmapInfo.Difficulty); - - // All changes to metadata are made in the provided beatmapInfo, so this should be copied to the `IBeatmap` before encoding. - beatmapContent.BeatmapInfo = beatmapInfo; - - using (var stream = new MemoryStream()) - { - using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) - new LegacyBeatmapEncoder(beatmapContent, beatmapSkin).Encode(sw); - - stream.Seek(0, SeekOrigin.Begin); - - // AddFile generally handles updating/replacing files, but this is a case where the filename may have also changed so let's delete for simplicity. - var existingFileInfo = setInfo.Files.SingleOrDefault(f => string.Equals(f.Filename, beatmapInfo.Path, StringComparison.OrdinalIgnoreCase)); - string targetFilename = createBeatmapFilenameFromMetadata(beatmapInfo); - - // ensure that two difficulties from the set don't point at the same beatmap file. - if (setInfo.Beatmaps.Any(b => b.ID != beatmapInfo.ID && string.Equals(b.Path, targetFilename, StringComparison.OrdinalIgnoreCase))) - throw new InvalidOperationException($"{setInfo.GetDisplayString()} already has a difficulty with the name of '{beatmapInfo.DifficultyName}'."); - - if (existingFileInfo != null) - DeleteFile(setInfo, existingFileInfo); - - beatmapInfo.MD5Hash = stream.ComputeMD5Hash(); - beatmapInfo.Hash = stream.ComputeSHA2Hash(); - - AddFile(setInfo, stream, createBeatmapFilenameFromMetadata(beatmapInfo)); - - Realm.Write(r => setInfo.CopyChangesToRealm(r.Find(setInfo.ID))); - } - - WorkingBeatmapCache?.Invalidate(beatmapInfo); - - static string createBeatmapFilenameFromMetadata(BeatmapInfo beatmapInfo) - { - var metadata = beatmapInfo.Metadata; - return $"{metadata.Artist} - {metadata.Title} ({metadata.Author.Username}) [{beatmapInfo.DifficultyName}].osu".GetValidArchiveContentFilename(); - } - } - - /// - /// Perform a lookup query on available s. - /// - /// The query. - /// The first result for the provided query, or null if no results were found. - public BeatmapInfo? QueryBeatmap(Expression> query) - { - return Realm.Run(realm => realm.All().FirstOrDefault(query)?.Detach()); - } - - /// - /// Delete videos from a list of beatmaps. - /// This will post notifications tracking progress. - /// - public void DeleteVideos(List items, bool silent = false) - { - if (items.Count == 0) return; - - var notification = new ProgressNotification - { - Progress = 0, - Text = $"Preparing to delete all {HumanisedModelName} videos...", - CompletionText = "No videos found to delete!", - State = ProgressNotificationState.Active, - }; - - if (!silent) - PostNotification?.Invoke(notification); - - int i = 0; - int deleted = 0; - - foreach (var b in items) - { - if (notification.State == ProgressNotificationState.Cancelled) - // user requested abort - return; - - var video = b.Files.FirstOrDefault(f => OsuGameBase.VIDEO_EXTENSIONS.Any(ex => f.Filename.EndsWith(ex, StringComparison.Ordinal))); - - if (video != null) - { - DeleteFile(b, video); - deleted++; - notification.CompletionText = $"Deleted {deleted} {HumanisedModelName} video(s)!"; - } - - notification.Text = $"Deleting videos from {HumanisedModelName}s ({deleted} deleted)"; - - notification.Progress = (float)++i / items.Count; - } - - notification.State = ProgressNotificationState.Completed; - } - } -} diff --git a/osu.Game/Database/RealmArchiveModelImporter.cs b/osu.Game/Database/RealmArchiveModelImporter.cs index 4153f421ef..32e71c5521 100644 --- a/osu.Game/Database/RealmArchiveModelImporter.cs +++ b/osu.Game/Database/RealmArchiveModelImporter.cs @@ -72,7 +72,7 @@ namespace osu.Game.Database /// /// Set an endpoint for notifications to be posted to. /// - public Action? PostNotification { protected get; set; } + public Action? PostNotification { get; set; } protected RealmArchiveModelImporter(Storage storage, RealmAccess realm) { diff --git a/osu.Game/Tests/Visual/EditorTestScene.cs b/osu.Game/Tests/Visual/EditorTestScene.cs index 8e9bb6ff78..fbb5209513 100644 --- a/osu.Game/Tests/Visual/EditorTestScene.cs +++ b/osu.Game/Tests/Visual/EditorTestScene.cs @@ -145,9 +145,9 @@ namespace osu.Game.Tests.Visual { } - protected override BeatmapModelManager CreateBeatmapModelManager(Storage storage, RealmAccess realm, RulesetStore rulesets, BeatmapOnlineLookupQueue onlineLookupQueue) + protected override BeatmapImporter CreateBeatmapImporter(Storage storage, RealmAccess realm, RulesetStore rulesets, BeatmapOnlineLookupQueue onlineLookupQueue) { - return new BeatmapModelManager(realm, storage, onlineLookupQueue); + return new BeatmapImporter(realm, storage, onlineLookupQueue); } protected override WorkingBeatmapCache CreateWorkingBeatmapCache(AudioManager audioManager, IResourceStore resources, IResourceStore storage, WorkingBeatmap defaultBeatmap, GameHost host) From 4d9e3d1982b836c7ff4eaf10d6a4b83bc0c1719f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Jun 2022 18:11:50 +0900 Subject: [PATCH 5/8] Rename Score/Skin `ModelManager` classes to `Importer` for now --- ...{ScoreModelManager.cs => ScoreImporter.cs} | 4 +- osu.Game/Scoring/ScoreManager.cs | 34 +++++++-------- .../{SkinModelManager.cs => SkinImporter.cs} | 4 +- osu.Game/Skinning/SkinManager.cs | 42 +++++++++---------- 4 files changed, 42 insertions(+), 42 deletions(-) rename osu.Game/Scoring/{ScoreModelManager.cs => ScoreImporter.cs} (93%) rename osu.Game/Skinning/{SkinModelManager.cs => SkinImporter.cs} (98%) diff --git a/osu.Game/Scoring/ScoreModelManager.cs b/osu.Game/Scoring/ScoreImporter.cs similarity index 93% rename from osu.Game/Scoring/ScoreModelManager.cs rename to osu.Game/Scoring/ScoreImporter.cs index c88955c5fd..76c43ba2e2 100644 --- a/osu.Game/Scoring/ScoreModelManager.cs +++ b/osu.Game/Scoring/ScoreImporter.cs @@ -19,7 +19,7 @@ using Realms; namespace osu.Game.Scoring { - public class ScoreModelManager : RealmArchiveModelManager + public class ScoreImporter : RealmArchiveModelManager { public override IEnumerable HandledExtensions => new[] { ".osr" }; @@ -28,7 +28,7 @@ namespace osu.Game.Scoring private readonly RulesetStore rulesets; private readonly Func beatmaps; - public ScoreModelManager(RulesetStore rulesets, Func beatmaps, Storage storage, RealmAccess realm) + public ScoreImporter(RulesetStore rulesets, Func beatmaps, Storage storage, RealmAccess realm) : base(storage, realm) { this.rulesets = rulesets; diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index e857d2109f..125746d5dd 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -28,7 +28,7 @@ namespace osu.Game.Scoring private readonly Scheduler scheduler; private readonly Func difficulties; private readonly OsuConfigManager configManager; - private readonly ScoreModelManager scoreModelManager; + private readonly ScoreImporter scoreImporter; public ScoreManager(RulesetStore rulesets, Func beatmaps, Storage storage, RealmAccess realm, Scheduler scheduler, Func difficulties = null, OsuConfigManager configManager = null) @@ -38,10 +38,10 @@ namespace osu.Game.Scoring this.difficulties = difficulties; this.configManager = configManager; - scoreModelManager = new ScoreModelManager(rulesets, beatmaps, storage, realm); + scoreImporter = new ScoreImporter(rulesets, beatmaps, storage, realm); } - public Score GetScore(ScoreInfo score) => scoreModelManager.GetScore(score); + public Score GetScore(ScoreInfo score) => scoreImporter.GetScore(score); /// /// Perform a lookup query on available s. @@ -231,7 +231,7 @@ namespace osu.Game.Scoring public Action PostNotification { - set => scoreModelManager.PostNotification = value; + set => scoreImporter.PostNotification = value; } #endregion @@ -240,7 +240,7 @@ namespace osu.Game.Scoring public bool Delete(ScoreInfo item) { - return scoreModelManager.Delete(item); + return scoreImporter.Delete(item); } public void Delete([CanBeNull] Expression> filter = null, bool silent = false) @@ -253,7 +253,7 @@ namespace osu.Game.Scoring if (filter != null) items = items.Where(filter); - scoreModelManager.Delete(items.ToList(), silent); + scoreImporter.Delete(items.ToList(), silent); }); } @@ -262,27 +262,27 @@ namespace osu.Game.Scoring realm.Run(r => { var beatmapScores = r.Find(beatmap.ID).Scores.ToList(); - scoreModelManager.Delete(beatmapScores, silent); + scoreImporter.Delete(beatmapScores, silent); }); } - public void Delete(List items, bool silent = false) => scoreModelManager.Delete(items, silent); + public void Delete(List items, bool silent = false) => scoreImporter.Delete(items, silent); - public void Undelete(List items, bool silent = false) => scoreModelManager.Undelete(items, silent); + public void Undelete(List items, bool silent = false) => scoreImporter.Undelete(items, silent); - public void Undelete(ScoreInfo item) => scoreModelManager.Undelete(item); + public void Undelete(ScoreInfo item) => scoreImporter.Undelete(item); - public Task Import(params string[] paths) => scoreModelManager.Import(paths); + public Task Import(params string[] paths) => scoreImporter.Import(paths); - public Task Import(params ImportTask[] tasks) => scoreModelManager.Import(tasks); + public Task Import(params ImportTask[] tasks) => scoreImporter.Import(tasks); - public IEnumerable HandledExtensions => scoreModelManager.HandledExtensions; + public IEnumerable HandledExtensions => scoreImporter.HandledExtensions; - public Task>> Import(ProgressNotification notification, params ImportTask[] tasks) => scoreModelManager.Import(notification, tasks); + public Task>> Import(ProgressNotification notification, params ImportTask[] tasks) => scoreImporter.Import(notification, tasks); - public Live Import(ScoreInfo item, ArchiveReader archive = null, bool batchImport = false, CancellationToken cancellationToken = default) => scoreModelManager.Import(item, archive, batchImport, cancellationToken); + public Live Import(ScoreInfo item, ArchiveReader archive = null, bool batchImport = false, CancellationToken cancellationToken = default) => scoreImporter.Import(item, archive, batchImport, cancellationToken); - public bool IsAvailableLocally(ScoreInfo model) => scoreModelManager.IsAvailableLocally(model); + public bool IsAvailableLocally(ScoreInfo model) => scoreImporter.IsAvailableLocally(model); #endregion @@ -290,7 +290,7 @@ namespace osu.Game.Scoring public Action>> PostImport { - set => scoreModelManager.PostImport = value; + set => scoreImporter.PostImport = value; } #endregion diff --git a/osu.Game/Skinning/SkinModelManager.cs b/osu.Game/Skinning/SkinImporter.cs similarity index 98% rename from osu.Game/Skinning/SkinModelManager.cs rename to osu.Game/Skinning/SkinImporter.cs index ca90f41080..67626a45a8 100644 --- a/osu.Game/Skinning/SkinModelManager.cs +++ b/osu.Game/Skinning/SkinImporter.cs @@ -20,13 +20,13 @@ using Realms; namespace osu.Game.Skinning { - public class SkinModelManager : RealmArchiveModelManager + public class SkinImporter : RealmArchiveModelManager { private const string skin_info_file = "skininfo.json"; private readonly IStorageResourceProvider skinResources; - public SkinModelManager(Storage storage, RealmAccess realm, IStorageResourceProvider skinResources) + public SkinImporter(Storage storage, RealmAccess realm, IStorageResourceProvider skinResources) : base(storage, realm) { this.skinResources = skinResources; diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index f296386d34..f244657ea3 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -55,7 +55,7 @@ namespace osu.Game.Skinning Default = Skinning.DefaultSkin.CreateInfo().ToLiveUnmanaged() }; - private readonly SkinModelManager skinModelManager; + private readonly SkinImporter skinImporter; private readonly RealmAccess realm; private readonly IResourceStore userFiles; @@ -80,7 +80,7 @@ namespace osu.Game.Skinning userFiles = new StorageBackedResourceStore(storage.GetStorageForDirectory("files")); - skinModelManager = new SkinModelManager(storage, realm, this); + skinImporter = new SkinImporter(storage, realm, this); var defaultSkins = new[] { @@ -166,7 +166,7 @@ namespace osu.Game.Skinning Name = NamingUtils.GetNextBestName(existingSkinNames, $@"{s.Name} (modified)") }; - var result = skinModelManager.Import(skinInfo); + var result = skinImporter.Import(skinInfo); if (result != null) { @@ -186,7 +186,7 @@ namespace osu.Game.Skinning if (!skin.SkinInfo.IsManaged) throw new InvalidOperationException($"Attempting to save a skin which is not yet tracked. Call {nameof(EnsureMutableSkin)} first."); - skinModelManager.Save(skin); + skinImporter.Save(skin); } /// @@ -260,26 +260,26 @@ namespace osu.Game.Skinning public Action PostNotification { - set => skinModelManager.PostNotification = value; + set => skinImporter.PostNotification = value; } public Action>> PostImport { - set => skinModelManager.PostImport = value; + set => skinImporter.PostImport = value; } - public Task Import(params string[] paths) => skinModelManager.Import(paths); + public Task Import(params string[] paths) => skinImporter.Import(paths); - public Task Import(params ImportTask[] tasks) => skinModelManager.Import(tasks); + public Task Import(params ImportTask[] tasks) => skinImporter.Import(tasks); - public IEnumerable HandledExtensions => skinModelManager.HandledExtensions; + public IEnumerable HandledExtensions => skinImporter.HandledExtensions; - public Task>> Import(ProgressNotification notification, params ImportTask[] tasks) => skinModelManager.Import(notification, tasks); + public Task>> Import(ProgressNotification notification, params ImportTask[] tasks) => skinImporter.Import(notification, tasks); - public Task> Import(ImportTask task, bool batchImport = false, CancellationToken cancellationToken = default) => skinModelManager.Import(task, batchImport, cancellationToken); + public Task> Import(ImportTask task, bool batchImport = false, CancellationToken cancellationToken = default) => skinImporter.Import(task, batchImport, cancellationToken); public Task> Import(ArchiveReader archive, bool batchImport = false, CancellationToken cancellationToken = default) => - skinModelManager.Import(archive, batchImport, cancellationToken); + skinImporter.Import(archive, batchImport, cancellationToken); #endregion @@ -300,25 +300,25 @@ namespace osu.Game.Skinning if (items.Any(s => s.ID == currentUserSkin)) scheduler.Add(() => CurrentSkinInfo.Value = Skinning.DefaultSkin.CreateInfo().ToLiveUnmanaged()); - skinModelManager.Delete(items.ToList(), silent); + skinImporter.Delete(items.ToList(), silent); }); } - public bool Delete(SkinInfo item) => skinModelManager.Delete(item); + public bool Delete(SkinInfo item) => skinImporter.Delete(item); - public void Delete(List items, bool silent = false) => skinModelManager.Delete(items, silent); + public void Delete(List items, bool silent = false) => skinImporter.Delete(items, silent); - public void Undelete(List items, bool silent = false) => skinModelManager.Undelete(items, silent); + public void Undelete(List items, bool silent = false) => skinImporter.Undelete(items, silent); - public void Undelete(SkinInfo item) => skinModelManager.Undelete(item); + public void Undelete(SkinInfo item) => skinImporter.Undelete(item); - public bool IsAvailableLocally(SkinInfo model) => skinModelManager.IsAvailableLocally(model); + public bool IsAvailableLocally(SkinInfo model) => skinImporter.IsAvailableLocally(model); - public void ReplaceFile(SkinInfo model, RealmNamedFileUsage file, Stream contents) => skinModelManager.ReplaceFile(model, file, contents); + public void ReplaceFile(SkinInfo model, RealmNamedFileUsage file, Stream contents) => skinImporter.ReplaceFile(model, file, contents); - public void DeleteFile(SkinInfo model, RealmNamedFileUsage file) => skinModelManager.DeleteFile(model, file); + public void DeleteFile(SkinInfo model, RealmNamedFileUsage file) => skinImporter.DeleteFile(model, file); - public void AddFile(SkinInfo model, Stream contents, string filename) => skinModelManager.AddFile(model, contents, filename); + public void AddFile(SkinInfo model, Stream contents, string filename) => skinImporter.AddFile(model, contents, filename); #endregion } From 04e4c5ef8867a043ce722e8067fa27d6fc629d80 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Jun 2022 18:26:13 +0900 Subject: [PATCH 6/8] Move and adjust implementation regions to restore sanity --- osu.Game/Beatmaps/BeatmapManager.cs | 65 ++++++++++------------------- 1 file changed, 23 insertions(+), 42 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 63bd7dc710..a4ac161223 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -260,8 +260,6 @@ namespace osu.Game.Beatmaps return realm.Run(r => r.All().FirstOrDefault(query)?.ToLive(realm)); } - #region Delegation to BeatmapImporter (methods which previously existed locally). - /// /// Perform a lookup query on available s. /// @@ -283,38 +281,6 @@ namespace osu.Game.Beatmaps set => beatmapImporter.PostNotification = value; } - #endregion - - #region Implementation of IModelManager - - public bool IsAvailableLocally(BeatmapSetInfo model) - { - return beatmapImporter.IsAvailableLocally(model); - } - - public bool Delete(BeatmapSetInfo item) - { - return beatmapImporter.Delete(item); - } - - public void Delete(List items, bool silent = false) - { - beatmapImporter.Delete(items, silent); - } - - public void Delete(Expression>? filter = null, bool silent = false) - { - realm.Run(r => - { - var items = r.All().Where(s => !s.DeletePending && !s.Protected); - - if (filter != null) - items = items.Where(filter); - - beatmapImporter.Delete(items.ToList(), silent); - }); - } - /// /// Saves an file against a given . /// @@ -381,6 +347,19 @@ namespace osu.Game.Beatmaps }); } + public void Delete(Expression>? filter = null, bool silent = false) + { + realm.Run(r => + { + var items = r.All().Where(s => !s.DeletePending && !s.Protected); + + if (filter != null) + items = items.Where(filter); + + beatmapImporter.Delete(items.ToList(), silent); + }); + } + /// /// Delete videos from a list of beatmaps. /// This will post notifications tracking progress. @@ -431,15 +410,17 @@ namespace osu.Game.Beatmaps realm.Run(r => beatmapImporter.Undelete(r.All().Where(s => s.DeletePending).ToList())); } - public void Undelete(List items, bool silent = false) - { - beatmapImporter.Undelete(items, silent); - } + #region Implementation of IModelManager - public void Undelete(BeatmapSetInfo item) - { - beatmapImporter.Undelete(item); - } + public bool IsAvailableLocally(BeatmapSetInfo model) => beatmapImporter.IsAvailableLocally(model); + + public bool Delete(BeatmapSetInfo item) => beatmapImporter.Delete(item); + + public void Delete(List items, bool silent = false) => beatmapImporter.Delete(items, silent); + + public void Undelete(List items, bool silent = false) => beatmapImporter.Undelete(items, silent); + + public void Undelete(BeatmapSetInfo item) => beatmapImporter.Undelete(item); #endregion From 8a5755ca527965acbf913611ddb464992d204f88 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Jun 2022 18:27:16 +0900 Subject: [PATCH 7/8] Remove pointless override in test implementation --- osu.Game/Tests/Visual/EditorTestScene.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/osu.Game/Tests/Visual/EditorTestScene.cs b/osu.Game/Tests/Visual/EditorTestScene.cs index fbb5209513..d4a624f26a 100644 --- a/osu.Game/Tests/Visual/EditorTestScene.cs +++ b/osu.Game/Tests/Visual/EditorTestScene.cs @@ -145,11 +145,6 @@ namespace osu.Game.Tests.Visual { } - protected override BeatmapImporter CreateBeatmapImporter(Storage storage, RealmAccess realm, RulesetStore rulesets, BeatmapOnlineLookupQueue onlineLookupQueue) - { - return new BeatmapImporter(realm, storage, onlineLookupQueue); - } - protected override WorkingBeatmapCache CreateWorkingBeatmapCache(AudioManager audioManager, IResourceStore resources, IResourceStore storage, WorkingBeatmap defaultBeatmap, GameHost host) { return new TestWorkingBeatmapCache(this, audioManager, resources, storage, defaultBeatmap, host); From a635664a86de13d2f46d04daa2bbd8d27f0db238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 16 Jun 2022 12:01:53 +0200 Subject: [PATCH 8/8] Fix invalid method reference in comment `BeatmapModelManager.Save()` was moved to `BeatmapManager`, not to `BeatmapImporter`. --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index a4ac161223..ea804dea72 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -174,7 +174,7 @@ namespace osu.Game.Beatmaps private WorkingBeatmap addDifficultyToSet(BeatmapSetInfo targetBeatmapSet, IBeatmap newBeatmap, ISkin beatmapSkin) { // populate circular beatmap set info <-> beatmap info references manually. - // several places like `BeatmapImporter.Save()` or `GetWorkingBeatmap()` + // several places like `Save()` or `GetWorkingBeatmap()` // rely on them being freely traversable in both directions for correct operation. targetBeatmapSet.Beatmaps.Add(newBeatmap.BeatmapInfo); newBeatmap.BeatmapInfo.BeatmapSet = targetBeatmapSet;