From d94b27a8a22bae840d5a1eaac09468946ac8dec7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Nov 2021 18:34:04 +0900 Subject: [PATCH 01/27] Switch realm ruleset key bindings to use ruleset's `ShortName` as key --- osu.Game/Database/RealmContextFactory.cs | 30 ++++++++++++++++++- .../Bindings/DatabasedKeyBindingContainer.cs | 25 +++++++--------- osu.Game/Input/Bindings/RealmKeyBinding.cs | 6 ++-- osu.Game/Input/RealmKeyBindingStore.cs | 10 +++---- .../Settings/Sections/Input/KeyBindingRow.cs | 2 +- .../Sections/Input/KeyBindingsSubsection.cs | 4 +-- osu.Game/Overlays/Toolbar/ToolbarButton.cs | 2 +- 7 files changed, 53 insertions(+), 26 deletions(-) diff --git a/osu.Game/Database/RealmContextFactory.cs b/osu.Game/Database/RealmContextFactory.cs index 70ea24b581..2a2c94ee7d 100644 --- a/osu.Game/Database/RealmContextFactory.cs +++ b/osu.Game/Database/RealmContextFactory.cs @@ -42,8 +42,9 @@ namespace osu.Game.Database /// 8 2021-10-29 Rebind scroll adjust keys to not have control modifier. /// 9 2021-11-04 Converted BeatmapMetadata.Author from string to RealmUser. /// 10 2021-11-22 Use ShortName instead of RulesetID for ruleset settings. + /// 11 2021-11-22 Use ShortName instead of RulesetID for ruleset key bindings. /// - private const int schema_version = 10; + private const int schema_version = 11; /// /// Lock object which is held during sections, blocking context creation during blocking periods. @@ -260,6 +261,33 @@ namespace osu.Game.Database newItem.RulesetName = rulesetName; } + break; + + case 11: + + string keyBindingClassName = getMappedOrOriginalName(typeof(RealmKeyBinding)); + + var oldKeyBindings = migration.OldRealm.DynamicApi.All(keyBindingClassName); + var newKeyBindings = migration.NewRealm.All().ToList(); + + for (int i = 0; i < newKeyBindings.Count; i++) + { + dynamic? oldItem = oldKeyBindings.ElementAt(i); + var newItem = newKeyBindings.ElementAt(i); + + if (oldItem.RulesetID == null) + continue; + + long rulesetId = oldItem.RulesetID; + + string? rulesetName = rulesets?.GetRuleset((int)rulesetId)?.ShortName; + + if (string.IsNullOrEmpty(rulesetName)) + migration.NewRealm.Remove(newItem); + else + newItem.RulesetName = rulesetName; + } + break; } } diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs index 5dced23614..baa5b9ff9c 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs @@ -50,23 +50,20 @@ namespace osu.Game.Input.Bindings protected override void LoadComplete() { - if (ruleset == null || ruleset.ID.HasValue) - { - int? rulesetId = ruleset?.ID; + string rulesetName = ruleset?.ShortName; - realmKeyBindings = realmFactory.Context.All() - .Where(b => b.RulesetID == rulesetId && b.Variant == variant); + realmKeyBindings = realmFactory.Context.All() + .Where(b => b.RulesetName == rulesetName && b.Variant == variant); - realmSubscription = realmKeyBindings - .SubscribeForNotifications((sender, changes, error) => - { - // first subscription ignored as we are handling this in LoadComplete. - if (changes == null) - return; + realmSubscription = realmKeyBindings + .SubscribeForNotifications((sender, changes, error) => + { + // first subscription ignored as we are handling this in LoadComplete. + if (changes == null) + return; - ReloadMappings(); - }); - } + ReloadMappings(); + }); base.LoadComplete(); } diff --git a/osu.Game/Input/Bindings/RealmKeyBinding.cs b/osu.Game/Input/Bindings/RealmKeyBinding.cs index 334d2da427..6a408847fe 100644 --- a/osu.Game/Input/Bindings/RealmKeyBinding.cs +++ b/osu.Game/Input/Bindings/RealmKeyBinding.cs @@ -6,6 +6,8 @@ using osu.Framework.Input.Bindings; using osu.Game.Database; using Realms; +#nullable enable + namespace osu.Game.Input.Bindings { [MapTo(nameof(KeyBinding))] @@ -14,7 +16,7 @@ namespace osu.Game.Input.Bindings [PrimaryKey] public Guid ID { get; set; } = Guid.NewGuid(); - public int? RulesetID { get; set; } + public string? RulesetName { get; set; } public int? Variant { get; set; } @@ -34,6 +36,6 @@ namespace osu.Game.Input.Bindings public int ActionInt { get; set; } [MapTo(nameof(KeyCombination))] - public string KeyCombinationString { get; set; } + public string KeyCombinationString { get; set; } = string.Empty; } } diff --git a/osu.Game/Input/RealmKeyBindingStore.cs b/osu.Game/Input/RealmKeyBindingStore.cs index 046969579c..3bdb0a180d 100644 --- a/osu.Game/Input/RealmKeyBindingStore.cs +++ b/osu.Game/Input/RealmKeyBindingStore.cs @@ -36,7 +36,7 @@ namespace osu.Game.Input using (var context = realmFactory.CreateContext()) { - foreach (var action in context.All().Where(b => b.RulesetID == null && (GlobalAction)b.ActionInt == globalAction)) + foreach (var action in context.All().Where(b => string.IsNullOrEmpty(b.RulesetName) && (GlobalAction)b.ActionInt == globalAction)) { string str = keyCombinationProvider.GetReadableString(action.KeyCombination); @@ -69,20 +69,20 @@ namespace osu.Game.Input { var instance = ruleset.CreateInstance(); foreach (int variant in instance.AvailableVariants) - insertDefaults(realm, existingBindings, instance.GetDefaultKeyBindings(variant), ruleset.ID, variant); + insertDefaults(realm, existingBindings, instance.GetDefaultKeyBindings(variant), ruleset.ShortName, variant); } transaction.Commit(); } } - private void insertDefaults(Realm realm, List existingBindings, IEnumerable defaults, int? rulesetId = null, int? variant = null) + private void insertDefaults(Realm realm, List existingBindings, IEnumerable defaults, string? rulesetName = null, int? variant = null) { // compare counts in database vs defaults for each action type. foreach (var defaultsForAction in defaults.GroupBy(k => k.Action)) { // avoid performing redundant queries when the database is empty and needs to be re-filled. - int existingCount = existingBindings.Count(k => k.RulesetID == rulesetId && k.Variant == variant && k.ActionInt == (int)defaultsForAction.Key); + int existingCount = existingBindings.Count(k => k.RulesetName == rulesetName && k.Variant == variant && k.ActionInt == (int)defaultsForAction.Key); if (defaultsForAction.Count() <= existingCount) continue; @@ -92,7 +92,7 @@ namespace osu.Game.Input { KeyCombinationString = k.KeyCombination.ToString(), ActionInt = (int)k.Action, - RulesetID = rulesetId, + RulesetName = rulesetName, Variant = variant })); } diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs index 96a685a9c5..e0a1a82326 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs @@ -524,7 +524,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input public void UpdateKeyCombination(KeyCombination newCombination) { - if (KeyBinding.RulesetID != null && !RealmKeyBindingStore.CheckValidForGameplay(newCombination)) + if (KeyBinding.RulesetName != null && !RealmKeyBindingStore.CheckValidForGameplay(newCombination)) return; KeyBinding.KeyCombination = newCombination; diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs index be0830a7c2..115a7bdc79 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs @@ -32,12 +32,12 @@ namespace osu.Game.Overlays.Settings.Sections.Input [BackgroundDependencyLoader] private void load(RealmContextFactory realmFactory) { - int? rulesetId = Ruleset?.ID; + string rulesetName = Ruleset?.ShortName; List bindings; using (var realm = realmFactory.CreateContext()) - bindings = realm.All().Where(b => b.RulesetID == rulesetId && b.Variant == variant).Detach(); + bindings = realm.All().Where(b => b.RulesetName == rulesetName && b.Variant == variant).Detach(); foreach (var defaultGroup in Defaults.GroupBy(d => d.Action)) { diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index b2252a5575..75bebfa763 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -207,7 +207,7 @@ namespace osu.Game.Overlays.Toolbar { if (Hotkey == null) return; - var realmKeyBinding = realmFactory.Context.All().FirstOrDefault(rkb => rkb.RulesetID == null && rkb.ActionInt == (int)Hotkey.Value); + var realmKeyBinding = realmFactory.Context.All().FirstOrDefault(rkb => rkb.RulesetName == null && rkb.ActionInt == (int)Hotkey.Value); if (realmKeyBinding != null) { From 4149d458f010598063e9ac3e2ff9673b6759f2b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 23 Nov 2021 18:04:21 +0900 Subject: [PATCH 02/27] Move realm data migrations inside the `RealmContextFactory` --- osu.Game/Database/RealmContextFactory.cs | 51 ++++++++++++++++++++++++ osu.Game/OsuGameBase.cs | 31 -------------- osu.sln.DotSettings | 1 + 3 files changed, 52 insertions(+), 31 deletions(-) diff --git a/osu.Game/Database/RealmContextFactory.cs b/osu.Game/Database/RealmContextFactory.cs index 411cfc52ee..760b154397 100644 --- a/osu.Game/Database/RealmContextFactory.cs +++ b/osu.Game/Database/RealmContextFactory.cs @@ -96,6 +96,9 @@ namespace osu.Game.Database Filename += realm_extension; cleanupPendingDeletions(); + + // run after the above operation to ensure realm is already in a good (fully migrated) state. + migrateDataFromEF(); } private void cleanupPendingDeletions() @@ -163,6 +166,54 @@ namespace osu.Game.Database }; } + private void migrateDataFromEF() + { + if (efContextFactory == null) + return; + + using (var db = efContextFactory.GetForWrite()) + { + // migrate ruleset settings. can be removed 20220315. + var existingSettings = db.Context.DatabasedSetting; + + // previous entries in EF are removed post migration. + if (!existingSettings.Any()) + return; + + using (var realm = CreateContext()) + using (var transaction = realm.BeginWrite()) + { + // only migrate data if the realm database is empty. + if (!realm.All().Any()) + { + foreach (var dkb in existingSettings) + { + if (dkb.RulesetID == null) + continue; + + string? shortName = getRulesetShortNameFromLegacyID(dkb.RulesetID.Value); + + if (string.IsNullOrEmpty(shortName)) + continue; + + realm.Add(new RealmRulesetSetting + { + Key = dkb.Key, + Value = dkb.StringValue, + // important: this RulesetStore must be the EF one. + RulesetName = shortName, + Variant = dkb.Variant ?? 0, + }); + } + } + + db.Context.RemoveRange(existingSettings); + + transaction.Commit(); + } + } + } + private void onMigration(Migration migration, ulong lastSchemaVersion) { for (ulong i = lastSchemaVersion + 1; i <= schema_version; i++) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 1890fd7d24..8c35e65dfc 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -262,8 +262,6 @@ namespace osu.Game dependencies.Cache(scorePerformanceManager); AddInternal(scorePerformanceManager); - migrateDataToRealm(); - dependencies.Cache(rulesetConfigCache = new RulesetConfigCache(realmFactory, RulesetStore)); var powerStatus = CreateBatteryInfo(); @@ -439,35 +437,6 @@ namespace osu.Game private void migrateDataToRealm() { - using (var db = contextFactory.GetForWrite()) - using (var realm = realmFactory.CreateContext()) - using (var transaction = realm.BeginWrite()) - { - // migrate ruleset settings. can be removed 20220315. - var existingSettings = db.Context.DatabasedSetting; - - // only migrate data if the realm database is empty. - if (!realm.All().Any()) - { - foreach (var dkb in existingSettings) - { - if (dkb.RulesetID == null) continue; - - realm.Add(new RealmRulesetSetting - { - Key = dkb.Key, - Value = dkb.StringValue, - // important: this RulesetStore must be the EF one. - RulesetName = RulesetStore.GetRuleset(dkb.RulesetID.Value).ShortName, - Variant = dkb.Variant ?? 0, - }); - } - } - - db.Context.RemoveRange(existingSettings); - - transaction.Commit(); - } } private void onRulesetChanged(ValueChangedEvent r) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 3fac94b243..a96f64cdc3 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -311,6 +311,7 @@ AABB API BPM + EF FPS GC GL From 8d69ebd7db4bdd6b5a70797d633d7c6922416110 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 23 Nov 2021 20:17:07 +0900 Subject: [PATCH 03/27] Remove nullability of `Ruleset.CreateInstance` --- osu.Game/Models/RealmRuleset.cs | 22 ++++++++++++++++++++++ osu.Game/Rulesets/IRulesetInfo.cs | 17 +---------------- osu.Game/Rulesets/RulesetInfo.cs | 14 +++++++++++--- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/osu.Game/Models/RealmRuleset.cs b/osu.Game/Models/RealmRuleset.cs index 5d70324713..5c18a10527 100644 --- a/osu.Game/Models/RealmRuleset.cs +++ b/osu.Game/Models/RealmRuleset.cs @@ -60,5 +60,27 @@ namespace osu.Game.Models InstantiationInfo = InstantiationInfo, Available = Available }; + + public Ruleset CreateInstance() + { + if (!Available) + throw new RulesetLoadException(@"Ruleset not available"); + + var type = Type.GetType(InstantiationInfo); + + if (type == null) + throw new RulesetLoadException(@"Type lookup failure"); + + var ruleset = Activator.CreateInstance(type) as Ruleset; + + if (ruleset == null) + throw new RulesetLoadException(@"Instantiation failure"); + + // overwrite the pre-populated RulesetInfo with a potentially database attached copy. + // TODO: figure if we still want/need this after switching to realm. + // ruleset.RulesetInfo = this; + + return ruleset; + } } } diff --git a/osu.Game/Rulesets/IRulesetInfo.cs b/osu.Game/Rulesets/IRulesetInfo.cs index c3bc6c1995..4e529a73fb 100644 --- a/osu.Game/Rulesets/IRulesetInfo.cs +++ b/osu.Game/Rulesets/IRulesetInfo.cs @@ -1,7 +1,6 @@ // 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 osu.Game.Database; #nullable enable @@ -28,20 +27,6 @@ namespace osu.Game.Rulesets /// string InstantiationInfo { get; } - Ruleset? CreateInstance() - { - var type = Type.GetType(InstantiationInfo); - - if (type == null) - return null; - - var ruleset = Activator.CreateInstance(type) as Ruleset; - - // overwrite the pre-populated RulesetInfo with a potentially database attached copy. - // TODO: figure if we still want/need this after switching to realm. - // ruleset.RulesetInfo = this; - - return ruleset; - } + Ruleset CreateInstance(); } } diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index ccb614fe91..77be39650f 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -4,7 +4,6 @@ using System; using System.Diagnostics.CodeAnalysis; using Newtonsoft.Json; -using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Testing; namespace osu.Game.Rulesets @@ -26,9 +25,18 @@ namespace osu.Game.Rulesets // TODO: this should probably be moved to RulesetStore. public Ruleset CreateInstance() { - if (!Available) return null; + if (!Available) + throw new RulesetLoadException(@"Ruleset not available"); - var ruleset = (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo).AsNonNull()); + var type = Type.GetType(InstantiationInfo); + + if (type == null) + throw new RulesetLoadException(@"Type lookup failure"); + + var ruleset = Activator.CreateInstance(type) as Ruleset; + + if (ruleset == null) + throw new RulesetLoadException(@"Instantiation failure"); // overwrite the pre-populated RulesetInfo with a potentially database attached copy. ruleset.RulesetInfo = this; From 0eea026afb36d96e37bf2c7f91be38afc61bd494 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Nov 2021 12:22:13 +0900 Subject: [PATCH 04/27] Remove null checks on `CreateInstance()` calls --- osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs | 2 +- .../Overlays/Settings/Sections/Input/RulesetBindingsSection.cs | 2 +- osu.Game/Screens/Edit/Setup/SetupScreen.cs | 2 +- osu.Game/Screens/Edit/Verify/IssueList.cs | 2 +- osu.Game/Stores/BeatmapImporter.cs | 3 --- 5 files changed, 4 insertions(+), 7 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs b/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs index 1feaa88350..f4501f0633 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs @@ -117,7 +117,7 @@ namespace osu.Game.Beatmaps.Drawables Spacing = new Vector2(1, 0); Direction = FillDirection.Horizontal; - var icon = rulesets.GetRuleset(rulesetId)?.CreateInstance()?.CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.Regular.QuestionCircle }; + var icon = rulesets.GetRuleset(rulesetId)?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.Regular.QuestionCircle }; Add(icon.With(i => { i.Size = new Vector2(14); diff --git a/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs b/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs index 48cbe1b59e..b5d26d4887 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs @@ -11,7 +11,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input { public class RulesetBindingsSection : SettingsSection { - public override Drawable CreateIcon() => ruleset?.CreateInstance()?.CreateIcon() ?? new SpriteIcon + public override Drawable CreateIcon() => ruleset?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = OsuIcon.Hot }; diff --git a/osu.Game/Screens/Edit/Setup/SetupScreen.cs b/osu.Game/Screens/Edit/Setup/SetupScreen.cs index 04767f1786..8d726f7752 100644 --- a/osu.Game/Screens/Edit/Setup/SetupScreen.cs +++ b/osu.Game/Screens/Edit/Setup/SetupScreen.cs @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Edit.Setup new DesignSection(), }; - var rulesetSpecificSection = beatmap.BeatmapInfo.Ruleset?.CreateInstance()?.CreateEditorSetupSection(); + var rulesetSpecificSection = beatmap.BeatmapInfo.Ruleset?.CreateInstance().CreateEditorSetupSection(); if (rulesetSpecificSection != null) sectionsEnumerable.Add(rulesetSpecificSection); diff --git a/osu.Game/Screens/Edit/Verify/IssueList.cs b/osu.Game/Screens/Edit/Verify/IssueList.cs index 0b1f988447..fd238feeac 100644 --- a/osu.Game/Screens/Edit/Verify/IssueList.cs +++ b/osu.Game/Screens/Edit/Verify/IssueList.cs @@ -43,7 +43,7 @@ namespace osu.Game.Screens.Edit.Verify private void load(OverlayColourProvider colours) { generalVerifier = new BeatmapVerifier(); - rulesetVerifier = beatmap.BeatmapInfo.Ruleset?.CreateInstance()?.CreateBeatmapVerifier(); + rulesetVerifier = beatmap.BeatmapInfo.Ruleset?.CreateInstance().CreateBeatmapVerifier(); context = new BeatmapVerifierContext(beatmap, workingBeatmap.Value, verify.InterpretedDifficulty.Value); verify.InterpretedDifficulty.BindValueChanged(difficulty => context.InterpretedDifficulty = difficulty.NewValue); diff --git a/osu.Game/Stores/BeatmapImporter.cs b/osu.Game/Stores/BeatmapImporter.cs index 32f0cd3d7a..8ab6941885 100644 --- a/osu.Game/Stores/BeatmapImporter.cs +++ b/osu.Game/Stores/BeatmapImporter.cs @@ -282,9 +282,6 @@ namespace osu.Game.Stores { var rulesetInstance = ((IRulesetInfo)beatmap.Ruleset).CreateInstance(); - if (rulesetInstance == null) - return; - decoded.BeatmapInfo.Ruleset = rulesetInstance.RulesetInfo; // TODO: this should be done in a better place once we actually need to dynamically update it. From 6cd1bfd94fc01ad76d9fee3d4c08de5bfc31559a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Nov 2021 12:35:05 +0900 Subject: [PATCH 05/27] Remove outdated comment --- osu.Game/Database/RealmContextFactory.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Database/RealmContextFactory.cs b/osu.Game/Database/RealmContextFactory.cs index 760b154397..f48e11da8d 100644 --- a/osu.Game/Database/RealmContextFactory.cs +++ b/osu.Game/Database/RealmContextFactory.cs @@ -200,7 +200,6 @@ namespace osu.Game.Database { Key = dkb.Key, Value = dkb.StringValue, - // important: this RulesetStore must be the EF one. RulesetName = shortName, Variant = dkb.Variant ?? 0, }); From 63b09b356f4dad79198a211aa473862289db5679 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Nov 2021 12:37:09 +0900 Subject: [PATCH 06/27] Rewrite commments to read better --- osu.Game/Database/RealmContextFactory.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/RealmContextFactory.cs b/osu.Game/Database/RealmContextFactory.cs index f48e11da8d..6f979a0f91 100644 --- a/osu.Game/Database/RealmContextFactory.cs +++ b/osu.Game/Database/RealmContextFactory.cs @@ -95,9 +95,11 @@ namespace osu.Game.Database if (!Filename.EndsWith(realm_extension, StringComparison.Ordinal)) Filename += realm_extension; + // This method triggers the first `CreateContext` call, which will implicitly run realm migrations and bring the schema up-to-date. cleanupPendingDeletions(); - // run after the above operation to ensure realm is already in a good (fully migrated) state. + // Data migration is handled separately from schema migrations. + // This is required as the user may be initialising realm for the first time ever, which would result in no schema migrations running. migrateDataFromEF(); } From 729f6819381faafad4d2611f6d0ca0ad4491dccd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Nov 2021 12:49:57 +0900 Subject: [PATCH 07/27] Update cases where equality can be used instead of primary key equality --- osu.Game.Tests/Scores/IO/ImportScoreTest.cs | 2 +- .../Visual/Navigation/TestScenePresentBeatmap.cs | 4 ++-- .../Visual/Navigation/TestScenePresentScore.cs | 8 ++++---- osu.Game/Beatmaps/BeatmapDifficultyCache.cs | 4 ++-- osu.Game/Beatmaps/BeatmapModelManager.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmapCache.cs | 4 ++-- osu.Game/OsuGameBase.cs | 2 +- osu.Game/Overlays/Music/PlaylistOverlay.cs | 2 +- osu.Game/Overlays/MusicController.cs | 10 +++++----- .../Header/Components/ProfileRulesetSelector.cs | 2 +- osu.Game/Overlays/Settings/Sections/SkinSection.cs | 2 +- osu.Game/Screens/Select/BeatmapCarousel.cs | 4 ++-- 12 files changed, 23 insertions(+), 23 deletions(-) diff --git a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs index be7803734e..0dee0f89ea 100644 --- a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs +++ b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs @@ -142,7 +142,7 @@ namespace osu.Game.Tests.Scores.IO var scoreManager = osu.Dependencies.Get(); beatmapManager.Delete(beatmapManager.QueryBeatmapSet(s => s.Beatmaps.Any(b => b.ID == imported.BeatmapInfo.ID))); - Assert.That(scoreManager.Query(s => s.ID == imported.ID).DeletePending, Is.EqualTo(true)); + Assert.That(scoreManager.Query(s => s.Equals(imported)).DeletePending, Is.EqualTo(true)); var secondImport = await LoadScoreIntoOsu(osu, imported); Assert.That(secondImport, Is.Null); diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs b/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs index d1ee984682..22570b8567 100644 --- a/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs +++ b/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs @@ -141,7 +141,7 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is Screens.Select.SongSelect); AddUntilStep("correct beatmap displayed", () => Game.Beatmap.Value.BeatmapSetInfo.MatchesOnlineID(getImport())); - AddAssert("correct ruleset selected", () => Game.Ruleset.Value.ID == getImport().Beatmaps.First().Ruleset.ID); + AddAssert("correct ruleset selected", () => Game.Ruleset.Value.Equals(getImport().Beatmaps.First().Ruleset)); } private void presentSecondDifficultyAndConfirm(Func getImport, int importedID) @@ -151,7 +151,7 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is Screens.Select.SongSelect); AddUntilStep("correct beatmap displayed", () => Game.Beatmap.Value.BeatmapInfo.OnlineID == importedID * 2048); - AddAssert("correct ruleset selected", () => Game.Ruleset.Value.ID == getImport().Beatmaps.First().Ruleset.ID); + AddAssert("correct ruleset selected", () => Game.Ruleset.Value.Equals(getImport().Beatmaps.First().Ruleset)); } } } diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs b/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs index 72f160c9a9..3b11a29962 100644 --- a/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs +++ b/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs @@ -155,15 +155,15 @@ namespace osu.Game.Tests.Visual.Navigation case ScorePresentType.Results: AddUntilStep("wait for results", () => lastWaitedScreen != Game.ScreenStack.CurrentScreen && Game.ScreenStack.CurrentScreen is ResultsScreen); AddStep("store last waited screen", () => lastWaitedScreen = Game.ScreenStack.CurrentScreen); - AddUntilStep("correct score displayed", () => ((ResultsScreen)Game.ScreenStack.CurrentScreen).Score.ID == getImport().ID); - AddAssert("correct ruleset selected", () => Game.Ruleset.Value.ID == getImport().Ruleset.ID); + AddUntilStep("correct score displayed", () => ((ResultsScreen)Game.ScreenStack.CurrentScreen).Score.Equals(getImport())); + AddAssert("correct ruleset selected", () => Game.Ruleset.Value.Equals(getImport().Ruleset)); break; case ScorePresentType.Gameplay: AddUntilStep("wait for player loader", () => lastWaitedScreen != Game.ScreenStack.CurrentScreen && Game.ScreenStack.CurrentScreen is ReplayPlayerLoader); AddStep("store last waited screen", () => lastWaitedScreen = Game.ScreenStack.CurrentScreen); - AddUntilStep("correct score displayed", () => ((ReplayPlayerLoader)Game.ScreenStack.CurrentScreen).Score.ID == getImport().ID); - AddAssert("correct ruleset selected", () => Game.Ruleset.Value.ID == getImport().Ruleset.ID); + AddUntilStep("correct score displayed", () => ((ReplayPlayerLoader)Game.ScreenStack.CurrentScreen).Score.Equals(getImport())); + AddAssert("correct ruleset selected", () => Game.Ruleset.Value.Equals(getImport().Ruleset)); break; } } diff --git a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs index f444b597c9..4d44b49218 100644 --- a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs +++ b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs @@ -340,8 +340,8 @@ namespace osu.Game.Beatmaps } public bool Equals(DifficultyCacheLookup other) - => BeatmapInfo.ID == other.BeatmapInfo.ID - && Ruleset.ID == other.Ruleset.ID + => BeatmapInfo.Equals(other.BeatmapInfo) + && Ruleset.Equals(other.Ruleset) && OrderedMods.SequenceEqual(other.OrderedMods); public override int GetHashCode() diff --git a/osu.Game/Beatmaps/BeatmapModelManager.cs b/osu.Game/Beatmaps/BeatmapModelManager.cs index 8f55232031..46d6fc89bd 100644 --- a/osu.Game/Beatmaps/BeatmapModelManager.cs +++ b/osu.Game/Beatmaps/BeatmapModelManager.cs @@ -208,7 +208,7 @@ namespace osu.Game.Beatmaps using (ContextFactory.GetForWrite()) { - beatmapInfo = setInfo.Beatmaps.Single(b => b.ID == beatmapInfo.ID); + beatmapInfo = setInfo.Beatmaps.Single(b => b.Equals(beatmapInfo)); var metadata = beatmapInfo.Metadata ?? setInfo.Metadata; diff --git a/osu.Game/Beatmaps/WorkingBeatmapCache.cs b/osu.Game/Beatmaps/WorkingBeatmapCache.cs index 0af28902a0..548f4a3d79 100644 --- a/osu.Game/Beatmaps/WorkingBeatmapCache.cs +++ b/osu.Game/Beatmaps/WorkingBeatmapCache.cs @@ -65,7 +65,7 @@ namespace osu.Game.Beatmaps { lock (workingCache) { - var working = workingCache.FirstOrDefault(w => w.BeatmapInfo?.ID == info.ID); + var working = workingCache.FirstOrDefault(w => info.Equals(w.BeatmapInfo)); if (working != null) { @@ -89,7 +89,7 @@ namespace osu.Game.Beatmaps lock (workingCache) { - var working = workingCache.FirstOrDefault(w => w.BeatmapInfo?.ID == beatmapInfo.ID); + var working = workingCache.FirstOrDefault(w => beatmapInfo.Equals(w.BeatmapInfo)); if (working != null) return working; diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 1890fd7d24..1f2dbf1054 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -214,7 +214,7 @@ namespace osu.Game SkinManager.ItemRemoved += item => Schedule(() => { // check the removed skin is not the current user choice. if it is, switch back to default. - if (item.ID == SkinManager.CurrentSkinInfo.Value.ID) + if (item.Equals(SkinManager.CurrentSkinInfo.Value)) SkinManager.CurrentSkinInfo.Value = SkinInfo.Default; }); diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index b8d04eab4e..0f4806d9cf 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -114,7 +114,7 @@ namespace osu.Game.Overlays.Music private void itemSelected(BeatmapSetInfo set) { - if (set.ID == (beatmap.Value?.BeatmapSetInfo?.ID ?? -1)) + if (set.Equals((beatmap.Value?.BeatmapSetInfo))) { beatmap.Value?.Track.Seek(0); return; diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 829ff5be25..76358fca3f 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -111,7 +111,7 @@ namespace osu.Game.Overlays beatmapSets.Add(set); }); - private void beatmapRemoved(BeatmapSetInfo set) => Schedule(() => beatmapSets.RemoveAll(s => s.ID == set.ID)); + private void beatmapRemoved(BeatmapSetInfo set) => Schedule(() => beatmapSets.RemoveAll(s => s.Equals(set))); private ScheduledDelegate seekDelegate; @@ -228,7 +228,7 @@ namespace osu.Game.Overlays queuedDirection = TrackChangeDirection.Prev; - var playable = BeatmapSets.TakeWhile(i => i.ID != current.BeatmapSetInfo.ID).LastOrDefault() ?? BeatmapSets.LastOrDefault(); + var playable = BeatmapSets.TakeWhile(i => !i.Equals(current.BeatmapSetInfo)).LastOrDefault() ?? BeatmapSets.LastOrDefault(); if (playable != null) { @@ -259,7 +259,7 @@ namespace osu.Game.Overlays queuedDirection = TrackChangeDirection.Next; - var playable = BeatmapSets.SkipWhile(i => i.ID != current.BeatmapSetInfo.ID).ElementAtOrDefault(1) ?? BeatmapSets.FirstOrDefault(); + var playable = BeatmapSets.SkipWhile(i => !i.Equals(current.BeatmapSetInfo)).ElementAtOrDefault(1) ?? BeatmapSets.FirstOrDefault(); if (playable != null) { @@ -309,8 +309,8 @@ namespace osu.Game.Overlays else { // figure out the best direction based on order in playlist. - int last = BeatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo?.ID).Count(); - int next = newWorking == null ? -1 : BeatmapSets.TakeWhile(b => b.ID != newWorking.BeatmapSetInfo?.ID).Count(); + int last = BeatmapSets.TakeWhile(b => !b.Equals(current.BeatmapSetInfo)).Count(); + int next = newWorking == null ? -1 : BeatmapSets.TakeWhile(b => !b.Equals(newWorking.BeatmapSetInfo)).Count(); direction = last > next ? TrackChangeDirection.Prev : TrackChangeDirection.Next; } diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs index eaa9703834..4d2290266c 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Profile.Header.Components public void SetDefaultRuleset(RulesetInfo ruleset) { foreach (var tabItem in TabContainer) - ((ProfileRulesetTabItem)tabItem).IsDefault = ((ProfileRulesetTabItem)tabItem).Value.ID == ruleset.ID; + ((ProfileRulesetTabItem)tabItem).IsDefault = ((ProfileRulesetTabItem)tabItem).Value.Equals(ruleset); } protected override TabItem CreateTabItem(RulesetInfo value) => new ProfileRulesetTabItem(value); diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 0714b28b47..e7a7abed59 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -132,7 +132,7 @@ namespace osu.Game.Overlays.Settings.Sections skinDropdown.Items = newDropdownItems; } - private void itemRemoved(SkinInfo item) => Schedule(() => skinDropdown.Items = skinDropdown.Items.Where(i => i.ID != item.ID).ToArray()); + private void itemRemoved(SkinInfo item) => Schedule(() => skinDropdown.Items = skinDropdown.Items.Where(i => !i.Equals(item)).ToArray()); private void sortUserSkins(List skinsList) { diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 0fc7a99c96..b0d0821ee9 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -186,7 +186,7 @@ namespace osu.Game.Screens.Select public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() => { - var existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.ID == beatmapSet.ID); + var existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.Equals(beatmapSet)); if (existingSet == null) return; @@ -198,7 +198,7 @@ namespace osu.Game.Screens.Select public void UpdateBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() => { int? previouslySelectedID = null; - CarouselBeatmapSet existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.ID == beatmapSet.ID); + CarouselBeatmapSet existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.Equals(beatmapSet)); // If the selected beatmap is about to be removed, store its ID so it can be re-selected if required if (existingSet?.State?.Value == CarouselItemState.Selected) From b1f3e9804577a8e829483c4115a288ba75419637 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Nov 2021 16:16:01 +0900 Subject: [PATCH 08/27] Fix incorrect usage of `ID` in `TestSceneMultiplayerResults` --- .../Visual/Multiplayer/TestSceneMultiplayerResults.cs | 2 +- .../Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs index c0b21c4421..80f807e7d3 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs @@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.Multiplayer PlaylistItem playlistItem = new PlaylistItem { - BeatmapID = beatmapInfo.ID, + BeatmapID = beatmapInfo.OnlineID ?? -1, }; Stack.Push(screen = new MultiplayerResultsScreen(score, 1, playlistItem)); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs index d391c39c89..da1fa226e1 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.Multiplayer PlaylistItem playlistItem = new PlaylistItem { - BeatmapID = beatmapInfo.ID, + BeatmapID = beatmapInfo.OnlineID ?? -1, }; SortedDictionary teamScores = new SortedDictionary From ee22c24370f57b066d73d37e2d04a1c970a19ab4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 23 Nov 2021 12:52:17 +0900 Subject: [PATCH 09/27] Update `RulesetConfigCache` to cache via `ShortName` instead of `ID` --- osu.Game/Rulesets/RulesetConfigCache.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/RulesetConfigCache.cs b/osu.Game/Rulesets/RulesetConfigCache.cs index aeac052673..5a082300b4 100644 --- a/osu.Game/Rulesets/RulesetConfigCache.cs +++ b/osu.Game/Rulesets/RulesetConfigCache.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets private readonly RealmContextFactory realmFactory; private readonly RulesetStore rulesets; - private readonly Dictionary configCache = new Dictionary(); + private readonly Dictionary configCache = new Dictionary(); public RulesetConfigCache(RealmContextFactory realmFactory, RulesetStore rulesets) { @@ -36,10 +36,10 @@ namespace osu.Game.Rulesets // let's keep things simple for now and just retrieve all the required configs at startup.. foreach (var ruleset in rulesets.AvailableRulesets) { - if (ruleset.ID == null) + if (string.IsNullOrEmpty(ruleset.ShortName)) continue; - configCache[ruleset.ID.Value] = ruleset.CreateInstance().CreateConfig(settingsStore); + configCache[ruleset.ShortName] = ruleset.CreateInstance().CreateConfig(settingsStore); } } @@ -51,10 +51,10 @@ namespace osu.Game.Rulesets /// If doesn't have a valid . public IRulesetConfigManager GetConfigFor(Ruleset ruleset) { - if (ruleset.RulesetInfo.ID == null) + if (string.IsNullOrEmpty(ruleset.ShortName)) return null; - if (!configCache.TryGetValue(ruleset.RulesetInfo.ID.Value, out var config)) + if (!configCache.TryGetValue(ruleset.RulesetInfo.ShortName, out var config)) // any ruleset request which wasn't initialised on startup should not be stored to realm. // this should only be used by tests. return ruleset.CreateConfig(null); From 49c2cb91254fe4a3ff193826a97482b144cc1a31 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Nov 2021 13:25:52 +0900 Subject: [PATCH 10/27] Initialise `BeatmapSet.Beatmaps` list to line up with realm expectations --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- osu.Game/Beatmaps/BeatmapModelManager.cs | 1 - osu.Game/Beatmaps/BeatmapSetInfo.cs | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index c2a2e93caf..4378da2dd3 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -86,7 +86,7 @@ namespace osu.Game.Beatmaps var set = new BeatmapSetInfo { Metadata = metadata, - Beatmaps = new List + Beatmaps = { new BeatmapInfo { diff --git a/osu.Game/Beatmaps/BeatmapModelManager.cs b/osu.Game/Beatmaps/BeatmapModelManager.cs index 8f55232031..132f15809a 100644 --- a/osu.Game/Beatmaps/BeatmapModelManager.cs +++ b/osu.Game/Beatmaps/BeatmapModelManager.cs @@ -370,7 +370,6 @@ namespace osu.Game.Beatmaps return new BeatmapSetInfo { OnlineID = beatmap.BeatmapInfo.BeatmapSet?.OnlineID, - Beatmaps = new List(), Metadata = beatmap.Metadata, DateAdded = DateTimeOffset.UtcNow }; diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 35468ce831..818a6dd48f 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -30,7 +30,7 @@ namespace osu.Game.Beatmaps public BeatmapMetadata Metadata { get; set; } - public List Beatmaps { get; set; } + public List Beatmaps { get; } = new List(); public BeatmapSetOnlineStatus Status { get; set; } = BeatmapSetOnlineStatus.None; From 8c60f37508cf52dbedab69a65a8d22c900695b0e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Nov 2021 13:25:26 +0900 Subject: [PATCH 11/27] Fix cases of dynamically assigning `Beatmap`s to `BeatmapSetInfo` using list assignment --- .../Beatmaps/IO/ImportBeatmapTest.cs | 2 +- ...eneOnlinePlayBeatmapAvailabilityTracker.cs | 9 ++-- .../Menus/TestSceneMusicActionHandling.cs | 2 +- .../TestSceneMultiplayerMatchSongSelect.cs | 36 +++++++++------ .../TestScenePlaylistsSongSelect.cs | 34 +++++++------- .../Navigation/TestScenePresentBeatmap.cs | 3 +- .../Navigation/TestScenePresentScore.cs | 3 +- .../SongSelect/TestSceneBeatmapCarousel.cs | 46 ++++++++++--------- .../TestSceneBeatmapRecommendations.cs | 20 ++++---- .../SongSelect/TestScenePlaySongSelect.cs | 33 ++++++------- osu.Game/Beatmaps/BeatmapModelManager.cs | 2 +- osu.Game/Tests/Beatmaps/TestBeatmap.cs | 12 +++-- osu.Game/Tests/Visual/OsuTestScene.cs | 21 ++++++--- 13 files changed, 123 insertions(+), 100 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 836cbfa6c5..a404a54ee4 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -584,7 +584,7 @@ namespace osu.Game.Tests.Beatmaps.IO { OnlineID = 1, Metadata = metadata, - Beatmaps = new List + Beatmaps = { new BeatmapInfo { diff --git a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs index b66da028f1..748de6c9a8 100644 --- a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs +++ b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs @@ -2,7 +2,7 @@ // 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.Threading; using System.Threading.Tasks; @@ -143,8 +143,11 @@ namespace osu.Game.Tests.Online var beatmap = decoder.Decode(reader); info = beatmap.BeatmapInfo; - info.BeatmapSet.Beatmaps = new List { info }; - info.BeatmapSet.Metadata = info.Metadata; + info.Metadata = info.Metadata; + + Debug.Assert(info.BeatmapSet != null); + + info.BeatmapSet.Beatmaps.Add(info); info.MD5Hash = stream.ComputeMD5Hash(); info.Hash = stream.ComputeSHA2Hash(); } diff --git a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs index 6dda8df6f0..f429b5b2a8 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs @@ -36,7 +36,7 @@ namespace osu.Game.Tests.Visual.Menus // ensure we have at least two beatmaps available to identify the direction the music controller navigated to. AddRepeatStep("import beatmap", () => Game.BeatmapManager.Import(new BeatmapSetInfo { - Beatmaps = new List + Beatmaps = { new BeatmapInfo { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs index aef1fb31d6..f308886bf4 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs @@ -47,6 +47,13 @@ namespace osu.Game.Tests.Visual.Multiplayer beatmaps = new List(); + var beatmapSetInfo = new BeatmapSetInfo + { + OnlineID = 10, + Hash = Guid.NewGuid().ToString().ComputeMD5Hash(), + DateAdded = DateTimeOffset.UtcNow + }; + for (int i = 0; i < 8; ++i) { int beatmapId = 10 * 10 + i; @@ -54,29 +61,28 @@ namespace osu.Game.Tests.Visual.Multiplayer int length = RNG.Next(30000, 200000); double bpm = RNG.NextSingle(80, 200); - beatmaps.Add(new BeatmapInfo + var metadata = new BeatmapMetadata + { + Artist = "Some Artist", + Title = "Some Beatmap", + AuthorString = "Some Author" + }; + + var beatmap = new BeatmapInfo { Ruleset = rulesets.GetRuleset(i % 4), OnlineID = beatmapId, Length = length, BPM = bpm, + Metadata = metadata, BaseDifficulty = new BeatmapDifficulty() - }); + }; + + beatmaps.Add(beatmap); + beatmapSetInfo.Beatmaps.Add(beatmap); } - manager.Import(new BeatmapSetInfo - { - OnlineID = 10, - Hash = Guid.NewGuid().ToString().ComputeMD5Hash(), - Metadata = new BeatmapMetadata - { - Artist = "Some Artist", - Title = "Some Beatmap", - AuthorString = "Some Author" - }, - Beatmaps = beatmaps, - DateAdded = DateTimeOffset.UtcNow - }).Wait(); + manager.Import(beatmapSetInfo).Wait(); } public override void SetUpSteps() diff --git a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs index 05f9a94cf7..04e47e17e5 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; @@ -42,7 +41,20 @@ namespace osu.Game.Tests.Visual.Multiplayer Dependencies.Cache(rulesets = new RulesetStore(ContextFactory)); Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default)); - var beatmaps = new List(); + var metadata = new BeatmapMetadata + { + // Create random metadata, then we can check if sorting works based on these + Artist = "Some Artist " + RNG.Next(0, 9), + Title = "Some Song (set id 10)", + AuthorString = "Some Guy " + RNG.Next(0, 9), + }; + + var beatmapSet = new BeatmapSetInfo + { + OnlineID = 10, + Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(), + DateAdded = DateTimeOffset.UtcNow, + }; for (int i = 0; i < 6; i++) { @@ -51,12 +63,13 @@ namespace osu.Game.Tests.Visual.Multiplayer int length = RNG.Next(30000, 200000); double bpm = RNG.NextSingle(80, 200); - beatmaps.Add(new BeatmapInfo + beatmapSet.Beatmaps.Add(new BeatmapInfo { Ruleset = new OsuRuleset().RulesetInfo, OnlineID = beatmapId, DifficultyName = $"{beatmapId} (length {TimeSpan.FromMilliseconds(length):m\\:ss}, bpm {bpm:0.#})", Length = length, + Metadata = metadata, BPM = bpm, BaseDifficulty = new BeatmapDifficulty { @@ -65,20 +78,7 @@ namespace osu.Game.Tests.Visual.Multiplayer }); } - manager.Import(new BeatmapSetInfo - { - OnlineID = 10, - Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(), - Metadata = new BeatmapMetadata - { - // Create random metadata, then we can check if sorting works based on these - Artist = "Some Artist " + RNG.Next(0, 9), - Title = $"Some Song (set id 10), max bpm {beatmaps.Max(b => b.BPM):0.#})", - AuthorString = "Some Guy " + RNG.Next(0, 9), - }, - Beatmaps = beatmaps, - DateAdded = DateTimeOffset.UtcNow, - }).Wait(); + manager.Import(beatmapSet).Wait(); } public override void SetUpSteps() diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs b/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs index d1ee984682..2d1512209e 100644 --- a/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs +++ b/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Screens; @@ -110,7 +109,7 @@ namespace osu.Game.Tests.Visual.Navigation Hash = Guid.NewGuid().ToString(), OnlineID = i, Metadata = metadata, - Beatmaps = new List + Beatmaps = { new BeatmapInfo { diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs b/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs index 72f160c9a9..1d4459a852 100644 --- a/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs +++ b/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Screens; @@ -41,7 +40,7 @@ namespace osu.Game.Tests.Visual.Navigation Hash = Guid.NewGuid().ToString(), OnlineID = 1, Metadata = metadata, - Beatmaps = new List + Beatmaps = { new BeatmapInfo { diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 5c40a3dd94..512e34975e 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -836,23 +836,27 @@ namespace osu.Game.Tests.Visual.SongSelect private BeatmapSetInfo createTestBeatmapSet(int id, bool randomDifficultyCount = false) { - return new BeatmapSetInfo + var metadata = new BeatmapMetadata + { + // Create random metadata, then we can check if sorting works based on these + Artist = $"peppy{id.ToString().PadLeft(6, '0')}", + Title = $"test set #{id}!", + AuthorString = string.Concat(Enumerable.Repeat((char)('z' - Math.Min(25, id - 1)), 5)) + }; + + var beatmapSet = new BeatmapSetInfo { - ID = id, OnlineID = id, Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(), - Metadata = new BeatmapMetadata - { - // Create random metadata, then we can check if sorting works based on these - Artist = $"peppy{id.ToString().PadLeft(6, '0')}", - Title = $"test set #{id}!", - AuthorString = string.Concat(Enumerable.Repeat((char)('z' - Math.Min(25, id - 1)), 5)) - }, - Beatmaps = getBeatmaps(randomDifficultyCount ? RNG.Next(1, 20) : 3).ToList() }; + + foreach (var b in getBeatmaps(randomDifficultyCount ? RNG.Next(1, 20) : 3, metadata)) + beatmapSet.Beatmaps.Add(b); + + return beatmapSet; } - private IEnumerable getBeatmaps(int count) + private IEnumerable getBeatmaps(int count, BeatmapMetadata metadata) { int id = 0; @@ -872,6 +876,7 @@ namespace osu.Game.Tests.Visual.SongSelect DifficultyName = version, StarRating = diff, Ruleset = new OsuRuleset().RulesetInfo, + Metadata = metadata, BaseDifficulty = new BeatmapDifficulty { OverallDifficulty = diff, @@ -882,19 +887,18 @@ namespace osu.Game.Tests.Visual.SongSelect private BeatmapSetInfo createTestBeatmapSetWithManyDifficulties(int id) { + var metadata = new BeatmapMetadata + { + // Create random metadata, then we can check if sorting works based on these + Artist = $"peppy{id.ToString().PadLeft(6, '0')}", + Title = $"test set #{id}!", + AuthorString = string.Concat(Enumerable.Repeat((char)('z' - Math.Min(25, id - 1)), 5)) + }; + var toReturn = new BeatmapSetInfo { - ID = id, OnlineID = id, Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(), - Metadata = new BeatmapMetadata - { - // Create random metadata, then we can check if sorting works based on these - Artist = $"peppy{id.ToString().PadLeft(6, '0')}", - Title = $"test set #{id}!", - AuthorString = string.Concat(Enumerable.Repeat((char)('z' - Math.Min(25, id - 1)), 5)) - }, - Beatmaps = new List(), }; for (int b = 1; b < 101; b++) @@ -902,10 +906,10 @@ namespace osu.Game.Tests.Visual.SongSelect toReturn.Beatmaps.Add(new BeatmapInfo { OnlineID = b * 10, - Path = $"extra{b}.osu", DifficultyName = $"Extra {b}", Ruleset = rulesets.GetRuleset((b - 1) % 4), StarRating = 2, + Metadata = metadata, BaseDifficulty = new BeatmapDifficulty { OverallDifficulty = 3.5f, diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs index c9ec53cfd5..73144b584f 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs @@ -182,18 +182,18 @@ namespace osu.Game.Tests.Visual.SongSelect { Hash = Guid.NewGuid().ToString(), OnlineID = importID, - Metadata = metadata, - Beatmaps = difficultyRulesets.Select((ruleset, difficultyIndex) => new BeatmapInfo - { - OnlineID = importID * 1024 + difficultyIndex, - Metadata = metadata, - BaseDifficulty = new BeatmapDifficulty(), - Ruleset = ruleset, - StarRating = difficultyIndex + 1, - DifficultyName = $"SR{difficultyIndex + 1}" - }).ToList() }; + beatmapSet.Beatmaps.AddRange(difficultyRulesets.Select((ruleset, difficultyIndex) => new BeatmapInfo + { + OnlineID = importID * 1024 + difficultyIndex, + Metadata = metadata, + BaseDifficulty = new BeatmapDifficulty(), + Ruleset = ruleset, + StarRating = difficultyIndex + 1, + DifficultyName = $"SR{difficultyIndex + 1}" + })); + return Game.BeatmapManager.Import(beatmapSet).Result.Value; } diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index f09dc38378..025c7f0dfd 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -907,7 +907,20 @@ namespace osu.Game.Tests.Visual.SongSelect int setId = getImportId(); - var beatmaps = new List(); + var beatmapSet = new BeatmapSetInfo + { + OnlineID = setId, + Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(), + DateAdded = DateTimeOffset.UtcNow, + }; + + var metadata = new BeatmapMetadata + { + // Create random metadata, then we can check if sorting works based on these + Artist = "Some Artist " + RNG.Next(0, 9), + Title = $"Some Song (set id {setId})", + AuthorString = "Some Guy " + RNG.Next(0, 9), + }; for (int i = 0; i < countPerRuleset; i++) { @@ -916,12 +929,13 @@ namespace osu.Game.Tests.Visual.SongSelect int length = RNG.Next(30000, 200000); double bpm = RNG.NextSingle(80, 200); - beatmaps.Add(new BeatmapInfo + beatmapSet.Beatmaps.Add(new BeatmapInfo { Ruleset = getRuleset(), OnlineID = beatmapId, DifficultyName = $"{beatmapId} (length {TimeSpan.FromMilliseconds(length):m\\:ss}, bpm {bpm:0.#})", Length = length, + Metadata = metadata, BPM = bpm, BaseDifficulty = new BeatmapDifficulty { @@ -930,20 +944,7 @@ namespace osu.Game.Tests.Visual.SongSelect }); } - return new BeatmapSetInfo - { - OnlineID = setId, - Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(), - Metadata = new BeatmapMetadata - { - // Create random metadata, then we can check if sorting works based on these - Artist = "Some Artist " + RNG.Next(0, 9), - Title = $"Some Song (set id {setId}, max bpm {beatmaps.Max(b => b.BPM):0.#})", - AuthorString = "Some Guy " + RNG.Next(0, 9), - }, - Beatmaps = beatmaps, - DateAdded = DateTimeOffset.UtcNow, - }; + return beatmapSet; } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Beatmaps/BeatmapModelManager.cs b/osu.Game/Beatmaps/BeatmapModelManager.cs index 132f15809a..15eac962cc 100644 --- a/osu.Game/Beatmaps/BeatmapModelManager.cs +++ b/osu.Game/Beatmaps/BeatmapModelManager.cs @@ -82,7 +82,7 @@ namespace osu.Game.Beatmaps protected override async Task Populate(BeatmapSetInfo beatmapSet, ArchiveReader archive, CancellationToken cancellationToken = default) { if (archive != null) - beatmapSet.Beatmaps = createBeatmapDifficulties(beatmapSet.Files); + beatmapSet.Beatmaps.AddRange(createBeatmapDifficulties(beatmapSet.Files)); foreach (BeatmapInfo b in beatmapSet.Beatmaps) { diff --git a/osu.Game/Tests/Beatmaps/TestBeatmap.cs b/osu.Game/Tests/Beatmaps/TestBeatmap.cs index 32a9b0b9d1..729253e25c 100644 --- a/osu.Game/Tests/Beatmaps/TestBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestBeatmap.cs @@ -2,7 +2,7 @@ // 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.Text; using System.Threading; @@ -33,12 +33,16 @@ namespace osu.Game.Tests.Beatmaps BeatmapInfo.Ruleset = ruleset; BeatmapInfo.RulesetID = ruleset.ID ?? 0; - BeatmapInfo.BeatmapSet.Metadata = BeatmapInfo.Metadata; - BeatmapInfo.BeatmapSet.Beatmaps = new List { BeatmapInfo }; - BeatmapInfo.BeatmapSet.OnlineID = Interlocked.Increment(ref onlineSetID); + BeatmapInfo.Metadata = BeatmapInfo.Metadata; BeatmapInfo.Length = 75000; BeatmapInfo.OnlineInfo = new APIBeatmap(); BeatmapInfo.OnlineID = Interlocked.Increment(ref onlineBeatmapID); + + Debug.Assert(BeatmapInfo.BeatmapSet != null); + + BeatmapInfo.BeatmapSet.Metadata = BeatmapInfo.Metadata; + BeatmapInfo.BeatmapSet.Beatmaps.Add(BeatmapInfo); + BeatmapInfo.BeatmapSet.OnlineID = Interlocked.Increment(ref onlineSetID); } protected virtual Beatmap CreateBeatmap() => createTestBeatmap(); diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index eedf266bbe..d774514dda 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Threading.Tasks; @@ -220,6 +221,8 @@ namespace osu.Game.Tests.Visual { var beatmap = CreateBeatmap(ruleset ?? Ruleset.Value).BeatmapInfo; + Debug.Assert(beatmap.BeatmapSet != null); + return new APIBeatmapSet { OnlineID = ((IBeatmapSetInfo)beatmap.BeatmapSet).OnlineID, @@ -230,13 +233,17 @@ namespace osu.Game.Tests.Visual Card = "https://assets.ppy.sh/beatmaps/163112/covers/card.jpg", List = "https://assets.ppy.sh/beatmaps/163112/covers/list.jpg" }, - Title = beatmap.BeatmapSet.Metadata.Title, - TitleUnicode = beatmap.BeatmapSet.Metadata.TitleUnicode, - Artist = beatmap.BeatmapSet.Metadata.Artist, - ArtistUnicode = beatmap.BeatmapSet.Metadata.ArtistUnicode, - Author = beatmap.BeatmapSet.Metadata.Author, - Source = beatmap.BeatmapSet.Metadata.Source, - Tags = beatmap.BeatmapSet.Metadata.Tags, + Title = beatmap.Metadata.Title, + TitleUnicode = beatmap.Metadata.TitleUnicode, + Artist = beatmap.Metadata.Artist, + ArtistUnicode = beatmap.Metadata.ArtistUnicode, + Author = new APIUser + { + Username = beatmap.Metadata.Author.Username, + Id = beatmap.Metadata.Author.OnlineID + }, + Source = beatmap.Metadata.Source, + Tags = beatmap.Metadata.Tags, Beatmaps = new[] { new APIBeatmap From a3fdab34d5b39840ca60b79cf80bebfe4bfbb780 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Nov 2021 13:34:52 +0900 Subject: [PATCH 12/27] Avoid json serialisation of aggregate helper properties Also avoids `throw`ing when there are no beatmaps available. Until now this wasn't an issue due to the `Beatmaps` list being null instead of empty. --- osu.Game/Beatmaps/BeatmapSetInfo.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 818a6dd48f..998bc6f16c 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using JetBrains.Annotations; +using Newtonsoft.Json; using osu.Framework.Testing; using osu.Game.Database; using osu.Game.Extensions; @@ -30,6 +31,7 @@ namespace osu.Game.Beatmaps public BeatmapMetadata Metadata { get; set; } + [NotNull] public List Beatmaps { get; } = new List(); public BeatmapSetOnlineStatus Status { get; set; } = BeatmapSetOnlineStatus.None; @@ -40,17 +42,20 @@ namespace osu.Game.Beatmaps /// /// The maximum star difficulty of all beatmaps in this set. /// - public double MaxStarDifficulty => Beatmaps?.Max(b => b.StarRating) ?? 0; + [JsonIgnore] + public double MaxStarDifficulty => Beatmaps.Count == 0 ? 0 : Beatmaps.Max(b => b.StarRating); /// /// The maximum playable length in milliseconds of all beatmaps in this set. /// - public double MaxLength => Beatmaps?.Max(b => b.Length) ?? 0; + [JsonIgnore] + public double MaxLength => Beatmaps.Count == 0 ? 0 : Beatmaps.Max(b => b.Length); /// /// The maximum BPM of all beatmaps in this set. /// - public double MaxBPM => Beatmaps?.Max(b => b.BPM) ?? 0; + [JsonIgnore] + public double MaxBPM => Beatmaps.Count == 0 ? 0 : Beatmaps.Max(b => b.BPM); [NotMapped] public bool DeletePending { get; set; } From 5a0a95f9d470f9d7d1c3d30ef7d937195a2d0056 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 24 Nov 2021 13:48:59 +0900 Subject: [PATCH 13/27] Trim whitespace --- osu.Game/Database/RealmContextFactory.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Database/RealmContextFactory.cs b/osu.Game/Database/RealmContextFactory.cs index 0a21f67422..99eb038b2d 100644 --- a/osu.Game/Database/RealmContextFactory.cs +++ b/osu.Game/Database/RealmContextFactory.cs @@ -269,7 +269,6 @@ namespace osu.Game.Database break; case 11: - string keyBindingClassName = getMappedOrOriginalName(typeof(RealmKeyBinding)); var oldKeyBindings = migration.OldRealm.DynamicApi.All(keyBindingClassName); From 0aedbbe165a67c1436e53b6a0b144bcd3d215d70 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Nov 2021 14:04:55 +0900 Subject: [PATCH 14/27] Fix incorrect fallback logic causing test failure --- osu.Game/Rulesets/RulesetConfigCache.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Rulesets/RulesetConfigCache.cs b/osu.Game/Rulesets/RulesetConfigCache.cs index 5a082300b4..262340b4ee 100644 --- a/osu.Game/Rulesets/RulesetConfigCache.cs +++ b/osu.Game/Rulesets/RulesetConfigCache.cs @@ -51,9 +51,6 @@ namespace osu.Game.Rulesets /// If doesn't have a valid . public IRulesetConfigManager GetConfigFor(Ruleset ruleset) { - if (string.IsNullOrEmpty(ruleset.ShortName)) - return null; - if (!configCache.TryGetValue(ruleset.RulesetInfo.ShortName, out var config)) // any ruleset request which wasn't initialised on startup should not be stored to realm. // this should only be used by tests. From ec89dfa04314eab13e78f12ab104cd407d4a62ad Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Nov 2021 14:09:25 +0900 Subject: [PATCH 15/27] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index d80fb858e9..d893792285 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 2f26e45ba8..f9c8d9743d 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 4554469c19..47f8fbb43a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -60,7 +60,7 @@ - + @@ -83,7 +83,7 @@ - + From a7853fc9cc96fa50b92b12b5c25dee18f9ccc11a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Nov 2021 14:26:23 +0900 Subject: [PATCH 16/27] Fix cases of known-non-null --- osu.Game/Beatmaps/WorkingBeatmapCache.cs | 2 -- osu.Game/Overlays/Music/PlaylistOverlay.cs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmapCache.cs b/osu.Game/Beatmaps/WorkingBeatmapCache.cs index 0af28902a0..857a1ca06f 100644 --- a/osu.Game/Beatmaps/WorkingBeatmapCache.cs +++ b/osu.Game/Beatmaps/WorkingBeatmapCache.cs @@ -55,8 +55,6 @@ namespace osu.Game.Beatmaps public void Invalidate(BeatmapSetInfo info) { - if (info.Beatmaps == null) return; - foreach (var b in info.Beatmaps) Invalidate(b); } diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index b8d04eab4e..41c4942c55 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -77,7 +77,7 @@ namespace osu.Game.Overlays.Music filter.Search.OnCommit += (sender, newText) => { - BeatmapInfo toSelect = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault(); + BeatmapInfo toSelect = list.FirstVisibleSet?.Beatmaps.FirstOrDefault(); if (toSelect != null) { From 44c34ca7b2473d65e24dffde56ca2270724267dd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Nov 2021 14:32:18 +0900 Subject: [PATCH 17/27] Revert changes causing `BeatmapSet.Metadata` to be expectedly null in some tests --- ...stSceneOnlinePlayBeatmapAvailabilityTracker.cs | 1 + .../TestSceneMultiplayerMatchSongSelect.cs | 15 ++++++++------- .../Multiplayer/TestScenePlaylistsSongSelect.cs | 1 + .../Visual/SongSelect/TestSceneBeatmapCarousel.cs | 3 +++ .../SongSelect/TestSceneBeatmapRecommendations.cs | 1 + .../Visual/SongSelect/TestScenePlaySongSelect.cs | 15 ++++++++------- 6 files changed, 22 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs index 748de6c9a8..0fba0eb7a9 100644 --- a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs +++ b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs @@ -148,6 +148,7 @@ namespace osu.Game.Tests.Online Debug.Assert(info.BeatmapSet != null); info.BeatmapSet.Beatmaps.Add(info); + info.BeatmapSet.Metadata = info.Metadata; info.MD5Hash = stream.ComputeMD5Hash(); info.Hash = stream.ComputeSHA2Hash(); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs index f308886bf4..6b67a979e5 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs @@ -47,10 +47,18 @@ namespace osu.Game.Tests.Visual.Multiplayer beatmaps = new List(); + var metadata = new BeatmapMetadata + { + Artist = "Some Artist", + Title = "Some Beatmap", + AuthorString = "Some Author" + }; + var beatmapSetInfo = new BeatmapSetInfo { OnlineID = 10, Hash = Guid.NewGuid().ToString().ComputeMD5Hash(), + Metadata = metadata, DateAdded = DateTimeOffset.UtcNow }; @@ -61,13 +69,6 @@ namespace osu.Game.Tests.Visual.Multiplayer int length = RNG.Next(30000, 200000); double bpm = RNG.NextSingle(80, 200); - var metadata = new BeatmapMetadata - { - Artist = "Some Artist", - Title = "Some Beatmap", - AuthorString = "Some Author" - }; - var beatmap = new BeatmapInfo { Ruleset = rulesets.GetRuleset(i % 4), diff --git a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs index 04e47e17e5..3e24b7a1d0 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs @@ -53,6 +53,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { OnlineID = 10, Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(), + Metadata = metadata, DateAdded = DateTimeOffset.UtcNow, }; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 512e34975e..1808f98c23 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -846,8 +846,10 @@ namespace osu.Game.Tests.Visual.SongSelect var beatmapSet = new BeatmapSetInfo { + ID = id, OnlineID = id, Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(), + Metadata = metadata, }; foreach (var b in getBeatmaps(randomDifficultyCount ? RNG.Next(1, 20) : 3, metadata)) @@ -899,6 +901,7 @@ namespace osu.Game.Tests.Visual.SongSelect { OnlineID = id, Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(), + Metadata = metadata, }; for (int b = 1; b < 101; b++) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs index 73144b584f..7d855a88e2 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs @@ -182,6 +182,7 @@ namespace osu.Game.Tests.Visual.SongSelect { Hash = Guid.NewGuid().ToString(), OnlineID = importID, + Metadata = metadata, }; beatmapSet.Beatmaps.AddRange(difficultyRulesets.Select((ruleset, difficultyIndex) => new BeatmapInfo diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 025c7f0dfd..c89b7e858b 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -907,13 +907,6 @@ namespace osu.Game.Tests.Visual.SongSelect int setId = getImportId(); - var beatmapSet = new BeatmapSetInfo - { - OnlineID = setId, - Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(), - DateAdded = DateTimeOffset.UtcNow, - }; - var metadata = new BeatmapMetadata { // Create random metadata, then we can check if sorting works based on these @@ -922,6 +915,14 @@ namespace osu.Game.Tests.Visual.SongSelect AuthorString = "Some Guy " + RNG.Next(0, 9), }; + var beatmapSet = new BeatmapSetInfo + { + OnlineID = setId, + Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(), + DateAdded = DateTimeOffset.UtcNow, + Metadata = metadata + }; + for (int i = 0; i < countPerRuleset; i++) { int beatmapId = setId * 1000 + i; From 3946a39b65c7734285bca71dbd54f00801b9f32f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Nov 2021 15:01:45 +0900 Subject: [PATCH 18/27] Make `BeatmapSet.Metadata` non-null --- osu.Game.Tests/Models/DisplayStringTest.cs | 12 ++++++------ osu.Game/Beatmaps/BeatmapSetInfo.cs | 2 +- osu.Game/Beatmaps/IBeatmapSetInfo.cs | 2 +- osu.Game/Extensions/ModelExtensions.cs | 2 +- osu.Game/Models/RealmBeatmapSet.cs | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Models/DisplayStringTest.cs b/osu.Game.Tests/Models/DisplayStringTest.cs index 95af21eb5f..2d0bda88e4 100644 --- a/osu.Game.Tests/Models/DisplayStringTest.cs +++ b/osu.Game.Tests/Models/DisplayStringTest.cs @@ -29,9 +29,9 @@ namespace osu.Game.Tests.Models { var mock = new Mock(); - mock.Setup(m => m.Metadata!.Artist).Returns("artist"); - mock.Setup(m => m.Metadata!.Title).Returns("title"); - mock.Setup(m => m.Metadata!.Author.Username).Returns("author"); + mock.Setup(m => m.Metadata.Artist).Returns("artist"); + mock.Setup(m => m.Metadata.Title).Returns("title"); + mock.Setup(m => m.Metadata.Author.Username).Returns("author"); Assert.That(mock.Object.GetDisplayString(), Is.EqualTo("artist - title (author)")); } @@ -41,9 +41,9 @@ namespace osu.Game.Tests.Models { var mock = new Mock(); - mock.Setup(m => m.Metadata!.Artist).Returns("artist"); - mock.Setup(m => m.Metadata!.Title).Returns("title"); - mock.Setup(m => m.Metadata!.Author.Username).Returns(string.Empty); + mock.Setup(m => m.Metadata.Artist).Returns("artist"); + mock.Setup(m => m.Metadata.Title).Returns("title"); + mock.Setup(m => m.Metadata.Author.Username).Returns(string.Empty); Assert.That(mock.Object.GetDisplayString(), Is.EqualTo("artist - title")); } diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 35468ce831..47960201d8 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -89,7 +89,7 @@ namespace osu.Game.Beatmaps #region Implementation of IBeatmapSetInfo - IBeatmapMetadataInfo IBeatmapSetInfo.Metadata => Metadata; + IBeatmapMetadataInfo IBeatmapSetInfo.Metadata => Metadata ?? Beatmaps.FirstOrDefault()?.Metadata ?? new BeatmapMetadata(); IEnumerable IBeatmapSetInfo.Beatmaps => Beatmaps; IEnumerable IBeatmapSetInfo.Files => Files; diff --git a/osu.Game/Beatmaps/IBeatmapSetInfo.cs b/osu.Game/Beatmaps/IBeatmapSetInfo.cs index 67f38397d4..aa114c8472 100644 --- a/osu.Game/Beatmaps/IBeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapSetInfo.cs @@ -22,7 +22,7 @@ namespace osu.Game.Beatmaps /// /// The best-effort metadata representing this set. In the case metadata differs between contained beatmaps, one is arbitrarily chosen. /// - IBeatmapMetadataInfo? Metadata { get; } + IBeatmapMetadataInfo Metadata { get; } /// /// All beatmaps contained in this set. diff --git a/osu.Game/Extensions/ModelExtensions.cs b/osu.Game/Extensions/ModelExtensions.cs index aaf87385c8..9f00d21383 100644 --- a/osu.Game/Extensions/ModelExtensions.cs +++ b/osu.Game/Extensions/ModelExtensions.cs @@ -42,7 +42,7 @@ namespace osu.Game.Extensions switch (model) { case IBeatmapSetInfo beatmapSetInfo: - result = beatmapSetInfo.Metadata?.GetDisplayTitle(); + result = beatmapSetInfo.Metadata.GetDisplayTitle(); break; case IBeatmapInfo beatmapInfo: diff --git a/osu.Game/Models/RealmBeatmapSet.cs b/osu.Game/Models/RealmBeatmapSet.cs index da75978977..ff39bcf13e 100644 --- a/osu.Game/Models/RealmBeatmapSet.cs +++ b/osu.Game/Models/RealmBeatmapSet.cs @@ -26,7 +26,7 @@ namespace osu.Game.Models public DateTimeOffset DateAdded { get; set; } - public IBeatmapMetadataInfo? Metadata => Beatmaps.FirstOrDefault()?.Metadata; + public IBeatmapMetadataInfo Metadata => Beatmaps.FirstOrDefault()?.Metadata ?? new RealmBeatmapMetadata(); public IList Beatmaps { get; } = null!; @@ -62,7 +62,7 @@ namespace osu.Game.Models return ID == other.ID; } - public override string ToString() => Metadata?.GetDisplayString() ?? base.ToString(); + public override string ToString() => Metadata.GetDisplayString(); public bool Equals(IBeatmapSetInfo? other) => other is RealmBeatmapSet b && Equals(b); From cb093e1e017202836d14ad233ddb13b959eec15a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Nov 2021 15:08:04 +0900 Subject: [PATCH 19/27] Remove reundant self-sets of metadata --- .../Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs | 1 - osu.Game/Tests/Beatmaps/TestBeatmap.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs index 0fba0eb7a9..a4c69075be 100644 --- a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs +++ b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs @@ -143,7 +143,6 @@ namespace osu.Game.Tests.Online var beatmap = decoder.Decode(reader); info = beatmap.BeatmapInfo; - info.Metadata = info.Metadata; Debug.Assert(info.BeatmapSet != null); diff --git a/osu.Game/Tests/Beatmaps/TestBeatmap.cs b/osu.Game/Tests/Beatmaps/TestBeatmap.cs index 729253e25c..99944bcf6d 100644 --- a/osu.Game/Tests/Beatmaps/TestBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestBeatmap.cs @@ -33,7 +33,6 @@ namespace osu.Game.Tests.Beatmaps BeatmapInfo.Ruleset = ruleset; BeatmapInfo.RulesetID = ruleset.ID ?? 0; - BeatmapInfo.Metadata = BeatmapInfo.Metadata; BeatmapInfo.Length = 75000; BeatmapInfo.OnlineInfo = new APIBeatmap(); BeatmapInfo.OnlineID = Interlocked.Increment(ref onlineBeatmapID); From db2d8b6d8bf875deddccecd0d583982060c30718 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Nov 2021 16:08:42 +0900 Subject: [PATCH 20/27] Fix ruleset instance creation null checks --- .../Components/TestSceneTournamentModDisplay.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs index 3c22bdca03..3cd13df0d3 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs @@ -42,7 +42,12 @@ namespace osu.Game.Tournament.Tests.Components private void success(APIBeatmap beatmap) { - var mods = rulesets.GetRuleset(Ladder.Ruleset.Value.ID ?? 0).CreateInstance().AllMods; + var ruleset = rulesets.GetRuleset(Ladder.Ruleset.Value.OnlineID); + + if (ruleset == null) + return; + + var mods = ruleset.CreateInstance().AllMods; foreach (var mod in mods) { From eff1293b5b3bd867fe165e9b87ac21c43e5282b5 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 24 Nov 2021 15:26:40 +0900 Subject: [PATCH 21/27] Revert "Run nunit in blame mode" This reverts commit 215c179b929a29e0c083422f29a6031f9450ffe3. --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2139572601..68f8ef51ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,7 @@ jobs: run: dotnet build -c Debug -warnaserror osu.Desktop.slnf - name: Test - run: dotnet test $pwd/*.Tests/bin/Debug/*/*.Tests.dll --blame-crash --blame-hang --blame-hang-timeout 5m --logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx" + run: dotnet test $pwd/*.Tests/bin/Debug/*/*.Tests.dll --logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx" shell: pwsh # Attempt to upload results even if test fails. @@ -48,7 +48,7 @@ jobs: if: ${{ always() }} with: name: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}} - path: ${{github.workspace}}/TestResults/**/* + path: ${{github.workspace}}/TestResults/TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx build-only-android: name: Build only (Android) From e57c343531f5fe5bc8a5a34d64f7907fcf0eee6f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Nov 2021 15:23:05 +0900 Subject: [PATCH 22/27] Add helper setter to EF `RulesetInfo.OnlineID` to allow updating usages --- osu.Game/Rulesets/RulesetInfo.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index 77be39650f..4a146c05bf 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.ComponentModel.DataAnnotations.Schema; using System.Diagnostics.CodeAnalysis; using Newtonsoft.Json; using osu.Framework.Testing; @@ -65,7 +66,12 @@ namespace osu.Game.Rulesets #region Implementation of IHasOnlineID - public int OnlineID => ID ?? -1; + [NotMapped] + public int OnlineID + { + get => ID ?? -1; + set => ID = value >= 0 ? value : (int?)null; + } #endregion } From f283770f34354422a1e4974907ac833cc8b8b268 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Nov 2021 14:26:24 +0900 Subject: [PATCH 23/27] Update mock `RulesetInfo` usage to set `OnlineID` instead of `ID` --- .../TestSceneBeatmapDifficultyCache.cs | 16 +++---- .../NonVisual/Filtering/FilterMatchingTest.cs | 12 +++--- .../Testing/TestSceneRulesetDependencies.cs | 2 +- .../TestScenePlayerScoreSubmission.cs | 2 +- .../Visual/Gameplay/TestSceneSpectatorHost.cs | 2 +- .../Navigation/TestSceneScreenNavigation.cs | 4 +- .../Online/TestSceneBeatmapSetOverlay.cs | 2 +- .../Visual/Online/TestSceneDirectPanel.cs | 2 +- .../Online/TestSceneNowPlayingCommand.cs | 2 +- .../TestSceneBeatmapRecommendations.cs | 2 +- .../SongSelect/TestScenePlaySongSelect.cs | 42 +++++++++---------- .../TestSceneModSelectOverlay.cs | 4 +- .../API/Requests/Responses/APIBeatmap.cs | 2 +- .../API/Requests/Responses/APIScoreInfo.cs | 2 +- osu.Game/Rulesets/Ruleset.cs | 2 +- 15 files changed, 49 insertions(+), 49 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs index f84dbca0be..2a60a7b96d 100644 --- a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs +++ b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs @@ -100,8 +100,8 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestKeyEqualsWithDifferentModInstances() { - var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModHardRock(), new OsuModHidden() }); - var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModHardRock(), new OsuModHidden() }); + var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModHardRock(), new OsuModHidden() }); + var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModHardRock(), new OsuModHidden() }); Assert.That(key1, Is.EqualTo(key2)); Assert.That(key1.GetHashCode(), Is.EqualTo(key2.GetHashCode())); @@ -110,8 +110,8 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestKeyEqualsWithDifferentModOrder() { - var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModHardRock(), new OsuModHidden() }); - var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModHidden(), new OsuModHardRock() }); + var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModHardRock(), new OsuModHidden() }); + var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModHidden(), new OsuModHardRock() }); Assert.That(key1, Is.EqualTo(key2)); Assert.That(key1.GetHashCode(), Is.EqualTo(key2.GetHashCode())); @@ -120,8 +120,8 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestKeyDoesntEqualWithDifferentModSettings() { - var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.1 } } }); - var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.9 } } }); + var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.1 } } }); + var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.9 } } }); Assert.That(key1, Is.Not.EqualTo(key2)); Assert.That(key1.GetHashCode(), Is.Not.EqualTo(key2.GetHashCode())); @@ -130,8 +130,8 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestKeyEqualWithMatchingModSettings() { - var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.25 } } }); - var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.25 } } }); + var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.25 } } }); + var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.25 } } }); Assert.That(key1, Is.EqualTo(key2)); Assert.That(key1.GetHashCode(), Is.EqualTo(key2.GetHashCode())); diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterMatchingTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterMatchingTest.cs index ee1feeca8d..e49b0d3a67 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterMatchingTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterMatchingTest.cs @@ -16,7 +16,7 @@ namespace osu.Game.Tests.NonVisual.Filtering { private BeatmapInfo getExampleBeatmap() => new BeatmapInfo { - Ruleset = new RulesetInfo { ID = 5 }, + Ruleset = new RulesetInfo { OnlineID = 5 }, StarRating = 4.0d, BaseDifficulty = new BeatmapDifficulty { @@ -57,7 +57,7 @@ namespace osu.Game.Tests.NonVisual.Filtering var exampleBeatmapInfo = getExampleBeatmap(); var criteria = new FilterCriteria { - Ruleset = new RulesetInfo { ID = 6 } + Ruleset = new RulesetInfo { OnlineID = 6 } }; var carouselItem = new CarouselBeatmap(exampleBeatmapInfo); carouselItem.Filter(criteria); @@ -70,7 +70,7 @@ namespace osu.Game.Tests.NonVisual.Filtering var exampleBeatmapInfo = getExampleBeatmap(); var criteria = new FilterCriteria { - Ruleset = new RulesetInfo { ID = 6 }, + Ruleset = new RulesetInfo { OnlineID = 6 }, AllowConvertedBeatmaps = true }; var carouselItem = new CarouselBeatmap(exampleBeatmapInfo); @@ -86,7 +86,7 @@ namespace osu.Game.Tests.NonVisual.Filtering var exampleBeatmapInfo = getExampleBeatmap(); var criteria = new FilterCriteria { - Ruleset = new RulesetInfo { ID = 6 }, + Ruleset = new RulesetInfo { OnlineID = 6 }, AllowConvertedBeatmaps = true, ApproachRate = new FilterCriteria.OptionalRange { @@ -107,7 +107,7 @@ namespace osu.Game.Tests.NonVisual.Filtering var exampleBeatmapInfo = getExampleBeatmap(); var criteria = new FilterCriteria { - Ruleset = new RulesetInfo { ID = 6 }, + Ruleset = new RulesetInfo { OnlineID = 6 }, AllowConvertedBeatmaps = true, BPM = new FilterCriteria.OptionalRange { @@ -132,7 +132,7 @@ namespace osu.Game.Tests.NonVisual.Filtering var exampleBeatmapInfo = getExampleBeatmap(); var criteria = new FilterCriteria { - Ruleset = new RulesetInfo { ID = 6 }, + Ruleset = new RulesetInfo { OnlineID = 6 }, AllowConvertedBeatmaps = true, SearchText = terms }; diff --git a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs index bb9b705c7e..330d3dd2ae 100644 --- a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs +++ b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs @@ -70,7 +70,7 @@ namespace osu.Game.Tests.Testing { // temporary ID to let RulesetConfigCache pass our // config manager to the ruleset dependencies. - RulesetInfo.ID = -1; + RulesetInfo.OnlineID = -1; } public override IResourceStore CreateResourceStore() => new NamespacedResourceStore(TestResources.GetStore(), @"Resources"); diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs index cb5058779c..324a132120 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs @@ -233,7 +233,7 @@ namespace osu.Game.Tests.Visual.Gameplay { prepareTokenResponse(true); - createPlayerTest(false, createRuleset: () => new OsuRuleset { RulesetInfo = { ID = rulesetId } }); + createPlayerTest(false, createRuleset: () => new OsuRuleset { RulesetInfo = { OnlineID = rulesetId ?? -1 } }); AddUntilStep("wait for token request", () => Player.TokenCreationRequested); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs index 2a82c65c7c..409cec4cf6 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestClientSendsCorrectRuleset() { AddUntilStep("spectator client sending frames", () => spectatorClient.PlayingUserStates.ContainsKey(dummy_user_id)); - AddAssert("spectator client sent correct ruleset", () => spectatorClient.PlayingUserStates[dummy_user_id].RulesetID == Ruleset.Value.ID); + AddAssert("spectator client sent correct ruleset", () => spectatorClient.PlayingUserStates[dummy_user_id].RulesetID == Ruleset.Value.OnlineID); } public override void TearDownSteps() diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index ef71c54e03..497c68cf2e 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -257,7 +257,7 @@ namespace osu.Game.Tests.Visual.Navigation InputManager.ReleaseKey(Key.ControlLeft); }); - AddAssert("Ruleset changed to osu!taiko", () => Game.Toolbar.ChildrenOfType().Single().Current.Value.ID == 1); + AddAssert("Ruleset changed to osu!taiko", () => Game.Toolbar.ChildrenOfType().Single().Current.Value.OnlineID == 1); AddAssert("Mods overlay still visible", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible); } @@ -278,7 +278,7 @@ namespace osu.Game.Tests.Visual.Navigation InputManager.ReleaseKey(Key.ControlLeft); }); - AddAssert("Ruleset changed to osu!taiko", () => Game.Toolbar.ChildrenOfType().Single().Current.Value.ID == 1); + AddAssert("Ruleset changed to osu!taiko", () => Game.Toolbar.ChildrenOfType().Single().Current.Value.OnlineID == 1); AddAssert("Options overlay still visible", () => songSelect.BeatmapOptionsOverlay.State.Value == Visibility.Visible); } diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 86863c0b5d..3314e291e8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -200,7 +200,7 @@ namespace osu.Game.Tests.Visual.Online { OnlineID = i * 10, DifficultyName = $"Test #{i}", - RulesetID = Ruleset.Value.ID ?? -1, + RulesetID = Ruleset.Value.OnlineID, StarRating = 2 + i * 0.1, OverallDifficulty = 3.5f, FailTimes = new APIFailTimes diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs index 01dde97d38..510b9e8483 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs @@ -94,7 +94,7 @@ namespace osu.Game.Tests.Visual.Online { new APIBeatmap { - RulesetID = Ruleset.Value.ID ?? 0, + RulesetID = Ruleset.Value.OnlineID, DifficultyName = "Test", StarRating = 6.42, } diff --git a/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs b/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs index 7a5ee84eb4..b689b85490 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs @@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("Set beatmap", () => Beatmap.Value = new DummyWorkingBeatmap(Audio, null) { - BeatmapInfo = { OnlineID = hasOnlineId ? 1234 : (int?)null } + BeatmapInfo = { OnlineID = hasOnlineId ? 1234 : -1 } }); AddStep("Run command", () => Add(new NowPlayingCommand())); diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs index c9ec53cfd5..af3312f50b 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.SongSelect switch (req) { case GetUserRequest userRequest: - userRequest.TriggerSuccess(getUser(userRequest.Ruleset.ID)); + userRequest.TriggerSuccess(getUser(userRequest.Ruleset.OnlineID)); return true; } diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index f09dc38378..42ec966b2e 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -258,7 +258,7 @@ namespace osu.Game.Tests.Visual.SongSelect { AddStep("import multi-ruleset map", () => { - var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray(); + var usableRulesets = rulesets.AvailableRulesets.Where(r => r.OnlineID != 2).ToArray(); manager.Import(createTestBeatmapSet(usableRulesets)).Wait(); }); } @@ -354,7 +354,7 @@ namespace osu.Game.Tests.Visual.SongSelect target = manager.GetAllUsableBeatmapSets() .Last(b => b.Beatmaps.Any(bi => bi.RulesetID == 0)).Beatmaps.Last(); - Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == 0); + Ruleset.Value = rulesets.AvailableRulesets.First(r => r.OnlineID == 0); Beatmap.Value = manager.GetWorkingBeatmap(target); }); @@ -385,12 +385,12 @@ namespace osu.Game.Tests.Visual.SongSelect .Last(b => b.Beatmaps.Any(bi => bi.RulesetID == 0)).Beatmaps.Last(); Beatmap.Value = manager.GetWorkingBeatmap(target); - Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == 0); + Ruleset.Value = rulesets.AvailableRulesets.First(r => r.OnlineID == 0); }); AddUntilStep("has selection", () => songSelect.Carousel.SelectedBeatmapInfo.Equals(target)); - AddUntilStep("has correct ruleset", () => Ruleset.Value.ID == 0); + AddUntilStep("has correct ruleset", () => Ruleset.Value.OnlineID == 0); // this is an important check, to make sure updateComponentFromBeatmap() was actually run AddUntilStep("selection shown on wedge", () => songSelect.CurrentBeatmapDetailsBeatmap.BeatmapInfo.MatchesOnlineID(target)); @@ -505,7 +505,7 @@ namespace osu.Game.Tests.Visual.SongSelect // special case for converts checked here. return selectedPanel.ChildrenOfType().All(i => - i.IsFiltered || i.Item.BeatmapInfo.Ruleset.ID == targetRuleset || i.Item.BeatmapInfo.Ruleset.ID == 0); + i.IsFiltered || i.Item.BeatmapInfo.Ruleset.OnlineID == targetRuleset || i.Item.BeatmapInfo.Ruleset.OnlineID == 0); }); AddUntilStep("carousel has correct", () => songSelect.Carousel.SelectedBeatmapInfo?.MatchesOnlineID(target) == true); @@ -665,7 +665,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("import multi-ruleset map", () => { - var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray(); + var usableRulesets = rulesets.AvailableRulesets.Where(r => r.OnlineID != 2).ToArray(); manager.Import(createTestBeatmapSet(usableRulesets)).Wait(); }); @@ -676,11 +676,11 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("record set ID", () => previousSetID = ((IBeatmapSetInfo)Beatmap.Value.BeatmapSetInfo).OnlineID); AddAssert("selection changed once", () => changeCount == 1); - AddAssert("Check ruleset is osu!", () => Ruleset.Value.ID == 0); + AddAssert("Check ruleset is osu!", () => Ruleset.Value.OnlineID == 0); changeRuleset(3); - AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.ID == 3); + AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.OnlineID == 3); AddUntilStep("selection changed", () => changeCount > 1); @@ -705,7 +705,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("import multi-ruleset map", () => { - var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray(); + var usableRulesets = rulesets.AvailableRulesets.Where(r => r.OnlineID != 2).ToArray(); manager.Import(createTestBeatmapSet(usableRulesets)).Wait(); }); @@ -720,11 +720,11 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("Find an icon for different ruleset", () => { difficultyIcon = set.ChildrenOfType() - .FirstOrDefault(icon => icon.Item.BeatmapInfo.Ruleset.ID == 3); + .FirstOrDefault(icon => icon.Item.BeatmapInfo.Ruleset.OnlineID == 3); return difficultyIcon != null; }); - AddAssert("Check ruleset is osu!", () => Ruleset.Value.ID == 0); + AddAssert("Check ruleset is osu!", () => Ruleset.Value.OnlineID == 0); int previousSetID = 0; @@ -737,7 +737,7 @@ namespace osu.Game.Tests.Visual.SongSelect InputManager.Click(MouseButton.Left); }); - AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.ID == 3); + AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.OnlineID == 3); AddAssert("Selected beatmap still same set", () => songSelect.Carousel.SelectedBeatmapInfo.BeatmapSet.OnlineID == previousSetID); AddAssert("Selected beatmap is mania", () => Beatmap.Value.BeatmapInfo.Ruleset.OnlineID == 3); @@ -754,7 +754,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("import huge difficulty count map", () => { - var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray(); + var usableRulesets = rulesets.AvailableRulesets.Where(r => r.OnlineID != 2).ToArray(); imported = manager.Import(createTestBeatmapSet(usableRulesets, 50)).Result.Value; }); @@ -771,10 +771,10 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("Find group icon for different ruleset", () => { return (groupIcon = set.ChildrenOfType() - .FirstOrDefault(icon => icon.Items.First().BeatmapInfo.Ruleset.ID == 3)) != null; + .FirstOrDefault(icon => icon.Items.First().BeatmapInfo.Ruleset.OnlineID == 3)) != null; }); - AddAssert("Check ruleset is osu!", () => Ruleset.Value.ID == 0); + AddAssert("Check ruleset is osu!", () => Ruleset.Value.OnlineID == 0); AddStep("Click on group", () => { @@ -783,7 +783,7 @@ namespace osu.Game.Tests.Visual.SongSelect InputManager.Click(MouseButton.Left); }); - AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.ID == 3); + AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.OnlineID == 3); AddAssert("Check first item in group selected", () => Beatmap.Value.BeatmapInfo.MatchesOnlineID(groupIcon.Items.First().BeatmapInfo)); } @@ -817,7 +817,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("wait for results screen presented", () => !songSelect.IsCurrentScreen()); AddAssert("check beatmap is correct for score", () => Beatmap.Value.BeatmapInfo.MatchesOnlineID(getPresentBeatmap())); - AddAssert("check ruleset is correct for score", () => Ruleset.Value.ID == 0); + AddAssert("check ruleset is correct for score", () => Ruleset.Value.OnlineID == 0); } [Test] @@ -849,7 +849,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("wait for results screen presented", () => !songSelect.IsCurrentScreen()); AddAssert("check beatmap is correct for score", () => Beatmap.Value.BeatmapInfo.MatchesOnlineID(getPresentBeatmap())); - AddAssert("check ruleset is correct for score", () => Ruleset.Value.ID == 0); + AddAssert("check ruleset is correct for score", () => Ruleset.Value.OnlineID == 0); } private void waitForInitialSelection() @@ -869,7 +869,7 @@ namespace osu.Game.Tests.Visual.SongSelect private void addRulesetImportStep(int id) => AddStep($"import test map for ruleset {id}", () => importForRuleset(id)); - private void importForRuleset(int id) => manager.Import(createTestBeatmapSet(rulesets.AvailableRulesets.Where(r => r.ID == id).ToArray())).Wait(); + private void importForRuleset(int id) => manager.Import(createTestBeatmapSet(rulesets.AvailableRulesets.Where(r => r.OnlineID == id).ToArray())).Wait(); private static int importId; @@ -880,7 +880,7 @@ namespace osu.Game.Tests.Visual.SongSelect private void changeMods(params Mod[] mods) => AddStep($"change mods to {string.Join(", ", mods.Select(m => m.Acronym))}", () => SelectedMods.Value = mods); - private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == id)); + private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.OnlineID == id)); private void createSongSelect() { @@ -893,7 +893,7 @@ namespace osu.Game.Tests.Visual.SongSelect { AddStep("import test maps", () => { - var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray(); + var usableRulesets = rulesets.AvailableRulesets.Where(r => r.OnlineID != 2).ToArray(); for (int i = 0; i < 100; i += 10) manager.Import(createTestBeatmapSet(usableRulesets)).Wait(); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 4f7aec3b67..f196bbd76e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -378,9 +378,9 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - private void changeRuleset(int? id) + private void changeRuleset(int? onlineId) { - AddStep($"change ruleset to {(id?.ToString() ?? "none")}", () => { Ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault(r => r.ID == id); }); + AddStep($"change ruleset to {(onlineId?.ToString() ?? "none")}", () => { Ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault(r => r.OnlineID == onlineId); }); waitForLoad(); } diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index 3fb9335629..243c39ab53 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -98,7 +98,7 @@ namespace osu.Game.Online.API.Requests.Responses public string MD5Hash => Checksum; - public IRulesetInfo Ruleset => new RulesetInfo { ID = RulesetID }; + public IRulesetInfo Ruleset => new RulesetInfo { OnlineID = RulesetID }; [JsonIgnore] public string Hash => throw new NotImplementedException(); diff --git a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs index d0677eacab..0a2d6ca7b0 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs @@ -146,7 +146,7 @@ namespace osu.Game.Online.API.Requests.Responses return scoreInfo; } - public IRulesetInfo Ruleset => new RulesetInfo { ID = RulesetID }; + public IRulesetInfo Ruleset => new RulesetInfo { OnlineID = RulesetID }; IBeatmapInfo IScoreInfo.Beatmap => Beatmap; } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 31ebcfd600..d279f6d6ee 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -183,7 +183,7 @@ namespace osu.Game.Rulesets { Name = Description, ShortName = ShortName, - ID = (this as ILegacyRuleset)?.LegacyID, + OnlineID = (this as ILegacyRuleset)?.LegacyID ?? -1, InstantiationInfo = GetType().GetInvariantInstantiationInfo(), Available = true, }; From bbd3ea5b7756b8ad2c40a13b1bd276e4e98ba8c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Nov 2021 15:25:49 +0900 Subject: [PATCH 24/27] Update all actual usages of `RulesetInfo.ID` to use `OnlineID` instead --- osu.Desktop/DiscordRichPresence.cs | 5 ++++- .../Beatmaps/Formats/LegacyScoreDecoderTest.cs | 2 +- osu.Game.Tournament/Components/SongBar.cs | 2 +- osu.Game/Beatmaps/BeatmapDifficultyCache.cs | 2 +- osu.Game/Beatmaps/DifficultyRecommender.cs | 2 +- osu.Game/Models/RealmRuleset.cs | 4 ++-- .../API/Requests/SearchBeatmapSetsRequest.cs | 4 ++-- osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs | 2 +- osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs | 2 +- osu.Game/Screens/Play/SoloPlayer.cs | 16 +++++++++------- osu.Game/Screens/Spectate/SpectatorScreen.cs | 2 +- osu.Game/Stores/RealmRulesetStore.cs | 6 +++--- 12 files changed, 27 insertions(+), 22 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index e1e7e6ad18..3642f70a56 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -108,7 +108,10 @@ namespace osu.Desktop presence.Assets.LargeImageText = $"{user.Value.Username}" + (user.Value.Statistics?.GlobalRank > 0 ? $" (rank #{user.Value.Statistics.GlobalRank:N0})" : string.Empty); // update ruleset - presence.Assets.SmallImageKey = ruleset.Value.ID <= 3 ? $"mode_{ruleset.Value.ID}" : "mode_custom"; + int onlineID = ruleset.Value.OnlineID; + bool isLegacyRuleset = onlineID >= 0 && onlineID <= ILegacyRuleset.MAX_LEGACY_RULESET_ID; + + presence.Assets.SmallImageKey = isLegacyRuleset ? $"mode_{onlineID}" : "mode_custom"; presence.Assets.SmallImageText = ruleset.Value.Name; client.SetPresence(presence); diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs index 9c71466489..6e5a546e87 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs @@ -30,7 +30,7 @@ namespace osu.Game.Tests.Beatmaps.Formats { var score = decoder.Parse(resourceStream); - Assert.AreEqual(3, score.ScoreInfo.Ruleset.ID); + Assert.AreEqual(3, score.ScoreInfo.Ruleset.OnlineID); Assert.AreEqual(2, score.ScoreInfo.Statistics[HitResult.Great]); Assert.AreEqual(1, score.ScoreInfo.Statistics[HitResult.Good]); diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index a74b88c592..a7f0d58145 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -127,7 +127,7 @@ namespace osu.Game.Tournament.Components (string heading, string content)[] stats; - switch (ruleset.Value.ID) + switch (ruleset.Value.OnlineID) { default: stats = new (string heading, string content)[] diff --git a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs index 4d44b49218..61717c18d5 100644 --- a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs +++ b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs @@ -349,7 +349,7 @@ namespace osu.Game.Beatmaps var hashCode = new HashCode(); hashCode.Add(BeatmapInfo.ID); - hashCode.Add(Ruleset.ID); + hashCode.Add(Ruleset.ShortName); foreach (var mod in OrderedMods) hashCode.Add(mod); diff --git a/osu.Game/Beatmaps/DifficultyRecommender.cs b/osu.Game/Beatmaps/DifficultyRecommender.cs index a2bd7c6ce9..8b00d0f7f2 100644 --- a/osu.Game/Beatmaps/DifficultyRecommender.cs +++ b/osu.Game/Beatmaps/DifficultyRecommender.cs @@ -83,7 +83,7 @@ namespace osu.Game.Beatmaps requestedUserId = api.LocalUser.Value.Id; // only query API for built-in rulesets - rulesets.AvailableRulesets.Where(ruleset => ruleset.ID <= ILegacyRuleset.MAX_LEGACY_RULESET_ID).ForEach(rulesetInfo => + rulesets.AvailableRulesets.Where(ruleset => ruleset.OnlineID >= 0 && ruleset.OnlineID <= ILegacyRuleset.MAX_LEGACY_RULESET_ID).ForEach(rulesetInfo => { var req = new GetUserRequest(api.LocalUser.Value.Id, rulesetInfo); diff --git a/osu.Game/Models/RealmRuleset.cs b/osu.Game/Models/RealmRuleset.cs index 5c18a10527..9a7488fda2 100644 --- a/osu.Game/Models/RealmRuleset.cs +++ b/osu.Game/Models/RealmRuleset.cs @@ -25,12 +25,12 @@ namespace osu.Game.Models public string InstantiationInfo { get; set; } = string.Empty; - public RealmRuleset(string shortName, string name, string instantiationInfo, int? onlineID = null) + public RealmRuleset(string shortName, string name, string instantiationInfo, int onlineID) { ShortName = shortName; Name = name; InstantiationInfo = instantiationInfo; - OnlineID = onlineID ?? -1; + OnlineID = onlineID; } [UsedImplicitly] diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs index ae082ca82e..736024b08b 100644 --- a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs +++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs @@ -86,8 +86,8 @@ namespace osu.Game.Online.API.Requests if (General != null && General.Any()) req.AddParameter("c", string.Join('.', General.Select(e => e.ToString().Underscore()))); - if (ruleset.ID.HasValue) - req.AddParameter("m", ruleset.ID.Value.ToString()); + if (ruleset.OnlineID >= 0) + req.AddParameter("m", ruleset.OnlineID.ToString()); req.AddParameter("s", SearchCategory.ToString().ToLowerInvariant()); diff --git a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs index 7ac4f90c07..f943422389 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs @@ -140,7 +140,7 @@ namespace osu.Game.Scoring.Legacy int countGeki = score.GetCountGeki() ?? 0; int countKatu = score.GetCountKatu() ?? 0; - switch (score.Ruleset.ID) + switch (score.Ruleset.OnlineID) { case 0: { diff --git a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs index 5769406948..7b8cacb35b 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs @@ -42,7 +42,7 @@ namespace osu.Game.Scoring.Legacy { using (SerializationWriter sw = new SerializationWriter(stream)) { - sw.Write((byte)(score.ScoreInfo.Ruleset.ID ?? 0)); + sw.Write((byte)(score.ScoreInfo.Ruleset.OnlineID)); sw.Write(LATEST_VERSION); sw.Write(score.ScoreInfo.BeatmapInfo.MD5Hash); sw.Write(score.ScoreInfo.UserString); diff --git a/osu.Game/Screens/Play/SoloPlayer.cs b/osu.Game/Screens/Play/SoloPlayer.cs index 6cea75af0a..c8d831ebe6 100644 --- a/osu.Game/Screens/Play/SoloPlayer.cs +++ b/osu.Game/Screens/Play/SoloPlayer.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; +using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Online.Solo; @@ -25,10 +26,13 @@ namespace osu.Game.Screens.Play protected override APIRequest CreateTokenRequest() { - if (!(Beatmap.Value.BeatmapInfo.OnlineID is int beatmapId)) + int beatmapId = Beatmap.Value.BeatmapInfo.OnlineID ?? -1; + int rulesetId = Ruleset.Value.OnlineID; + + if (beatmapId <= 0) return null; - if (!(Ruleset.Value.ID is int rulesetId) || Ruleset.Value.ID > ILegacyRuleset.MAX_LEGACY_RULESET_ID) + if (rulesetId < 0 || rulesetId > ILegacyRuleset.MAX_LEGACY_RULESET_ID) return null; return new CreateSoloScoreRequest(beatmapId, rulesetId, Game.VersionHash); @@ -38,13 +42,11 @@ namespace osu.Game.Screens.Play protected override APIRequest CreateSubmissionRequest(Score score, long token) { - var beatmap = score.ScoreInfo.BeatmapInfo; + IBeatmapInfo beatmap = score.ScoreInfo.BeatmapInfo; - Debug.Assert(beatmap.OnlineID != null); + Debug.Assert(beatmap.OnlineID > 0); - int beatmapId = beatmap.OnlineID.Value; - - return new SubmitSoloScoreRequest(beatmapId, token, score.ScoreInfo); + return new SubmitSoloScoreRequest(beatmap.OnlineID, token, score.ScoreInfo); } } } diff --git a/osu.Game/Screens/Spectate/SpectatorScreen.cs b/osu.Game/Screens/Spectate/SpectatorScreen.cs index 1f07042ede..ca56366927 100644 --- a/osu.Game/Screens/Spectate/SpectatorScreen.cs +++ b/osu.Game/Screens/Spectate/SpectatorScreen.cs @@ -146,7 +146,7 @@ namespace osu.Game.Screens.Spectate var user = userMap[userId]; var spectatorState = playingUserStates[userId]; - var resolvedRuleset = rulesets.AvailableRulesets.FirstOrDefault(r => r.ID == spectatorState.RulesetID)?.CreateInstance(); + var resolvedRuleset = rulesets.AvailableRulesets.FirstOrDefault(r => r.OnlineID == spectatorState.RulesetID)?.CreateInstance(); if (resolvedRuleset == null) return; diff --git a/osu.Game/Stores/RealmRulesetStore.cs b/osu.Game/Stores/RealmRulesetStore.cs index cf9ffd112c..0119aec9a4 100644 --- a/osu.Game/Stores/RealmRulesetStore.cs +++ b/osu.Game/Stores/RealmRulesetStore.cs @@ -117,8 +117,8 @@ namespace osu.Game.Stores // add all legacy rulesets first to ensure they have exclusive choice of primary key. foreach (var r in instances.Where(r => r is ILegacyRuleset)) { - if (realm.All().FirstOrDefault(rr => rr.OnlineID == r.RulesetInfo.ID) == null) - realm.Add(new RealmRuleset(r.RulesetInfo.ShortName, r.RulesetInfo.Name, r.RulesetInfo.InstantiationInfo, r.RulesetInfo.ID)); + if (realm.All().FirstOrDefault(rr => rr.OnlineID == r.RulesetInfo.OnlineID) == null) + realm.Add(new RealmRuleset(r.RulesetInfo.ShortName, r.RulesetInfo.Name, r.RulesetInfo.InstantiationInfo, r.RulesetInfo.OnlineID)); } // add any other rulesets which have assemblies present but are not yet in the database. @@ -136,7 +136,7 @@ namespace osu.Game.Stores existingSameShortName.InstantiationInfo = r.RulesetInfo.InstantiationInfo; } else - realm.Add(new RealmRuleset(r.RulesetInfo.ShortName, r.RulesetInfo.Name, r.RulesetInfo.InstantiationInfo, r.RulesetInfo.ID)); + realm.Add(new RealmRuleset(r.RulesetInfo.ShortName, r.RulesetInfo.Name, r.RulesetInfo.InstantiationInfo, r.RulesetInfo.OnlineID)); } } From 9c61ec217b8a644100419203c9e94b2653f3b784 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 19 Nov 2021 18:47:07 +0900 Subject: [PATCH 25/27] Remove unnecessary `mainTrackMixer` parameter from `BeatmapManager` --- osu.Game/Beatmaps/BeatmapManager.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index c2a2e93caf..8acdc96ac0 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -10,7 +10,6 @@ using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; using osu.Framework.Audio; -using osu.Framework.Audio.Mixing; using osu.Framework.Audio.Track; using osu.Framework.IO.Stores; using osu.Framework.Platform; @@ -40,7 +39,7 @@ namespace osu.Game.Beatmaps private readonly WorkingBeatmapCache workingBeatmapCache; private readonly BeatmapOnlineLookupQueue onlineBeatmapLookupQueue; - public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore gameResources, GameHost host = null, WorkingBeatmap defaultBeatmap = null, bool performOnlineLookups = false, AudioMixer mainTrackMixer = null) + public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore gameResources, GameHost host = null, WorkingBeatmap defaultBeatmap = null, bool performOnlineLookups = false) { var userResources = new FileStore(contextFactory, storage).Store; From 3e0e01abdb6f75ba2d05c0dc9c712160e426d11f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 23 Nov 2021 01:02:22 +0900 Subject: [PATCH 26/27] Move bookmark parsing logic into `LegacyBeatmapDecoder` --- osu.Game/Beatmaps/BeatmapInfo.cs | 23 ------------------- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 6 ++++- 2 files changed, 5 insertions(+), 24 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index d2b322a843..782944c28e 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; using Newtonsoft.Json; using osu.Framework.Testing; using osu.Game.Database; @@ -104,28 +103,6 @@ namespace osu.Game.Beatmaps /// public int CountdownOffset { get; set; } - // Editor - // This bookmarks stuff is necessary because DB doesn't know how to store int[] - [JsonIgnore] - public string StoredBookmarks - { - get => string.Join(',', Bookmarks); - set - { - if (string.IsNullOrEmpty(value)) - { - Bookmarks = Array.Empty(); - return; - } - - Bookmarks = value.Split(',').Select(v => - { - bool result = int.TryParse(v, out int val); - return new { result, val }; - }).Where(p => p.result).Select(p => p.val).ToArray(); - } - } - [NotMapped] public int[] Bookmarks { get; set; } = Array.Empty(); diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 65d050e608..e5db9d045a 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -201,7 +201,11 @@ namespace osu.Game.Beatmaps.Formats switch (pair.Key) { case @"Bookmarks": - beatmap.BeatmapInfo.StoredBookmarks = pair.Value; + beatmap.BeatmapInfo.Bookmarks = pair.Value.Split(',').Select(v => + { + bool result = int.TryParse(v, out int val); + return new { result, val }; + }).Where(p => p.result).Select(p => p.val).ToArray(); break; case @"DistanceSpacing": From 2dabedebffaa87919d1a6593de963a72bdd8e54a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 23 Nov 2021 01:22:19 +0900 Subject: [PATCH 27/27] Remove unnecessary user assign in `HitObjectSampleTest` --- osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs index b87c3d57c2..adb447c927 100644 --- a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs +++ b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs @@ -15,7 +15,6 @@ using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; using osu.Game.IO; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; using osu.Game.Screens.Ranking; @@ -39,10 +38,7 @@ namespace osu.Game.Tests.Beatmaps private readonly BeatmapInfo beatmapInfo = new BeatmapInfo { BeatmapSet = new BeatmapSetInfo(), - Metadata = new BeatmapMetadata - { - Author = APIUser.SYSTEM_USER - } + Metadata = new BeatmapMetadata(), }; private readonly TestResourceStore userSkinResourceStore = new TestResourceStore();