1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-12 19:03:08 +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.Models;
using osu.Game.Rulesets;
using osu.Game.Scoring;
using Realms;
#nullable enable
@ -27,6 +28,7 @@ namespace osu.Game.Database
c.CreateMap<BeatmapMetadata, BeatmapMetadata>();
c.CreateMap<BeatmapDifficulty, BeatmapDifficulty>();
c.CreateMap<RulesetInfo, RulesetInfo>();
c.CreateMap<ScoreInfo, ScoreInfo>();
c.CreateMap<RealmUser, RealmUser>();
c.CreateMap<RealmFile, RealmFile>();
c.CreateMap<RealmNamedFileUsage, RealmNamedFileUsage>();

View File

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

View File

@ -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));
}
}

View File

@ -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<INamedFileUsage> IHasNamedFiles.Files => Files;
#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);
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");
}
// 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);
}
/// <summary>

View File

@ -149,7 +149,10 @@ namespace osu.Game.Screens.Select.Leaderboards
{
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())
{
@ -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);