1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 14:17:26 +08:00

Add framestable-bypassing seek for spectator

This commit is contained in:
smoogipoo 2021-06-03 17:27:21 +09:00
parent c787c008a5
commit 420df124b5
4 changed files with 37 additions and 14 deletions

View File

@ -177,6 +177,7 @@ namespace osu.Game.Tests.Visual.Gameplay
public override Container Overlays { get; }
public override Container FrameStableComponents { get; }
public override IFrameStableClock FrameStableClock { get; }
internal override bool FrameStablePlayback { get; set; }
public override IReadOnlyList<Mod> Mods { get; }
public override double GameplayStartTime { get; }

View File

@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.UI
/// <summary>
/// Whether to enable frame-stable playback.
/// </summary>
internal bool FrameStablePlayback
internal override bool FrameStablePlayback
{
get => frameStablePlayback;
set
@ -432,6 +432,8 @@ namespace osu.Game.Rulesets.UI
/// </summary>
public abstract IFrameStableClock FrameStableClock { get; }
internal abstract bool FrameStablePlayback { get; set; }
/// <summary>
/// The mods which are to be applied.
/// </summary>

View File

@ -576,6 +576,24 @@ namespace osu.Game.Screens.Play
/// <param name="time">The destination time to seek to.</param>
public void Seek(double time) => GameplayClockContainer.Seek(time);
/// <summary>
/// Seeks to a specific time in gameplay, bypassing frame stability.
/// </summary>
/// <remarks>
/// Intermediate hitobject judgements may not be applied or reverted correctly during this seek.
/// </remarks>
/// <param name="time">The destination time to seek to.</param>
public void NonFrameStableSeek(double time)
{
bool wasFrameStable = DrawableRuleset.FrameStablePlayback;
DrawableRuleset.FrameStablePlayback = false;
Seek(time);
// Delay resetting frame-stable playback for one frame to give the FrameStabilityContainer a chance to seek.
ScheduleAfterChildren(() => DrawableRuleset.FrameStablePlayback = wasFrameStable);
}
/// <summary>
/// Restart gameplay via a parent <see cref="PlayerLoader"/>.
/// <remarks>This can be called from a child screen in order to trigger the restart process.</remarks>

View File

@ -1,11 +1,9 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Screens;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.Spectator;
@ -50,6 +48,7 @@ namespace osu.Game.Screens.Play
base.LoadComplete();
spectatorClient.OnNewFrames += userSentFrames;
seekToGameplay();
}
private void userSentFrames(int userId, FrameDataBundle bundle)
@ -73,6 +72,20 @@ namespace osu.Game.Screens.Play
score.Replay.Frames.Add(convertedFrame);
}
seekToGameplay();
}
private bool seekedToGameplay;
private void seekToGameplay()
{
if (seekedToGameplay || score.Replay.Frames.Count == 0)
return;
NonFrameStableSeek(score.Replay.Frames[0].Time);
seekedToGameplay = true;
}
protected override ResultsScreen CreateResults(ScoreInfo score)
@ -85,17 +98,6 @@ namespace osu.Game.Screens.Play
DrawableRuleset?.SetReplayScore(score);
}
protected override GameplayClockContainer CreateGameplayClockContainer(WorkingBeatmap beatmap, double gameplayStart)
{
// if we already have frames, start gameplay at the point in time they exist, should they be too far into the beatmap.
double? firstFrameTime = score.Replay.Frames.FirstOrDefault()?.Time;
if (firstFrameTime == null || firstFrameTime <= gameplayStart + 5000)
return base.CreateGameplayClockContainer(beatmap, gameplayStart);
return new MasterGameplayClockContainer(beatmap, firstFrameTime.Value, true);
}
public override bool OnExiting(IScreen next)
{
spectatorClient.OnUserBeganPlaying -= userBeganPlaying;