1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-12 18:23:04 +08:00

Detach and reattach scores to make work

This commit is contained in:
Dean Herbert 2022-01-07 17:27:48 +09:00
parent 60d2de8a3b
commit 2b8706b6ce
7 changed files with 35 additions and 11 deletions

View File

@ -10,6 +10,7 @@ using osu.Game.Beatmaps;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
using osu.Game.Models; using osu.Game.Models;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Scoring;
using Realms; using Realms;
#nullable enable #nullable enable
@ -27,6 +28,7 @@ namespace osu.Game.Database
c.CreateMap<BeatmapMetadata, BeatmapMetadata>(); c.CreateMap<BeatmapMetadata, BeatmapMetadata>();
c.CreateMap<BeatmapDifficulty, BeatmapDifficulty>(); c.CreateMap<BeatmapDifficulty, BeatmapDifficulty>();
c.CreateMap<RulesetInfo, RulesetInfo>(); c.CreateMap<RulesetInfo, RulesetInfo>();
c.CreateMap<ScoreInfo, ScoreInfo>();
c.CreateMap<RealmUser, RealmUser>(); c.CreateMap<RealmUser, RealmUser>();
c.CreateMap<RealmFile, RealmFile>(); c.CreateMap<RealmFile, RealmFile>();
c.CreateMap<RealmNamedFileUsage, RealmNamedFileUsage>(); c.CreateMap<RealmNamedFileUsage, RealmNamedFileUsage>();

View File

@ -502,6 +502,8 @@ namespace osu.Game
return; return;
} }
databasedScoreInfo = databasedScoreInfo.Detach();
var databasedScore = ScoreManager.GetScore(databasedScoreInfo); var databasedScore = ScoreManager.GetScore(databasedScoreInfo);
if (databasedScore.Replay == null) if (databasedScore.Replay == null)

View File

@ -21,7 +21,7 @@ namespace osu.Game.Scoring.Legacy
this.beatmaps = beatmaps; this.beatmaps = beatmaps;
} }
protected override Ruleset GetRuleset(int rulesetId) => rulesets.GetRuleset(rulesetId).CreateInstance(); 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 WorkingBeatmap GetBeatmap(string md5Hash) => beatmaps.GetWorkingBeatmap(beatmaps.QueryBeatmap(b => b.MD5Hash == md5Hash));
} }
} }

View File

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using AutoMapper;
using Newtonsoft.Json; using Newtonsoft.Json;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Framework.Testing; using osu.Framework.Testing;
@ -112,9 +113,16 @@ namespace osu.Game.Scoring
[MapTo(nameof(Rank))] [MapTo(nameof(Rank))]
public int RankInt { get; set; } public int RankInt { get; set; }
[IgnoreMap]
IRulesetInfo IScoreInfo.Ruleset => Ruleset; IRulesetInfo IScoreInfo.Ruleset => Ruleset;
[IgnoreMap]
IBeatmapInfo IScoreInfo.Beatmap => Beatmap; IBeatmapInfo IScoreInfo.Beatmap => Beatmap;
[IgnoreMap]
IUser IScoreInfo.User => User; IUser IScoreInfo.User => User;
[IgnoreMap]
IEnumerable<INamedFileUsage> IHasNamedFiles.Files => Files; IEnumerable<INamedFileUsage> IHasNamedFiles.Files => Files;
#region Properties required to make things work with existing usages #region Properties required to make things work with existing usages

View File

@ -55,6 +55,15 @@ namespace osu.Game.Scoring
public Score GetScore(ScoreInfo score) => new LegacyDatabasedScore(score, rulesets, beatmaps(), Files.Store); 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) 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<BeatmapInfo>(model.Beatmap.ID);
if (!model.Ruleset.IsManaged)
model.Ruleset = realm.Find<RulesetInfo>(model.Ruleset.ShortName);
return Task.CompletedTask;
}
} }
} }

View File

@ -1038,19 +1038,17 @@ namespace osu.Game.Screens.Play
replayReader = new LegacyByteArrayReader(stream.ToArray(), "replay.osr"); 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. // 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. // 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 // 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). // conflicts across various systems (ie. solo and multiplayer).
long onlineScoreId = score.ScoreInfo.OnlineID; importableScore.OnlineID = -1;
score.ScoreInfo.OnlineID = -1; await scoreManager.Import(importableScore, replayReader).ConfigureAwait(false);
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;
} }
/// <summary> /// <summary>

View File

@ -149,7 +149,10 @@ namespace osu.Game.Screens.Select.Leaderboards
{ {
using (var realm = realmFactory.CreateContext()) using (var realm = realmFactory.CreateContext())
{ {
var scores = realm.All<ScoreInfo>().Where(s => !s.DeletePending && s.BeatmapInfo.ID == fetchBeatmapInfo.ID && s.Ruleset.OnlineID == ruleset.Value.ID); var scores = realm.All<ScoreInfo>()
.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()) 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.Where(s => s.Mods.Any(m => selectedMods.Contains(m.Acronym)));
} }
scores = scores.Detach();
scoreManager.OrderByTotalScoreAsync(scores.ToArray(), cancellationToken) scoreManager.OrderByTotalScoreAsync(scores.ToArray(), cancellationToken)
.ContinueWith(ordered => scoresCallback?.Invoke(ordered.Result), TaskContinuationOptions.OnlyOnRanToCompletion); .ContinueWith(ordered => scoresCallback?.Invoke(ordered.Result), TaskContinuationOptions.OnlyOnRanToCompletion);