1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-13 21:12:55 +08:00

Change the way Score is initialised in Player to better lend to population of metadata

This commit is contained in:
Dean Herbert 2021-06-02 15:44:04 +09:00
parent 45984f035b
commit a15cac6f53
5 changed files with 45 additions and 76 deletions

View File

@ -17,7 +17,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
public class MultiSpectatorPlayer : SpectatorPlayer public class MultiSpectatorPlayer : SpectatorPlayer
{ {
private readonly Bindable<bool> waitingOnFrames = new Bindable<bool>(true); private readonly Bindable<bool> waitingOnFrames = new Bindable<bool>(true);
private readonly Score score;
private readonly ISpectatorPlayerClock spectatorPlayerClock; private readonly ISpectatorPlayerClock spectatorPlayerClock;
/// <summary> /// <summary>
@ -28,7 +27,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
public MultiSpectatorPlayer([NotNull] Score score, [NotNull] ISpectatorPlayerClock spectatorPlayerClock) public MultiSpectatorPlayer([NotNull] Score score, [NotNull] ISpectatorPlayerClock spectatorPlayerClock)
: base(score) : base(score)
{ {
this.score = score;
this.spectatorPlayerClock = spectatorPlayerClock; this.spectatorPlayerClock = spectatorPlayerClock;
} }
@ -43,7 +41,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
base.UpdateAfterChildren(); base.UpdateAfterChildren();
// This is required because the frame stable clock is set to WaitingOnFrames = false for one frame. // This is required because the frame stable clock is set to WaitingOnFrames = false for one frame.
waitingOnFrames.Value = DrawableRuleset.FrameStableClock.WaitingOnFrames.Value || score.Replay.Frames.Count == 0; waitingOnFrames.Value = DrawableRuleset.FrameStableClock.WaitingOnFrames.Value || Score.Replay.Frames.Count == 0;
} }
protected override GameplayClockContainer CreateGameplayClockContainer(WorkingBeatmap beatmap, double gameplayStart) protected override GameplayClockContainer CreateGameplayClockContainer(WorkingBeatmap beatmap, double gameplayStart)

View File

@ -54,11 +54,11 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
return new PlaylistsResultsScreen(score, RoomId.Value.Value, PlaylistItem, true); return new PlaylistsResultsScreen(score, RoomId.Value.Value, PlaylistItem, true);
} }
protected override Score CreateScore() protected override void PrepareScoreForResults()
{ {
var score = base.CreateScore(); base.PrepareScoreForResults();
score.ScoreInfo.TotalScore = (int)Math.Round(ScoreProcessor.GetStandardisedScore());
return score; Score.ScoreInfo.TotalScore = (int)Math.Round(ScoreProcessor.GetStandardisedScore());
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)

View File

@ -6,7 +6,6 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio; using osu.Framework.Audio;
using osu.Framework.Audio.Sample; using osu.Framework.Audio.Sample;
@ -24,10 +23,8 @@ using osu.Game.IO.Archives;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.Spectator; using osu.Game.Online.Spectator;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Game.Replays;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Scoring; using osu.Game.Scoring;
@ -137,6 +134,8 @@ namespace osu.Game.Screens.Play
public readonly PlayerConfiguration Configuration; public readonly PlayerConfiguration Configuration;
protected Score Score { get; private set; }
/// <summary> /// <summary>
/// Create a new player instance. /// Create a new player instance.
/// </summary> /// </summary>
@ -161,22 +160,32 @@ namespace osu.Game.Screens.Play
if (!LoadedBeatmapSuccessfully) if (!LoadedBeatmapSuccessfully)
return; return;
Score = CreateScore();
// ensure the score is in a consistent state with the current player.
Score.ScoreInfo.Beatmap = Beatmap.Value.BeatmapInfo;
Score.ScoreInfo.Ruleset = rulesetInfo;
Score.ScoreInfo.Mods = Mods.Value.ToArray();
PrepareReplay(); PrepareReplay();
ScoreProcessor.NewJudgement += result => ScoreProcessor.PopulateScore(Score.ScoreInfo);
gameActive.BindValueChanged(_ => updatePauseOnFocusLostState(), true); gameActive.BindValueChanged(_ => updatePauseOnFocusLostState(), true);
} }
[CanBeNull]
private Score recordingScore;
/// <summary> /// <summary>
/// Run any recording / playback setup for replays. /// Run any recording / playback setup for replays.
/// </summary> /// </summary>
protected virtual void PrepareReplay() protected virtual void PrepareReplay()
{ {
DrawableRuleset.SetRecordTarget(recordingScore = new Score()); DrawableRuleset.SetRecordTarget(Score);
}
ScoreProcessor.NewJudgement += result => ScoreProcessor.PopulateScore(recordingScore.ScoreInfo); protected virtual void PrepareScoreForResults()
{
// perform one final population to ensure everything is up-to-date.
ScoreProcessor.PopulateScore(Score.ScoreInfo);
} }
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
@ -631,11 +640,11 @@ namespace osu.Game.Screens.Play
prepareScoreForDisplayTask ??= Task.Run(async () => prepareScoreForDisplayTask ??= Task.Run(async () =>
{ {
var score = CreateScore(); PrepareScoreForResults();
try try
{ {
await PrepareScoreForResultsAsync(score).ConfigureAwait(false); await PrepareScoreForResultsAsync(Score).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -644,14 +653,14 @@ namespace osu.Game.Screens.Play
try try
{ {
await ImportScore(score).ConfigureAwait(false); await ImportScore(Score).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Error(ex, "Score import failed!"); Logger.Error(ex, "Score import failed!");
} }
return score.ScoreInfo; return Score.ScoreInfo;
}); });
if (skipStoryboardOutro) if (skipStoryboardOutro)
@ -903,41 +912,19 @@ namespace osu.Game.Screens.Play
} }
/// <summary> /// <summary>
/// Creates the player's <see cref="Score"/>. /// Creates the player's <see cref="Scoring.Score"/>.
/// </summary> /// </summary>
/// <returns>The <see cref="Score"/>.</returns> /// <returns>The <see cref="Scoring.Score"/>.</returns>
protected virtual Score CreateScore() protected virtual Score CreateScore() =>
new Score
{ {
var score = new Score ScoreInfo = new ScoreInfo { User = api.LocalUser.Value },
{
ScoreInfo = new ScoreInfo
{
Beatmap = Beatmap.Value.BeatmapInfo,
Ruleset = rulesetInfo,
Mods = Mods.Value.ToArray(),
}
}; };
if (DrawableRuleset.ReplayScore != null)
{
score.ScoreInfo.User = DrawableRuleset.ReplayScore.ScoreInfo?.User ?? new GuestUser();
score.Replay = DrawableRuleset.ReplayScore.Replay;
}
else
{
score.ScoreInfo.User = api.LocalUser.Value;
score.Replay = new Replay { Frames = recordingScore?.Replay.Frames.ToList() ?? new List<ReplayFrame>() };
}
ScoreProcessor.PopulateScore(score.ScoreInfo);
return score;
}
/// <summary> /// <summary>
/// Imports the player's <see cref="Score"/> to the local database. /// Imports the player's <see cref="Scoring.Score"/> to the local database.
/// </summary> /// </summary>
/// <param name="score">The <see cref="Score"/> to import.</param> /// <param name="score">The <see cref="Scoring.Score"/> to import.</param>
/// <returns>The imported score.</returns> /// <returns>The imported score.</returns>
protected virtual async Task ImportScore(Score score) protected virtual async Task ImportScore(Score score)
{ {
@ -968,9 +955,9 @@ namespace osu.Game.Screens.Play
} }
/// <summary> /// <summary>
/// Prepare the <see cref="Score"/> for display at results. /// Prepare the <see cref="Scoring.Score"/> for display at results.
/// </summary> /// </summary>
/// <param name="score">The <see cref="Score"/> to prepare.</param> /// <param name="score">The <see cref="Scoring.Score"/> to prepare.</param>
/// <returns>A task that prepares the provided score. On completion, the score is assumed to be ready for display.</returns> /// <returns>A task that prepares the provided score. On completion, the score is assumed to be ready for display.</returns>
protected virtual Task PrepareScoreForResultsAsync(Score score) => Task.CompletedTask; protected virtual Task PrepareScoreForResultsAsync(Score score) => Task.CompletedTask;

