From 2b8706b6ce2762bf6d1130840308a4bb3f6dd905 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Jan 2022 17:27:48 +0900 Subject: [PATCH] Detach and reattach scores to make work --- osu.Game/Database/RealmObjectExtensions.cs | 2 ++ osu.Game/OsuGame.cs | 2 ++ .../Scoring/Legacy/DatabasedLegacyScoreDecoder.cs | 4 ++-- osu.Game/Scoring/ScoreInfo.cs | 8 ++++++++ osu.Game/Scoring/ScoreModelManager.cs | 11 ++++++++++- osu.Game/Screens/Play/Player.cs | 12 +++++------- .../Select/Leaderboards/BeatmapLeaderboard.cs | 7 ++++++- 7 files changed, 35 insertions(+), 11 deletions(-) diff --git a/osu.Game/Database/RealmObjectExtensions.cs b/osu.Game/Database/RealmObjectExtensions.cs index 9d7d08e106..dfa3076448 100644 --- a/osu.Game/Database/RealmObjectExtensions.cs +++ b/osu.Game/Database/RealmObjectExtensions.cs @@ -10,6 +10,7 @@ using osu.Game.Beatmaps; using osu.Game.Input.Bindings; using osu.Game.Models; using osu.Game.Rulesets; +using osu.Game.Scoring; using Realms; #nullable enable @@ -27,6 +28,7 @@ namespace osu.Game.Database c.CreateMap(); c.CreateMap(); c.CreateMap(); + c.CreateMap(); c.CreateMap(); c.CreateMap(); c.CreateMap(); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 8d1eccb7c1..149de9bc76 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -502,6 +502,8 @@ namespace osu.Game return; } + databasedScoreInfo = databasedScoreInfo.Detach(); + var databasedScore = ScoreManager.GetScore(databasedScoreInfo); if (databasedScore.Replay == null) diff --git a/osu.Game/Scoring/Legacy/DatabasedLegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/DatabasedLegacyScoreDecoder.cs index a49eb89ecc..03e13455f0 100644 --- a/osu.Game/Scoring/Legacy/DatabasedLegacyScoreDecoder.cs +++ b/osu.Game/Scoring/Legacy/DatabasedLegacyScoreDecoder.cs @@ -21,7 +21,7 @@ namespace osu.Game.Scoring.Legacy this.beatmaps = beatmaps; } - protected override Ruleset GetRuleset(int rulesetId) => rulesets.GetRuleset(rulesetId).CreateInstance(); - protected override WorkingBeatmap GetBeatmap(string md5Hash) => beatmaps.GetWorkingBeatmap(beatmaps.QueryBeatmap(b => !b.BeatmapSet.DeletePending && b.MD5Hash == md5Hash)); + protected override Ruleset GetRuleset(int rulesetId) => rulesets.GetRuleset(rulesetId)?.CreateInstance(); + protected override WorkingBeatmap GetBeatmap(string md5Hash) => beatmaps.GetWorkingBeatmap(beatmaps.QueryBeatmap(b => b.MD5Hash == md5Hash)); } } diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 65c31951b8..c07f4a4f87 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using AutoMapper; using Newtonsoft.Json; using osu.Framework.Localisation; using osu.Framework.Testing; @@ -112,9 +113,16 @@ namespace osu.Game.Scoring [MapTo(nameof(Rank))] public int RankInt { get; set; } + [IgnoreMap] IRulesetInfo IScoreInfo.Ruleset => Ruleset; + + [IgnoreMap] IBeatmapInfo IScoreInfo.Beatmap => Beatmap; + + [IgnoreMap] IUser IScoreInfo.User => User; + + [IgnoreMap] IEnumerable IHasNamedFiles.Files => Files; #region Properties required to make things work with existing usages diff --git a/osu.Game/Scoring/ScoreModelManager.cs b/osu.Game/Scoring/ScoreModelManager.cs index 81f80df3ad..8f04e50f63 100644 --- a/osu.Game/Scoring/ScoreModelManager.cs +++ b/osu.Game/Scoring/ScoreModelManager.cs @@ -55,6 +55,15 @@ namespace osu.Game.Scoring public Score GetScore(ScoreInfo score) => new LegacyDatabasedScore(score, rulesets, beatmaps(), Files.Store); protected override Task Populate(ScoreInfo model, ArchiveReader? archive, Realm realm, CancellationToken cancellationToken = default) - => Task.CompletedTask; + { + // Ensure the beatmap is not detached. + if (!model.Beatmap.IsManaged) + model.Beatmap = realm.Find(model.Beatmap.ID); + + if (!model.Ruleset.IsManaged) + model.Ruleset = realm.Find(model.Ruleset.ShortName); + + return Task.CompletedTask; + } } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 5a443ec48e..9fc0d70cc0 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -1038,19 +1038,17 @@ namespace osu.Game.Screens.Play replayReader = new LegacyByteArrayReader(stream.ToArray(), "replay.osr"); } + // the import process will re-attach managed beatmap/rulesets to this score. we don't want this for now, so create a temporary copy to import. + var importableScore = score.ScoreInfo.DeepClone(); + // For the time being, online ID responses are not really useful for anything. // In addition, the IDs provided via new (lazer) endpoints are based on a different autoincrement from legacy (stable) scores. // // Until we better define the server-side logic behind this, let's not store the online ID to avoid potential unique constraint // conflicts across various systems (ie. solo and multiplayer). - long onlineScoreId = score.ScoreInfo.OnlineID; + importableScore.OnlineID = -1; - score.ScoreInfo.OnlineID = -1; - - await scoreManager.Import(score.ScoreInfo, replayReader).ConfigureAwait(false); - - // ... And restore the online ID for other processes to handle correctly (e.g. de-duplication for the results screen). - score.ScoreInfo.OnlineID = onlineScoreId; + await scoreManager.Import(importableScore, replayReader).ConfigureAwait(false); } /// diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index f2654cbdee..caa994a98b 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -149,7 +149,10 @@ namespace osu.Game.Screens.Select.Leaderboards { using (var realm = realmFactory.CreateContext()) { - var scores = realm.All().Where(s => !s.DeletePending && s.BeatmapInfo.ID == fetchBeatmapInfo.ID && s.Ruleset.OnlineID == ruleset.Value.ID); + var scores = realm.All() + .AsEnumerable() + // TODO: update to use a realm filter directly (or at least figure out the beatmap part to reduce scope). + .Where(s => !s.DeletePending && s.BeatmapInfo.ID == fetchBeatmapInfo.ID && s.Ruleset.OnlineID == ruleset.Value.ID); if (filterMods && !mods.Value.Any()) { @@ -164,6 +167,8 @@ namespace osu.Game.Screens.Select.Leaderboards scores = scores.Where(s => s.Mods.Any(m => selectedMods.Contains(m.Acronym))); } + scores = scores.Detach(); + scoreManager.OrderByTotalScoreAsync(scores.ToArray(), cancellationToken) .ContinueWith(ordered => scoresCallback?.Invoke(ordered.Result), TaskContinuationOptions.OnlyOnRanToCompletion);