View File

@ -4,7 +4,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using osu.Framework.Allocation;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
@ -16,8 +15,6 @@ namespace osu.Game.Screens.Play
{ {
public class ReplayPlayer : Player, IKeyBindingHandler<GlobalAction> public class ReplayPlayer : Player, IKeyBindingHandler<GlobalAction>
{ {
protected Score Score { get; private set; }
private readonly Func<IBeatmap, IReadOnlyList<Mod>, Score> createScore; private readonly Func<IBeatmap, IReadOnlyList<Mod>, Score> createScore;
// Disallow replays from failing. (see https://github.com/ppy/osu/issues/6108) // Disallow replays from failing. (see https://github.com/ppy/osu/issues/6108)
@ -34,28 +31,15 @@ namespace osu.Game.Screens.Play
this.createScore = createScore; this.createScore = createScore;
} }
[BackgroundDependencyLoader]
private void load()
{
if (!LoadedBeatmapSuccessfully) return;
Score = createScore(GameplayBeatmap.PlayableBeatmap, Mods.Value);
}
protected override void PrepareReplay() protected override void PrepareReplay()
{ {
DrawableRuleset?.SetReplayScore(Score); DrawableRuleset?.SetReplayScore(Score);
// todo: move to base class along with Score?
ScoreProcessor.NewJudgement += result => ScoreProcessor.PopulateScore(Score.ScoreInfo);
} }
protected override Score CreateScore() protected override Score CreateScore() => createScore(GameplayBeatmap.PlayableBeatmap, Mods.Value);
{
var baseScore = base.CreateScore();
// Since the replay score doesn't contain statistics, we'll pass them through here.
Score.ScoreInfo.HitEvents = baseScore.ScoreInfo.HitEvents;
return Score;
}
// Don't re-import replay scores as they're already present in the database. // Don't re-import replay scores as they're already present in the database.
protected override Task ImportScore(Score score) => Task.CompletedTask; protected override Task ImportScore(Score score) => Task.CompletedTask;

View File

@ -18,6 +18,9 @@ namespace osu.Game.Screens.Play
{ {
private readonly Score score; private readonly Score score;
[Resolved]
private SpectatorClient spectatorClient { get; set; }
protected override bool CheckModsAllowFailure() => false; // todo: better support starting mid-way through beatmap protected override bool CheckModsAllowFailure() => false; // todo: better support starting mid-way through beatmap
public SpectatorPlayer(Score score) public SpectatorPlayer(Score score)
@ -25,13 +28,10 @@ namespace osu.Game.Screens.Play
this.score = score; this.score = score;
} }
protected override ResultsScreen CreateResults(ScoreInfo score) protected override Score CreateScore() => score;
{
return new SpectatorResultsScreen(score);
}
[Resolved] protected override ResultsScreen CreateResults(ScoreInfo score)
private SpectatorClient spectatorClient { get; set; } => new SpectatorResultsScreen(score);
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()